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);
155 static bool qt_paintengine_supports_transformations(QPaintEngine::Type type)
157 return type == QPaintEngine::OpenGL2
158 || type == QPaintEngine::OpenVG
159 || type == QPaintEngine::OpenGL
160 || type == QPaintEngine::CoreGraphics;
164 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
167 case QInternal::Image:
168 case QInternal::Printer:
169 case QInternal::Picture:
170 // can be drawn onto these devices safely from any thread
177 if (QApplication::testAttribute(Qt::AA_X11InitThreads))
180 if (!extraCondition && QThread::currentThread() != qApp->thread()) {
181 qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
190 void QPainterPrivate::checkEmulation()
193 if (extended->flags() & QPaintEngineEx::DoNotEmulate)
196 bool doEmulation = false;
197 if (state->bgMode == Qt::OpaqueMode)
200 const QGradient *bg = state->brush.gradient();
201 if (bg && bg->coordinateMode() > QGradient::LogicalMode)
204 const QGradient *pg = qpen_brush(state->pen).gradient();
205 if (pg && pg->coordinateMode() > QGradient::LogicalMode)
209 if (extended != emulationEngine) {
210 if (!emulationEngine)
211 emulationEngine = new QEmulationPaintEngine(extended);
212 extended = emulationEngine;
213 extended->setState(state);
215 } else if (emulationEngine == extended) {
216 extended = emulationEngine->real_engine;
221 QPainterPrivate::~QPainterPrivate()
223 delete emulationEngine;
224 for (int i=0; i<states.size(); ++i)
232 QTransform QPainterPrivate::viewTransform() const
235 qreal scaleW = qreal(state->vw)/qreal(state->ww);
236 qreal scaleH = qreal(state->vh)/qreal(state->wh);
237 return QTransform(scaleW, 0, 0, scaleH,
238 state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
246 Returns true if using a shared painter; otherwise false.
248 bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
253 if (pdev->devType() != QInternal::Widget)
256 QWidget *widget = static_cast<QWidget *>(pdev);
259 // Someone either called QPainter::setRedirected in the widget's paint event
260 // right before this painter was created (or begin was called) or
261 // sent a paint event directly to the widget.
262 if (!widget->d_func()->redirectDev)
265 QPainter *sp = widget->d_func()->sharedPainter();
266 if (!sp || !sp->isActive())
269 if (sp->paintEngine()->paintDevice() != widget->d_func()->redirectDev)
272 // Check if we're attempting to paint outside a paint event.
273 if (!sp->d_ptr->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent)
274 && !widget->testAttribute(Qt::WA_PaintOutsidePaintEvent)
275 && !widget->testAttribute(Qt::WA_WState_InPaintEvent)) {
277 qWarning("QPainter::begin: Widget painting can only begin as a result of a paintEvent");
281 // Save the current state of the shared painter and assign
282 // the current d_ptr to the shared painter's d_ptr.
284 if (!sp->d_ptr->d_ptrs) {
285 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
286 // redirections within the same paintEvent(), which should be enough
287 // in 99% of all cases). E.g: A renders B which renders C which renders D.
288 sp->d_ptr->d_ptrs_size = 4;
289 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
290 Q_CHECK_PTR(sp->d_ptr->d_ptrs);
291 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
292 // However, to support corner cases we grow the array dynamically if needed.
293 sp->d_ptr->d_ptrs_size <<= 1;
294 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
295 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
297 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
299 q->d_ptr.reset(sp->d_ptr.data());
301 Q_ASSERT(q->d_ptr->state);
303 // Now initialize the painter with correct widget properties.
306 widget->d_func()->redirected(&offset);
307 offset += q->d_ptr->engine->coordinateOffset();
309 // Update system rect.
310 q->d_ptr->state->ww = q->d_ptr->state->vw = widget->width();
311 q->d_ptr->state->wh = q->d_ptr->state->vh = widget->height();
314 if (q->d_ptr->state->WxF) {
315 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix;
316 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
317 q->d_ptr->state->worldMatrix = QTransform();
318 q->d_ptr->state->WxF = false;
320 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
322 q->d_ptr->updateMatrix();
324 QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
325 if (enginePrivate->currentClipWidget == widget) {
326 enginePrivate->systemStateChanged();
330 // Update system transform and clip.
331 enginePrivate->currentClipWidget = widget;
332 enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
336 void QPainterPrivate::detachPainterPrivate(QPainter *q)
338 Q_ASSERT(refcount > 1);
341 QPainterPrivate *original = d_ptrs[--refcount - 1];
343 inDestructor = false;
345 original->inDestructor = true;
346 } else if (!original) {
347 original = new QPainterPrivate(q);
350 d_ptrs[refcount - 1] = 0;
353 q->d_ptr.reset(original);
355 if (emulationEngine) {
356 extended = emulationEngine->real_engine;
357 delete emulationEngine;
363 void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op)
366 if (qt_show_painter_debug_output) {
367 printf("QPainter::drawHelper\n");
371 if (originalPath.isEmpty())
374 QPaintEngine::PaintEngineFeatures gradientStretch =
375 QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
376 | QPaintEngine::ObjectBoundingModeGradients);
378 const bool mustEmulateObjectBoundingModeGradients = extended
379 || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients)
380 && !engine->hasFeature(QPaintEngine::PatternTransform));
382 if (!(state->emulationSpecifier & ~gradientStretch)
383 && !mustEmulateObjectBoundingModeGradients) {
384 drawStretchedGradient(originalPath, op);
386 } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {
387 drawOpaqueBackground(originalPath, op);
393 qreal strokeOffsetX = 0, strokeOffsetY = 0;
395 QPainterPath path = originalPath * state->matrix;
396 QRectF pathBounds = path.boundingRect();
398 bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
400 qreal penWidth = state->pen.widthF();
405 // In case of complex xform
406 if (state->matrix.type() > QTransform::TxScale) {
407 QPainterPathStroker stroker;
408 stroker.setWidth(penWidth);
409 stroker.setJoinStyle(state->pen.joinStyle());
410 stroker.setCapStyle(state->pen.capStyle());
411 QPainterPath stroke = stroker.createStroke(originalPath);
412 strokeBounds = (stroke * state->matrix).boundingRect();
414 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);
415 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);
421 if (!strokeBounds.isEmpty()) {
422 absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
424 absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
425 .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
428 if (q->hasClipping()) {
429 bool hasPerspectiveTransform = false;
430 for (int i = 0; i < state->clipInfo.size(); ++i) {
431 const QPainterClipInfo &info = state->clipInfo.at(i);
432 if (info.matrix.type() == QTransform::TxProject) {
433 hasPerspectiveTransform = true;
437 // avoid mapping QRegions with perspective transforms
438 if (!hasPerspectiveTransform) {
439 // The trick with txinv and invMatrix is done in order to
440 // avoid transforming the clip to logical coordinates, and
441 // then back to device coordinates. This is a problem with
442 // QRegion/QRect based clips, since they use integer
443 // coordinates and converting to/from logical coordinates will
445 bool old_txinv = txinv;
446 QTransform old_invMatrix = invMatrix;
448 invMatrix = QTransform();
449 QPainterPath clipPath = q->clipPath();
450 QRectF r = clipPath.boundingRect().intersected(absPathRect);
451 absPathRect = r.toAlignedRect();
453 invMatrix = old_invMatrix;
457 // qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
458 // devMinX, devMinY, device->width(), device->height());
459 // qDebug() << " - matrix" << state->matrix;
460 // qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
461 // qDebug() << " - path.bounds" << path.boundingRect();
463 if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
466 QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
471 p.d_ptr->helper_device = helper_device;
473 p.setOpacity(state->opacity);
474 p.translate(-absPathRect.x(), -absPathRect.y());
475 p.setTransform(state->matrix, true);
476 p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
477 p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
478 p.setBackground(state->bgBrush);
479 p.setBackgroundMode(state->bgMode);
480 p.setBrushOrigin(state->brushOrigin);
482 p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);
483 p.setRenderHint(QPainter::SmoothPixmapTransform,
484 state->renderHints & QPainter::SmoothPixmapTransform);
486 p.drawPath(originalPath);
489 static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0;
490 if (do_fallback_overlay) {
491 QImage block(8, 8, QImage::Format_ARGB32_Premultiplied);
493 pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
494 pt.drawLine(0, 0, 8, 8);
497 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
499 p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
506 state->matrix = QTransform();
508 extended->transformChanged();
510 state->dirtyFlags |= QPaintEngine::DirtyTransform;
513 engine->drawImage(absPathRect,
515 QRectF(0, 0, absPathRect.width(), absPathRect.height()),
516 Qt::OrderedDither | Qt::OrderedAlphaDither);
520 void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op)
524 q->setBackgroundMode(Qt::TransparentMode);
526 if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
527 q->fillPath(path, state->bgBrush.color());
528 q->fillPath(path, state->brush);
531 if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
532 q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
533 q->strokePath(path, state->pen);
536 q->setBackgroundMode(Qt::OpaqueMode);
539 static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
541 Q_ASSERT(brush.style() >= Qt::LinearGradientPattern
542 && brush.style() <= Qt::ConicalGradientPattern);
544 QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
545 boundingRect.x(), boundingRect.y());
547 QGradient g = *brush.gradient();
548 g.setCoordinateMode(QGradient::LogicalMode);
551 b.setTransform(gradientToUser * b.transform());
555 void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op)
559 const qreal sw = helper_device->width();
560 const qreal sh = helper_device->height();
562 bool changedPen = false;
563 bool changedBrush = false;
564 bool needsFill = false;
566 const QPen pen = state->pen;
567 const QBrush brush = state->brush;
569 const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
570 const QGradient::CoordinateMode brushMode = coordinateMode(brush);
574 // Draw the xformed fill if the brush is a stretch gradient.
575 if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
576 if (brushMode == QGradient::StretchToDeviceMode) {
577 q->setPen(Qt::NoPen);
578 changedPen = pen.style() != Qt::NoPen;
582 const qreal isw = 1.0 / sw;
583 const qreal ish = 1.0 / sh;
584 QTransform inv(isw, 0, 0, ish, 0, 0);
585 engine->drawPath(path * inv);
590 if (brushMode == QGradient::ObjectBoundingMode) {
591 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
592 boundingRect = path.boundingRect();
593 q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
599 if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
600 // Draw the xformed outline if the pen is a stretch gradient.
601 if (penMode == QGradient::StretchToDeviceMode) {
602 q->setPen(Qt::NoPen);
607 engine->drawPath(path);
611 q->setBrush(pen.brush());
615 QPainterPathStroker stroker;
616 stroker.setDashPattern(pen.style());
617 stroker.setWidth(pen.widthF());
618 stroker.setJoinStyle(pen.joinStyle());
619 stroker.setCapStyle(pen.capStyle());
620 stroker.setMiterLimit(pen.miterLimit());
621 QPainterPath stroke = stroker.createStroke(path);
623 const qreal isw = 1.0 / sw;
624 const qreal ish = 1.0 / sh;
625 QTransform inv(isw, 0, 0, ish, 0, 0);
626 engine->drawPath(stroke * inv);
629 if (!needsFill && brush.style() != Qt::NoBrush) {
630 q->setBrush(Qt::NoBrush);
634 if (penMode == QGradient::ObjectBoundingMode) {
635 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
637 // avoid computing the bounding rect twice
638 if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
639 boundingRect = path.boundingRect();
642 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect));
645 } else if (changedPen) {
651 engine->drawPath(path);
653 } else if (needsFill) {
654 if (pen.style() != Qt::NoPen) {
655 q->setPen(Qt::NoPen);
660 engine->drawPath(path);
670 void QPainterPrivate::updateMatrix()
672 state->matrix = state->WxF ? state->worldMatrix : QTransform();
674 state->matrix *= viewTransform();
676 txinv = false; // no inverted matrix
677 state->matrix *= state->redirectionMatrix;
679 extended->transformChanged();
681 state->dirtyFlags |= QPaintEngine::DirtyTransform;
683 // printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
684 // qDebug() << " --- using matrix" << state->matrix << redirection_offset;
688 void QPainterPrivate::updateInvMatrix()
690 Q_ASSERT(txinv == false);
691 txinv = true; // creating inverted matrix
692 invMatrix = state->matrix.inverted();
695 extern bool qt_isExtendedRadialGradient(const QBrush &brush);
697 void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
700 bool linearGradient = false;
701 bool radialGradient = false;
702 bool extendedRadialGradient = false;
703 bool conicalGradient = false;
704 bool patternBrush = false;
706 bool complexXform = false;
710 // Pen and brush properties (we have to check both if one changes because the
711 // one that's unchanged can still be in a state which requires emulation)
712 if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) {
713 // Check Brush stroke emulation
714 if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke))
715 s->emulationSpecifier |= QPaintEngine::BrushStroke;
717 s->emulationSpecifier &= ~QPaintEngine::BrushStroke;
721 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
722 Qt::BrushStyle brushStyle = qbrush_style(s->brush);
723 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
724 alpha = (penBrushStyle != Qt::NoBrush
725 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
726 && !penBrush.isOpaque())
727 || (brushStyle != Qt::NoBrush
728 && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
729 && !s->brush.isOpaque());
730 linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
731 (brushStyle == Qt::LinearGradientPattern));
732 radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
733 (brushStyle == Qt::RadialGradientPattern));
734 extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
735 conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
736 (brushStyle == Qt::ConicalGradientPattern));
737 patternBrush = (((penBrushStyle > Qt::SolidPattern
738 && penBrushStyle < Qt::LinearGradientPattern)
739 || penBrushStyle == Qt::TexturePattern) ||
740 ((brushStyle > Qt::SolidPattern
741 && brushStyle < Qt::LinearGradientPattern)
742 || brushStyle == Qt::TexturePattern));
744 bool penTextureAlpha = false;
745 if (penBrush.style() == Qt::TexturePattern)
746 penTextureAlpha = qHasPixmapTexture(penBrush)
747 ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
748 : penBrush.textureImage().hasAlphaChannel();
749 bool brushTextureAlpha = false;
750 if (s->brush.style() == Qt::TexturePattern) {
751 brushTextureAlpha = qHasPixmapTexture(s->brush)
752 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
753 : s->brush.textureImage().hasAlphaChannel();
755 if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
756 || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
757 && !engine->hasFeature(QPaintEngine::MaskedBrush))
758 s->emulationSpecifier |= QPaintEngine::MaskedBrush;
760 s->emulationSpecifier &= ~QPaintEngine::MaskedBrush;
763 if (s->state() & (QPaintEngine::DirtyHints
764 | QPaintEngine::DirtyOpacity
765 | QPaintEngine::DirtyBackgroundMode)) {
773 qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
775 " - linearGradient: %d\n"
776 " - radialGradient: %d\n"
777 " - conicalGradient: %d\n"
778 " - patternBrush: %d\n"
787 uint(s->renderHints),
792 if (s->state() & QPaintEngine::DirtyTransform) {
793 xform = !s->matrix.isIdentity();
794 complexXform = !s->matrix.isAffine();
795 } else if (s->matrix.type() >= QTransform::TxTranslate) {
797 complexXform = !s->matrix.isAffine();
800 const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone);
801 const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone);
803 const bool patternXform = patternBrush && (xform || brushXform || penXform);
805 // Check alphablending
806 if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend))
807 s->emulationSpecifier |= QPaintEngine::AlphaBlend;
809 s->emulationSpecifier &= ~QPaintEngine::AlphaBlend;
811 // Linear gradient emulation
812 if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill))
813 s->emulationSpecifier |= QPaintEngine::LinearGradientFill;
815 s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
817 // Radial gradient emulation
818 if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
819 s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
821 s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
823 // Conical gradient emulation
824 if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
825 s->emulationSpecifier |= QPaintEngine::ConicalGradientFill;
827 s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill;
830 if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
831 s->emulationSpecifier |= QPaintEngine::PatternBrush;
833 s->emulationSpecifier &= ~QPaintEngine::PatternBrush;
836 if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform))
837 s->emulationSpecifier |= QPaintEngine::PatternTransform;
839 s->emulationSpecifier &= ~QPaintEngine::PatternTransform;
842 if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform))
843 s->emulationSpecifier |= QPaintEngine::PrimitiveTransform;
845 s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform;
847 // Perspective XForms
848 if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform))
849 s->emulationSpecifier |= QPaintEngine::PerspectiveTransform;
851 s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform;
854 if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity))
855 s->emulationSpecifier |= QPaintEngine::ConstantOpacity;
857 s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity;
859 bool gradientStretch = false;
860 bool objectBoundingMode = false;
861 if (linearGradient || conicalGradient || radialGradient) {
862 QGradient::CoordinateMode brushMode = coordinateMode(s->brush);
863 QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush());
865 gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
866 gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
868 objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
869 objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
872 s->emulationSpecifier |= QGradient_StretchToDevice;
874 s->emulationSpecifier &= ~QGradient_StretchToDevice;
876 if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
877 s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients;
879 s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients;
881 // Opaque backgrounds...
882 if (s->bgMode == Qt::OpaqueMode &&
883 (is_pen_transparent(s->pen) || is_brush_transparent(s->brush)))
884 s->emulationSpecifier |= QPaintEngine_OpaqueBackground;
886 s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground;
889 //won't be correct either way because the device can already have
890 // something rendered to it in which case subsequent emulation
891 // on a fully transparent qimage and then blitting the results
892 // won't produce correct results
894 if (state->composition_mode > QPainter::CompositionMode_Xor &&
895 !engine->hasFeature(QPaintEngine::BlendModes))
896 s->emulationSpecifier |= QPaintEngine::BlendModes;
898 s->emulationSpecifier &= ~QPaintEngine::BlendModes;
902 void QPainterPrivate::updateStateImpl(QPainterState *newState)
904 // ### we might have to call QPainter::begin() here...
905 if (!engine->state) {
906 engine->state = newState;
907 engine->setDirty(QPaintEngine::AllDirty);
910 if (engine->state->painter() != newState->painter)
911 // ### this could break with clip regions vs paths.
912 engine->setDirty(QPaintEngine::AllDirty);
914 // Upon restore, revert all changes since last save
915 else if (engine->state != newState)
916 newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
918 // We need to store all changes made so that restore can deal with them
920 newState->changeFlags |= newState->dirtyFlags;
922 updateEmulationSpecifier(newState);
924 // Unset potential dirty background mode
925 newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode
926 | QPaintEngine::DirtyBackground);
928 engine->state = newState;
929 engine->updateState(*newState);
930 engine->clearDirty(QPaintEngine::AllDirty);
934 void QPainterPrivate::updateState(QPainterState *newState)
938 engine->state = newState;
940 } else if (newState->state() || engine->state!=newState) {
941 bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
942 && newState->pen.widthF() == 0;
943 if (setNonCosmeticPen) {
944 // Override the default pen's cosmetic state if the
945 // NonCosmeticDefaultPen render hint is used.
946 QPen oldPen = newState->pen;
947 newState->pen.setWidth(1);
948 newState->pen.setCosmetic(false);
949 newState->dirtyFlags |= QPaintEngine::DirtyPen;
951 updateStateImpl(newState);
953 // Restore the state pen back to its default to preserve visible
955 newState->pen = oldPen;
957 updateStateImpl(newState);
965 \brief The QPainter class performs low-level painting on widgets and
972 QPainter provides highly optimized functions to do most of the
973 drawing GUI programs require. It can draw everything from simple
974 lines to complex shapes like pies and chords. It can also draw
975 aligned text and pixmaps. Normally, it draws in a "natural"
976 coordinate system, but it can also do view and world
977 transformation. QPainter can operate on any object that inherits
978 the QPaintDevice class.
980 The common use of QPainter is inside a widget's paint event:
981 Construct and customize (e.g. set the pen or the brush) the
982 painter. Then draw. Remember to destroy the QPainter object after
983 drawing. For example:
985 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 0
987 The core functionality of QPainter is drawing, but the class also
988 provide several functions that allows you to customize QPainter's
989 settings and its rendering quality, and others that enable
990 clipping. In addition you can control how different shapes are
991 merged together by specifying the painter's composition mode.
993 The isActive() function indicates whether the painter is active. A
994 painter is activated by the begin() function and the constructor
995 that takes a QPaintDevice argument. The end() function, and the
996 destructor, deactivates it.
998 Together with the QPaintDevice and QPaintEngine classes, QPainter
999 form the basis for Qt's paint system. QPainter is the class used
1000 to perform drawing operations. QPaintDevice represents a device
1001 that can be painted on using a QPainter. QPaintEngine provides the
1002 interface that the painter uses to draw onto different types of
1003 devices. If the painter is active, device() returns the paint
1004 device on which the painter paints, and paintEngine() returns the
1005 paint engine that the painter is currently operating on. For more
1006 information, see the \l {Paint System}.
1008 Sometimes it is desirable to make someone else paint on an unusual
1009 QPaintDevice. QPainter supports a static function to do this,
1012 \warning When the paintdevice is a widget, QPainter can only be
1013 used inside a paintEvent() function or in a function called by
1014 paintEvent(); that is unless the Qt::WA_PaintOutsidePaintEvent
1015 widget attribute is set. On Mac OS X and Windows, you can only
1016 paint in a paintEvent() function regardless of this attribute's
1023 There are several settings that you can customize to make QPainter
1024 draw according to your preferences:
1028 \o font() is the font used for drawing text. If the painter
1029 isActive(), you can retrieve information about the currently set
1030 font, and its metrics, using the fontInfo() and fontMetrics()
1031 functions respectively.
1033 \o brush() defines the color or pattern that is used for filling
1036 \o pen() defines the color or stipple that is used for drawing
1037 lines or boundaries.
1039 \o backgroundMode() defines whether there is a background() or
1040 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
1042 \o background() only applies when backgroundMode() is \l
1043 Qt::OpaqueMode and pen() is a stipple. In that case, it
1044 describes the color of the background pixels in the stipple.
1046 \o brushOrigin() defines the origin of the tiled brushes, normally
1047 the origin of widget's background.
1049 \o viewport(), window(), worldTransform() make up the painter's coordinate
1050 transformation system. For more information, see the \l
1051 {Coordinate Transformations} section and the \l {Coordinate
1052 System} documentation.
1054 \o hasClipping() tells whether the painter clips at all. (The paint
1055 device clips, too.) If the painter clips, it clips to clipRegion().
1057 \o layoutDirection() defines the layout direction used by the
1058 painter when drawing text.
1060 \o worldMatrixEnabled() tells whether world transformation is enabled.
1062 \o viewTransformEnabled() tells whether view transformation is
1067 Note that some of these settings mirror settings in some paint
1068 devices, e.g. QWidget::font(). The QPainter::begin() function (or
1069 equivalently the QPainter constructor) copies these attributes
1070 from the paint device.
1072 You can at any time save the QPainter's state by calling the
1073 save() function which saves all the available settings on an
1074 internal stack. The restore() function pops them back.
1078 QPainter provides functions to draw most primitives: drawPoint(),
1079 drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1080 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1081 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
1082 convenience functions, drawRects() and drawLines(), draw the given
1083 number of rectangles or lines in the given array of \l
1084 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1087 The QPainter class also provides the fillRect() function which
1088 fills the given QRect, with the given QBrush, and the eraseRect()
1089 function that erases the area inside the given rectangle.
1091 All of these functions have both integer and floating point
1096 \o \inlineimage qpainter-basicdrawing.png
1098 \bold {Basic Drawing Example}
1100 The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1101 display basic graphics primitives in a variety of styles using the
1106 If you need to draw a complex shape, especially if you need to do
1107 so repeatedly, consider creating a QPainterPath and drawing it
1113 \bold {Painter Paths example}
1115 The QPainterPath class provides a container for painting
1116 operations, enabling graphical shapes to be constructed and
1119 The \l {painting/painterpaths}{Painter Paths} example shows how
1120 painter paths can be used to build complex shapes for rendering.
1122 \o \inlineimage qpainter-painterpaths.png
1125 QPainter also provides the fillPath() function which fills the
1126 given QPainterPath with the given QBrush, and the strokePath()
1127 function that draws the outline of the given path (i.e. strokes
1130 See also the \l {demos/deform}{Vector Deformation} demo which
1131 shows how to use advanced vector techniques to draw text using a
1132 QPainterPath, the \l {demos/gradients}{Gradients} demo which shows
1133 the different types of gradients that are available in Qt, and the \l
1134 {demos/pathstroke}{Path Stroking} demo which shows Qt's built-in
1135 dash patterns and shows how custom patterns can be used to extend
1136 the range of available patterns.
1140 \o \l {demos/deform}{Vector Deformation}
1141 \o \l {demos/gradients}{Gradients}
1142 \o \l {demos/pathstroke}{Path Stroking}
1144 \o \inlineimage qpainter-vectordeformation.png
1145 \o \inlineimage qpainter-gradients.png
1146 \o \inlineimage qpainter-pathstroking.png
1150 There are functions to draw pixmaps/images, namely drawPixmap(),
1151 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1152 produce the same result, except that drawPixmap() is faster
1153 on-screen while drawImage() may be faster on a QPrinter or other
1156 Text drawing is done using drawText(). When you need
1157 fine-grained positioning, boundingRect() tells you where a given
1158 drawText() command will draw.
1160 There is a drawPicture() function that draws the contents of an
1161 entire QPicture. The drawPicture() function is the only function
1162 that disregards all the painter's settings as QPicture has its own
1165 \section1 Rendering Quality
1167 To get the optimal rendering result using QPainter, you should use
1168 the platform independent QImage as paint device; i.e. using QImage
1169 will ensure that the result has an identical pixel representation
1172 The QPainter class also provides a means of controlling the
1173 rendering quality through its RenderHint enum and the support for
1174 floating point precision: All the functions for drawing primitives
1175 has a floating point version. These are often used in combination
1176 with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1180 \o \inlineimage qpainter-concentriccircles.png
1182 \bold {Concentric Circles Example}
1184 The \l {painting/concentriccircles}{Concentric Circles} example
1185 shows the improved rendering quality that can be obtained using
1186 floating point precision and anti-aliasing when drawing custom
1189 The application's main window displays several widgets which are
1190 drawn using the various combinations of precision and
1195 The RenderHint enum specifies flags to QPainter that may or may
1196 not be respected by any given engine. \l
1197 {RenderHint}{QPainter::Antialiasing} indicates that the engine
1198 should antialias edges of primitives if possible, \l
1199 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1200 should antialias text if possible, and the \l
1201 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1202 engine should use a smooth pixmap transformation algorithm.
1203 \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
1204 indicating that the engine should use fragment programs and offscreen
1205 rendering for antialiasing.
1207 The renderHints() function returns a flag that specifies the
1208 rendering hints that are set for this painter. Use the
1209 setRenderHint() function to set or clear the currently set
1212 \section1 Coordinate Transformations
1214 Normally, the QPainter operates on the device's own coordinate
1215 system (usually pixels), but QPainter has good support for
1216 coordinate transformations.
1220 \o nop \o rotate() \o scale() \o translate()
1222 \o \inlineimage qpainter-clock.png
1223 \o \inlineimage qpainter-rotation.png
1224 \o \inlineimage qpainter-scale.png
1225 \o \inlineimage qpainter-translation.png
1228 The most commonly used transformations are scaling, rotation,
1229 translation and shearing. Use the scale() function to scale the
1230 coordinate system by a given offset, the rotate() function to
1231 rotate it clockwise and translate() to translate it (i.e. adding a
1232 given offset to the points). You can also twist the coordinate
1233 system around the origin using the shear() function. See the \l
1234 {demos/affine}{Affine Transformations} demo for a visualization of
1235 a sheared coordinate system.
1237 See also the \l {painting/transformations}{Transformations}
1238 example which shows how transformations influence the way that
1239 QPainter renders graphics primitives. In particular it shows how
1240 the order of transformations affects the result.
1245 \bold {Affine Transformations Demo}
1247 The \l {demos/affine}{Affine Transformations} demo show Qt's
1248 ability to perform affine transformations on painting
1249 operations. The demo also allows the user to experiment with the
1250 transformation operations and see the results immediately.
1252 \o \inlineimage qpainter-affinetransformations.png
1255 All the tranformation operations operate on the transformation
1256 worldTransform(). A matrix transforms a point in the plane to another
1257 point. For more information about the transformation matrix, see
1258 the \l {Coordinate System} and QTransform documentation.
1260 The setWorldTransform() function can replace or add to the currently
1261 set worldTransform(). The resetTransform() function resets any
1262 transformations that were made using translate(), scale(),
1263 shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1264 functions. The deviceTransform() returns the matrix that transforms
1265 from logical coordinates to device coordinates of the platform
1266 dependent paint device. The latter function is only needed when
1267 using platform painting commands on the platform dependent handle,
1268 and the platform does not do transformations nativly.
1270 When drawing with QPainter, we specify points using logical
1271 coordinates which then are converted into the physical coordinates
1272 of the paint device. The mapping of the logical coordinates to the
1273 physical coordinates are handled by QPainter's combinedTransform(), a
1274 combination of viewport() and window() and worldTransform(). The
1275 viewport() represents the physical coordinates specifying an
1276 arbitrary rectangle, the window() describes the same rectangle in
1277 logical coordinates, and the worldTransform() is identical with the
1278 transformation matrix.
1280 See also \l {Coordinate System}
1284 QPainter can clip any drawing operation to a rectangle, a region,
1285 or a vector path. The current clip is available using the
1286 functions clipRegion() and clipPath(). Whether paths or regions are
1287 preferred (faster) depends on the underlying paintEngine(). For
1288 example, the QImage paint engine prefers paths while the X11 paint
1289 engine prefers regions. Setting a clip is done in the painters
1290 logical coordinates.
1292 After QPainter's clipping, the paint device may also clip. For
1293 example, most widgets clip away the pixels used by child widgets,
1294 and most printers clip away an area near the edges of the paper.
1295 This additional clipping is not reflected by the return value of
1296 clipRegion() or hasClipping().
1298 \section1 Composition Modes
1299 \target Composition Modes
1301 QPainter provides the CompositionMode enum which defines the
1302 Porter-Duff rules for digital image compositing; it describes a
1303 model for combining the pixels in one image, the source, with the
1304 pixels in another image, the destination.
1306 The two most common forms of composition are \l
1307 {QPainter::CompositionMode}{Source} and \l
1308 {QPainter::CompositionMode}{SourceOver}. \l
1309 {QPainter::CompositionMode}{Source} is used to draw opaque objects
1310 onto a paint device. In this mode, each pixel in the source
1311 replaces the corresponding pixel in the destination. In \l
1312 {QPainter::CompositionMode}{SourceOver} composition mode, the
1313 source object is transparent and is drawn on top of the
1316 Note that composition transformation operates pixelwise. For that
1317 reason, there is a difference between using the graphic primitive
1318 itself and its bounding rectangle: The bounding rect contains
1319 pixels with alpha == 0 (i.e the pixels surrounding the
1320 primitive). These pixels will overwrite the other image's pixels,
1321 affectively clearing those, while the primitive only overwrites
1326 \o \inlineimage qpainter-compositiondemo.png
1329 \bold {Composition Modes Demo}
1331 The \l {demos/composition}{Composition Modes} demo, available in
1332 Qt's demo directory, allows you to experiment with the various
1333 composition modes and see the results immediately.
1337 \section1 Limitations
1340 If you are using coordinates with Qt's raster-based paint engine, it is
1341 important to note that, while coordinates greater than +/- 2\sup 15 can
1342 be used, any painting performed with coordinates outside this range is not
1343 guaranteed to be shown; the drawing may be clipped. This is due to the
1344 use of \c{short int} in the implementation.
1346 The outlines generated by Qt's stroker are only an approximation when dealing
1347 with curved shapes. It is in most cases impossible to represent the outline of
1348 a bezier curve segment using another bezier curve segment, and so Qt approximates
1349 the curve outlines by using several smaller curves. For performance reasons there
1350 is a limit to how many curves Qt uses for these outlines, and thus when using
1351 large pen widths or scales the outline error increases. To generate outlines with
1352 smaller errors it is possible to use the QPainterPathStroker class, which has the
1353 setCurveThreshold member function which let's the user specify the error tolerance.
1354 Another workaround is to convert the paths to polygons first and then draw the
1357 \section1 Performance
1359 QPainter is a rich framework that allows developers to do a great
1360 variety of graphical operations, such as gradients, composition
1361 modes and vector graphics. And QPainter can do this across a
1362 variety of different hardware and software stacks. Naturally the
1363 underlying combination of hardware and software has some
1364 implications for performance, and ensuring that every single
1365 operation is fast in combination with all the various combinations
1366 of composition modes, brushes, clipping, transformation, etc, is
1367 close to an impossible task because of the number of
1368 permutations. As a compromise we have selected a subset of the
1369 QPainter API and backends, where performance is guaranteed to be as
1370 good as we can sensibly get it for the given combination of
1371 hardware and software.
1373 The backends we focus on as high-performance engines are:
1377 \o Raster - This backend implements all rendering in pure software
1378 and is always used to render into QImages. For optimal performance
1379 only use the format types QImage::Format_ARGB32_Premultiplied,
1380 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1381 including QImage::Format_ARGB32, has significantly worse
1382 performance. This engine is also used by default on Windows and on
1383 QWS. It can be used as default graphics system on any
1384 OS/hardware/software combination by passing \c {-graphicssystem
1385 raster} on the command line
1387 \o OpenGL 2.0 (ES) - This backend is the primary backend for
1388 hardware accelerated graphics. It can be run on desktop machines
1389 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1390 specification. This includes most graphics chips produced in the
1391 last couple of years. The engine can be enabled by using QPainter
1392 onto a QGLWidget or by passing \c {-graphicssystem opengl} on the
1393 command line when the underlying system supports it.
1395 \o OpenVG - This backend implements the Khronos standard for 2D
1396 and Vector Graphics. It is primarily for embedded devices with
1397 hardware support for OpenVG. The engine can be enabled by
1398 passing \c {-graphicssystem openvg} on the command line when
1399 the underlying system supports it.
1403 These operations are:
1407 \o Simple transformations, meaning translation and scaling, pluss
1408 0, 90, 180, 270 degree rotations.
1410 \o \c drawPixmap() in combination with simple transformations and
1411 opacity with non-smooth transformation mode
1412 (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1414 \o Rectangle fills with solid color, two-color linear gradients
1415 and simple transforms.
1417 \o Rectangular clipping with simple transformations and intersect
1420 \o Composition Modes \c QPainter::CompositionMode_Source and
1421 QPainter::CompositionMode_SourceOver
1423 \o Rounded rectangle filling using solid color and two-color
1424 linear gradients fills.
1426 \o 3x3 patched pixmaps, via qDrawBorderPixmap.
1430 This list gives an indication of which features to safely use in
1431 an application where performance is critical. For certain setups,
1432 other operations may be fast too, but before making extensive use
1433 of them, it is recommended to benchmark and verify them on the
1434 system where the software will run in the end. There are also
1435 cases where expensive operations are ok to use, for instance when
1436 the result is cached in a QPixmap.
1438 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
1439 {Drawing Utility Functions}
1443 \enum QPainter::RenderHint
1445 Renderhints are used to specify flags to QPainter that may or
1446 may not be respected by any given engine.
1448 \value Antialiasing Indicates that the engine should antialias
1449 edges of primitives if possible.
1451 \value TextAntialiasing Indicates that the engine should antialias
1452 text if possible. To forcibly disable antialiasing for text, do not
1453 use this hint. Instead, set QFont::NoAntialias on your font's style
1456 \value SmoothPixmapTransform Indicates that the engine should use
1457 a smooth pixmap transformation algorithm (such as bilinear) rather
1458 than nearest neighbor.
1460 \value HighQualityAntialiasing An OpenGL-specific rendering hint
1461 indicating that the engine should use fragment programs and offscreen
1462 rendering for antialiasing.
1464 \value NonCosmeticDefaultPen The engine should interpret pens with a width
1465 of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
1466 pen with a width of 1.
1468 \sa renderHints(), setRenderHint(), {QPainter#Rendering
1469 Quality}{Rendering Quality}, {Concentric Circles Example}
1474 Constructs a painter.
1479 QPainter::QPainter()
1480 : d_ptr(new QPainterPrivate(this))
1485 \fn QPainter::QPainter(QPaintDevice *device)
1487 Constructs a painter that begins painting the paint \a device
1490 This constructor is convenient for short-lived painters, e.g. in a
1491 QWidget::paintEvent() and should be used only once. The
1492 constructor calls begin() for you and the QPainter destructor
1493 automatically calls end().
1495 Here's an example using begin() and end():
1496 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 1
1498 The same example using this constructor:
1499 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 2
1501 Since the constructor cannot provide feedback when the initialization
1502 of the painter failed you should rather use begin() and end() to paint
1503 on external devices, e.g. printers.
1508 QPainter::QPainter(QPaintDevice *pd)
1512 if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1513 d_ptr.reset(new QPainterPrivate(this));
1520 Destroys the painter.
1522 QPainter::~QPainter()
1524 d_ptr->inDestructor = true;
1528 else if (d_ptr->refcount > 1)
1529 d_ptr->detachPainterPrivate(this);
1531 // don't throw anything in the destructor.
1534 // Make sure we haven't messed things up.
1535 Q_ASSERT(d_ptr->inDestructor);
1536 d_ptr->inDestructor = false;
1537 Q_ASSERT(d_ptr->refcount == 1);
1539 free(d_ptr->d_ptrs);
1544 Returns the paint device on which this painter is currently
1545 painting, or 0 if the painter is not active.
1550 QPaintDevice *QPainter::device() const
1552 Q_D(const QPainter);
1553 if (isActive() && d->engine->d_func()->currentClipWidget)
1554 return d->engine->d_func()->currentClipWidget;
1555 return d->original_device;
1559 Returns true if begin() has been called and end() has not yet been
1560 called; otherwise returns false.
1562 \sa begin(), QPaintDevice::paintingActive()
1565 bool QPainter::isActive() const
1567 Q_D(const QPainter);
1572 Initializes the painters pen, background and font to the same as
1573 the given \a widget. This function is called automatically when the
1574 painter is opened on a QWidget.
1576 \sa begin(), {QPainter#Settings}{Settings}
1578 void QPainter::initFrom(const QWidget *widget)
1580 Q_ASSERT_X(widget, "QPainter::initFrom(const QWidget *widget)", "Widget cannot be 0");
1583 qWarning("QPainter::initFrom: Painter not active, aborted");
1587 const QPalette &pal = widget->palette();
1588 d->state->pen = QPen(pal.brush(widget->foregroundRole()), 0);
1589 d->state->bgBrush = pal.brush(widget->backgroundRole());
1590 d->state->deviceFont = QFont(widget->font(), const_cast<QWidget*> (widget));
1591 d->state->font = d->state->deviceFont;
1593 d->extended->penChanged();
1594 } else if (d->engine) {
1595 d->engine->setDirty(QPaintEngine::DirtyPen);
1596 d->engine->setDirty(QPaintEngine::DirtyBrush);
1597 d->engine->setDirty(QPaintEngine::DirtyFont);
1603 Saves the current painter state (pushes the state onto a stack). A
1604 save() must be followed by a corresponding restore(); the end()
1605 function unwinds the stack.
1610 void QPainter::save()
1612 #ifdef QT_DEBUG_DRAW
1613 if (qt_show_painter_debug_output)
1614 printf("QPainter::save()\n");
1618 qWarning("QPainter::save: Painter not active");
1623 d->state = d->extended->createState(d->states.back());
1624 d->extended->setState(d->state);
1626 d->updateState(d->state);
1627 d->state = new QPainterState(d->states.back());
1628 d->engine->state = d->state;
1630 d->states.push_back(d->state);
1634 Restores the current painter state (pops a saved state off the
1640 void QPainter::restore()
1642 #ifdef QT_DEBUG_DRAW
1643 if (qt_show_painter_debug_output)
1644 printf("QPainter::restore()\n");
1647 if (d->states.size()<=1) {
1648 qWarning("QPainter::restore: Unbalanced save/restore");
1650 } else if (!d->engine) {
1651 qWarning("QPainter::restore: Painter not active");
1655 QPainterState *tmp = d->state;
1656 d->states.pop_back();
1657 d->state = d->states.back();
1661 d->checkEmulation();
1662 d->extended->setState(d->state);
1667 // trigger clip update if the clip path/region has changed since
1669 if (!d->state->clipInfo.isEmpty()
1670 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1671 // reuse the tmp state to avoid any extra allocs...
1672 tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1673 tmp->clipOperation = Qt::NoClip;
1674 tmp->clipPath = QPainterPath();
1675 d->engine->updateState(*tmp);
1676 // replay the list of clip states,
1677 for (int i=0; i<d->state->clipInfo.size(); ++i) {
1678 const QPainterClipInfo &info = d->state->clipInfo.at(i);
1679 tmp->matrix = info.matrix;
1680 tmp->matrix *= d->state->redirectionMatrix;
1681 tmp->clipOperation = info.operation;
1682 if (info.clipType == QPainterClipInfo::RectClip) {
1683 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1684 tmp->clipRegion = info.rect;
1685 } else if (info.clipType == QPainterClipInfo::RegionClip) {
1686 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1687 tmp->clipRegion = info.region;
1688 } else { // clipType == QPainterClipInfo::PathClip
1689 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1690 tmp->clipPath = info.path;
1692 d->engine->updateState(*tmp);
1696 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1697 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1698 tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1699 tmp->changeFlags |= QPaintEngine::DirtyTransform;
1702 d->updateState(d->state);
1709 \fn bool QPainter::begin(QPaintDevice *device)
1711 Begins painting the paint \a device and returns true if
1712 successful; otherwise returns false.
1714 Notice that all painter settings (setPen(), setBrush() etc.) are reset
1715 to default values when begin() is called.
1717 The errors that can occur are serious problems, such as these:
1719 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 3
1721 Note that most of the time, you can use one of the constructors
1722 instead of begin(), and that end() is automatically done at
1725 \warning A paint device can only be painted by one painter at a
1728 \warning Painting on a QImage with the format
1729 QImage::Format_Indexed8 is not supported.
1731 \sa end(), QPainter()
1734 static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1743 bool QPainter::begin(QPaintDevice *pd)
1747 if (pd->painters > 0) {
1748 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1752 if (d_ptr->engine) {
1753 qWarning("QPainter::begin: Painter already active");
1757 if (QPainterPrivate::attachPainterPrivate(this, pd))
1762 d->helper_device = pd;
1763 d->original_device = pd;
1764 QPaintDevice *rpd = 0;
1766 QPoint redirectionOffset;
1767 // We know for sure that redirection is broken when the widget is inside
1768 // its paint event, so it's safe to use our hard-coded redirection. However,
1769 // there IS one particular case we still need to support, and that's
1770 // when people call QPainter::setRedirected in the widget's paint event right
1771 // before any painter is created (or QPainter::begin is called). In that
1772 // particular case our hard-coded redirection is restored and the redirection
1773 // is retrieved from QPainter::redirected (as before).
1774 if (pd->devType() == QInternal::Widget)
1775 rpd = static_cast<QWidget *>(pd)->d_func()->redirected(&redirectionOffset);
1778 rpd = redirected(pd, &redirectionOffset);
1783 #ifdef QT_DEBUG_DRAW
1784 if (qt_show_painter_debug_output)
1785 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1788 if (pd->devType() == QInternal::Pixmap)
1789 static_cast<QPixmap *>(pd)->detach();
1790 else if (pd->devType() == QInternal::Image)
1791 static_cast<QImage *>(pd)->detach();
1793 d->engine = pd->paintEngine();
1796 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1802 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1803 if (d->emulationEngine)
1804 d->emulationEngine->real_engine = d->extended;
1806 // Setup new state...
1807 Q_ASSERT(!d->state);
1808 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1809 d->state->painter = this;
1810 d->states.push_back(d->state);
1812 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1813 d->state->brushOrigin = QPointF();
1815 // Slip a painter state into the engine before we do any other operations
1817 d->extended->setState(d->state);
1819 d->engine->state = d->state;
1821 switch (pd->devType()) {
1822 case QInternal::Widget:
1824 const QWidget *widget = static_cast<const QWidget *>(pd);
1827 const bool paintOutsidePaintEvent = widget->testAttribute(Qt::WA_PaintOutsidePaintEvent);
1828 const bool inPaintEvent = widget->testAttribute(Qt::WA_WState_InPaintEvent);
1829 if(!d->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent)
1830 && !paintOutsidePaintEvent && !inPaintEvent) {
1831 qWarning("QPainter::begin: Widget painting can only begin as a "
1832 "result of a paintEvent");
1833 qt_cleanup_painter_state(d);
1837 // Adjust offset for alien widgets painting outside the paint event.
1838 if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
1839 && widget->testAttribute(Qt::WA_WState_Created)) {
1840 const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
1841 d->state->redirectionMatrix.translate(offset.x(), offset.y());
1845 case QInternal::Pixmap:
1847 QPixmap *pm = static_cast<QPixmap *>(pd);
1850 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1851 qt_cleanup_painter_state(d);
1855 if (pm->depth() == 1) {
1856 d->state->pen = QPen(Qt::color1);
1857 d->state->brush = QBrush(Qt::color0);
1861 case QInternal::Image:
1863 QImage *img = static_cast<QImage *>(pd);
1865 if (img->isNull()) {
1866 qWarning("QPainter::begin: Cannot paint on a null image");
1867 qt_cleanup_painter_state(d);
1869 } else if (img->format() == QImage::Format_Indexed8) {
1870 // Painting on indexed8 images is not supported.
1871 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1872 qt_cleanup_painter_state(d);
1875 if (img->depth() == 1) {
1876 d->state->pen = QPen(Qt::color1);
1877 d->state->brush = QBrush(Qt::color0);
1884 if (d->state->ww == 0) // For compat with 3.x painter defaults
1885 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1887 d->engine->setPaintDevice(pd);
1889 bool begun = d->engine->begin(pd);
1891 qWarning("QPainter::begin(): Returned false");
1892 if (d->engine->isActive()) {
1895 qt_cleanup_painter_state(d);
1899 d->engine->setActive(begun);
1902 // Copy painter properties from original paint device,
1903 // required for QPixmap::grabWidget()
1904 if (d->original_device->devType() == QInternal::Widget) {
1905 QWidget *widget = static_cast<QWidget *>(d->original_device);
1908 d->state->layoutDirection = Qt::LayoutDirectionAuto;
1909 // make sure we have a font compatible with the paintdevice
1910 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1913 QRect systemRect = d->engine->systemRect();
1914 if (!systemRect.isEmpty()) {
1915 d->state->ww = d->state->vw = systemRect.width();
1916 d->state->wh = d->state->vh = systemRect.height();
1918 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1919 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1922 const QPoint coordinateOffset = d->engine->coordinateOffset();
1923 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1925 Q_ASSERT(d->engine->isActive());
1927 if (!d->state->redirectionMatrix.isIdentity())
1930 Q_ASSERT(d->engine->isActive());
1931 d->state->renderHints = QPainter::TextAntialiasing;
1932 ++d->device->painters;
1934 d->state->emulationSpecifier = 0;
1940 Ends painting. Any resources used while painting are released. You
1941 don't normally need to call this since it is called by the
1944 Returns true if the painter is no longer active; otherwise returns false.
1946 \sa begin(), isActive()
1949 bool QPainter::end()
1951 #ifdef QT_DEBUG_DRAW
1952 if (qt_show_painter_debug_output)
1953 printf("QPainter::end()\n");
1958 qWarning("QPainter::end: Painter not active, aborted");
1959 qt_cleanup_painter_state(d);
1963 if (d->refcount > 1) {
1964 d->detachPainterPrivate(this);
1970 if (d->engine->isActive()) {
1971 ended = d->engine->end();
1974 --d->device->painters;
1975 if (d->device->painters == 0) {
1976 d->engine->setPaintDevice(0);
1977 d->engine->setActive(false);
1981 if (d->states.size() > 1) {
1982 qWarning("QPainter::end: Painter ended with %d saved states",
1986 if (d->engine->autoDestruct()) {
1990 if (d->emulationEngine) {
1991 delete d->emulationEngine;
1992 d->emulationEngine = 0;
1999 qt_cleanup_painter_state(d);
2006 Returns the paint engine that the painter is currently operating
2007 on if the painter is active; otherwise 0.
2011 QPaintEngine *QPainter::paintEngine() const
2013 Q_D(const QPainter);
2020 Flushes the painting pipeline and prepares for the user issuing commands
2021 directly to the underlying graphics context. Must be followed by a call to
2022 endNativePainting().
2024 Note that only the states the underlying paint engine changes will be reset
2025 to their respective default states. The states we reset may change from
2026 release to release. The following states are currently reset in the OpenGL
2030 \i blending is disabled
2031 \i the depth, stencil and scissor tests are disabled
2032 \i the active texture unit is reset to 0
2033 \i the depth mask, depth function and the clear depth are reset to their
2035 \i the stencil mask, stencil operation and stencil function are reset to
2036 their default values
2037 \i the current color is reset to solid white
2040 If, for example, the OpenGL polygon mode is changed by the user inside a
2041 beginNativePaint()/endNativePainting() block, it will not be reset to the
2042 default state by endNativePainting(). Here is an example that shows
2043 intermixing of painter commands and raw OpenGL commands:
2045 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
2047 \sa endNativePainting()
2049 void QPainter::beginNativePainting()
2053 qWarning("QPainter::beginNativePainting: Painter not active");
2058 d->extended->beginNativePainting();
2064 Restores the painter after manually issuing native painting commands. Lets
2065 the painter restore any native state that it relies on before calling any
2066 other painter commands.
2068 \sa beginNativePainting()
2070 void QPainter::endNativePainting()
2072 Q_D(const QPainter);
2074 qWarning("QPainter::beginNativePainting: Painter not active");
2079 d->extended->endNativePainting();
2081 d->engine->syncState();
2085 Returns the font metrics for the painter if the painter is
2086 active. Otherwise, the return value is undefined.
2088 \sa font(), isActive(), {QPainter#Settings}{Settings}
2091 QFontMetrics QPainter::fontMetrics() const
2093 Q_D(const QPainter);
2095 qWarning("QPainter::fontMetrics: Painter not active");
2096 return QFontMetrics(QFont());
2098 return QFontMetrics(d->state->font);
2103 Returns the font info for the painter if the painter is
2104 active. Otherwise, the return value is undefined.
2106 \sa font(), isActive(), {QPainter#Settings}{Settings}
2109 QFontInfo QPainter::fontInfo() const
2111 Q_D(const QPainter);
2113 qWarning("QPainter::fontInfo: Painter not active");
2114 return QFontInfo(QFont());
2116 return QFontInfo(d->state->font);
2122 Returns the opacity of the painter. The default value is
2126 qreal QPainter::opacity() const
2128 Q_D(const QPainter);
2130 qWarning("QPainter::opacity: Painter not active");
2133 return d->state->opacity;
2139 Sets the opacity of the painter to \a opacity. The value should
2140 be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2141 1.0 is fully opaque.
2143 Opacity set on the painter will apply to all drawing operations
2147 void QPainter::setOpacity(qreal opacity)
2152 qWarning("QPainter::setOpacity: Painter not active");
2156 opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2158 if (opacity == d->state->opacity)
2161 d->state->opacity = opacity;
2164 d->extended->opacityChanged();
2166 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2171 Returns the currently set brush origin.
2173 \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2176 QPoint QPainter::brushOrigin() const
2178 Q_D(const QPainter);
2180 qWarning("QPainter::brushOrigin: Painter not active");
2183 return QPointF(d->state->brushOrigin).toPoint();
2187 \fn void QPainter::setBrushOrigin(const QPointF &position)
2189 Sets the brush origin to \a position.
2191 The brush origin specifies the (0, 0) coordinate of the painter's
2194 Note that while the brushOrigin() was necessary to adopt the
2195 parent's background for a widget in Qt 3, this is no longer the
2196 case since the Qt 4 painter doesn't paint the background unless
2197 you explicitly tell it to do so by setting the widget's \l
2198 {QWidget::autoFillBackground}{autoFillBackground} property to
2201 \sa brushOrigin(), {QPainter#Settings}{Settings}
2204 void QPainter::setBrushOrigin(const QPointF &p)
2207 #ifdef QT_DEBUG_DRAW
2208 if (qt_show_painter_debug_output)
2209 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2213 qWarning("QPainter::setBrushOrigin: Painter not active");
2217 d->state->brushOrigin = p;
2220 d->extended->brushOriginChanged();
2224 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2228 \fn void QPainter::setBrushOrigin(const QPoint &position)
2231 Sets the brush's origin to the given \a position.
2235 \fn void QPainter::setBrushOrigin(int x, int y)
2239 Sets the brush's origin to point (\a x, \a y).
2243 \enum QPainter::CompositionMode
2245 Defines the modes supported for digital image compositing.
2246 Composition modes are used to specify how the pixels in one image,
2247 the source, are merged with the pixel in another image, the
2250 Please note that the bitwise raster operation modes, denoted with
2251 a RasterOp prefix, are only natively supported in the X11 and
2252 raster paint engines. This means that the only way to utilize
2253 these modes on the Mac is via a QImage. The RasterOp denoted blend
2254 modes are \e not supported for pens and brushes with alpha
2255 components. Also, turning on the QPainter::Antialiasing render
2256 hint will effectively disable the RasterOp modes.
2259 \image qpainter-compositionmode1.png
2260 \image qpainter-compositionmode2.png
2262 The most common type is SourceOver (often referred to as just
2263 alpha blending) where the source pixel is blended on top of the
2264 destination pixel in such a way that the alpha component of the
2265 source defines the translucency of the pixel.
2267 When the paint device is a QImage, the image format must be set to
2268 \l {QImage::Format}{Format_ARGB32Premultiplied} or
2269 \l {QImage::Format}{Format_ARGB32} for the composition modes to have
2270 any effect. For performance the premultiplied version is the preferred
2273 When a composition mode is set it applies to all painting
2274 operator, pens, brushes, gradients and pixmap/image drawing.
2276 \value CompositionMode_SourceOver This is the default mode. The
2277 alpha of the source is used to blend the pixel on top of the
2280 \value CompositionMode_DestinationOver The alpha of the
2281 destination is used to blend it on top of the source pixels. This
2282 mode is the inverse of CompositionMode_SourceOver.
2284 \value CompositionMode_Clear The pixels in the destination are
2285 cleared (set to fully transparent) independent of the source.
2287 \value CompositionMode_Source The output is the source
2288 pixel. (This means a basic copy operation and is identical to
2289 SourceOver when the source pixel is opaque).
2291 \value CompositionMode_Destination The output is the destination
2292 pixel. This means that the blending has no effect. This mode is
2293 the inverse of CompositionMode_Source.
2295 \value CompositionMode_SourceIn The output is the source, where
2296 the alpha is reduced by that of the destination.
2298 \value CompositionMode_DestinationIn The output is the
2299 destination, where the alpha is reduced by that of the
2300 source. This mode is the inverse of CompositionMode_SourceIn.
2302 \value CompositionMode_SourceOut The output is the source, where
2303 the alpha is reduced by the inverse of destination.
2305 \value CompositionMode_DestinationOut The output is the
2306 destination, where the alpha is reduced by the inverse of the
2307 source. This mode is the inverse of CompositionMode_SourceOut.
2309 \value CompositionMode_SourceAtop The source pixel is blended on
2310 top of the destination, with the alpha of the source pixel reduced
2311 by the alpha of the destination pixel.
2313 \value CompositionMode_DestinationAtop The destination pixel is
2314 blended on top of the source, with the alpha of the destination
2315 pixel is reduced by the alpha of the destination pixel. This mode
2316 is the inverse of CompositionMode_SourceAtop.
2318 \value CompositionMode_Xor The source, whose alpha is reduced with
2319 the inverse of the destination alpha, is merged with the
2320 destination, whose alpha is reduced by the inverse of the source
2321 alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2323 \value CompositionMode_Plus Both the alpha and color of the source
2324 and destination pixels are added together.
2326 \value CompositionMode_Multiply The output is the source color
2327 multiplied by the destination. Multiplying a color with white
2328 leaves the color unchanged, while multiplying a color
2329 with black produces black.
2331 \value CompositionMode_Screen The source and destination colors
2332 are inverted and then multiplied. Screening a color with white
2333 produces white, whereas screening a color with black leaves the
2336 \value CompositionMode_Overlay Multiplies or screens the colors
2337 depending on the destination color. The destination color is mixed
2338 with the source color to reflect the lightness or darkness of the
2341 \value CompositionMode_Darken The darker of the source and
2342 destination colors is selected.
2344 \value CompositionMode_Lighten The lighter of the source and
2345 destination colors is selected.
2347 \value CompositionMode_ColorDodge The destination color is
2348 brightened to reflect the source color. A black source color
2349 leaves the destination color unchanged.
2351 \value CompositionMode_ColorBurn The destination color is darkened
2352 to reflect the source color. A white source color leaves the
2353 destination color unchanged.
2355 \value CompositionMode_HardLight Multiplies or screens the colors
2356 depending on the source color. A light source color will lighten
2357 the destination color, whereas a dark source color will darken the
2360 \value CompositionMode_SoftLight Darkens or lightens the colors
2361 depending on the source color. Similar to
2362 CompositionMode_HardLight.
2364 \value CompositionMode_Difference Subtracts the darker of the
2365 colors from the lighter. Painting with white inverts the
2366 destination color, whereas painting with black leaves the
2367 destination color unchanged.
2369 \value CompositionMode_Exclusion Similar to
2370 CompositionMode_Difference, but with a lower contrast. Painting
2371 with white inverts the destination color, whereas painting with
2372 black leaves the destination color unchanged.
2374 \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2375 the source and destination pixels (src OR dst).
2377 \value RasterOp_SourceAndDestination Does a bitwise AND operation
2378 on the source and destination pixels (src AND dst).
2380 \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2381 on the source and destination pixels (src XOR dst).
2383 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2384 operation on the source and destination pixels ((NOT src) AND (NOT
2387 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2388 operation on the source and destination pixels ((NOT src) OR (NOT
2391 \value RasterOp_NotSourceXorDestination Does a bitwise operation
2392 where the source pixels are inverted and then XOR'ed with the
2393 destination ((NOT src) XOR dst).
2395 \value RasterOp_NotSource Does a bitwise operation where the
2396 source pixels are inverted (NOT src).
2398 \value RasterOp_NotSourceAndDestination Does a bitwise operation
2399 where the source is inverted and then AND'ed with the destination
2400 ((NOT src) AND dst).
2402 \value RasterOp_SourceAndNotDestination Does a bitwise operation
2403 where the source is AND'ed with the inverted destination pixels
2404 (src AND (NOT dst)).
2406 \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2407 Modes}{Composition Modes}, {Image Composition Example}
2411 Sets the composition mode to the given \a mode.
2413 \warning Only a QPainter operating on a QImage fully supports all
2414 composition modes. The RasterOp modes are supported for X11 as
2415 described in compositionMode().
2417 \sa compositionMode()
2419 void QPainter::setCompositionMode(CompositionMode mode)
2423 qWarning("QPainter::setCompositionMode: Painter not active");
2426 if (d->state->composition_mode == mode)
2429 d->state->composition_mode = mode;
2430 d->extended->compositionModeChanged();
2434 if (mode >= QPainter::RasterOp_SourceOrDestination) {
2435 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2436 qWarning("QPainter::setCompositionMode: "
2437 "Raster operation modes not supported on device");
2440 } else if (mode >= QPainter::CompositionMode_Plus) {
2441 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2442 qWarning("QPainter::setCompositionMode: "
2443 "Blend modes not supported on device");
2446 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2447 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2448 qWarning("QPainter::setCompositionMode: "
2449 "PorterDuff modes not supported on device");
2454 d->state->composition_mode = mode;
2455 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2459 Returns the current composition mode.
2461 \sa CompositionMode, setCompositionMode()
2463 QPainter::CompositionMode QPainter::compositionMode() const
2465 Q_D(const QPainter);
2467 qWarning("QPainter::compositionMode: Painter not active");
2468 return QPainter::CompositionMode_SourceOver;
2470 return d->state->composition_mode;
2474 Returns the current background brush.
2476 \sa setBackground(), {QPainter#Settings}{Settings}
2479 const QBrush &QPainter::background() const
2481 Q_D(const QPainter);
2483 qWarning("QPainter::background: Painter not active");
2484 return d->fakeState()->brush;
2486 return d->state->bgBrush;
2491 Returns true if clipping has been set; otherwise returns false.
2493 \sa setClipping(), {QPainter#Clipping}{Clipping}
2496 bool QPainter::hasClipping() const
2498 Q_D(const QPainter);
2500 qWarning("QPainter::hasClipping: Painter not active");
2503 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2508 Enables clipping if \a enable is true, or disables clipping if \a
2511 \sa hasClipping(), {QPainter#Clipping}{Clipping}
2514 void QPainter::setClipping(bool enable)
2517 #ifdef QT_DEBUG_DRAW
2518 if (qt_show_painter_debug_output)
2519 printf("QPainter::setClipping(), enable=%s, was=%s\n",
2520 enable ? "on" : "off",
2521 hasClipping() ? "on" : "off");
2524 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2528 if (hasClipping() == enable)
2531 // we can't enable clipping if we don't have a clip
2533 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2535 d->state->clipEnabled = enable;
2538 d->extended->clipEnabledChanged();
2542 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2543 d->updateState(d->state);
2548 Returns the currently set clip region. Note that the clip region
2549 is given in logical coordinates.
2551 \warning QPainter does not store the combined clip explicitly as
2552 this is handled by the underlying QPaintEngine, so the path is
2553 recreated on demand and transformed to the current logical
2554 coordinate system. This is potentially an expensive operation.
2556 \sa setClipRegion(), clipPath(), setClipping()
2559 QRegion QPainter::clipRegion() const
2561 Q_D(const QPainter);
2563 qWarning("QPainter::clipRegion: Painter not active");
2568 bool lastWasNothing = true;
2571 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2573 // ### Falcon: Use QPainterPath
2574 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2575 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2576 switch (info.clipType) {
2578 case QPainterClipInfo::RegionClip: {
2579 QTransform matrix = (info.matrix * d->invMatrix);
2580 if (lastWasNothing) {
2581 region = info.region * matrix;
2582 lastWasNothing = false;
2585 if (info.operation == Qt::IntersectClip)
2586 region &= info.region * matrix;
2587 else if (info.operation == Qt::UniteClip)
2588 region |= info.region * matrix;
2589 else if (info.operation == Qt::NoClip) {
2590 lastWasNothing = true;
2593 region = info.region * matrix;
2597 case QPainterClipInfo::PathClip: {
2598 QTransform matrix = (info.matrix * d->invMatrix);
2599 if (lastWasNothing) {
2600 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2601 info.path.fillRule());
2602 lastWasNothing = false;
2605 if (info.operation == Qt::IntersectClip) {
2606 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2607 info.path.fillRule());
2608 } else if (info.operation == Qt::UniteClip) {
2609 region |= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2610 info.path.fillRule());
2611 } else if (info.operation == Qt::NoClip) {
2612 lastWasNothing = true;
2615 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2616 info.path.fillRule());
2621 case QPainterClipInfo::RectClip: {
2622 QTransform matrix = (info.matrix * d->invMatrix);
2623 if (lastWasNothing) {
2624 region = QRegion(info.rect) * matrix;
2625 lastWasNothing = false;
2628 if (info.operation == Qt::IntersectClip) {
2629 // Use rect intersection if possible.
2630 if (matrix.type() <= QTransform::TxScale)
2631 region &= matrix.mapRect(info.rect);
2633 region &= matrix.map(QRegion(info.rect));
2634 } else if (info.operation == Qt::UniteClip) {
2635 region |= QRegion(info.rect) * matrix;
2636 } else if (info.operation == Qt::NoClip) {
2637 lastWasNothing = true;
2640 region = QRegion(info.rect) * matrix;
2645 case QPainterClipInfo::RectFClip: {
2646 QTransform matrix = (info.matrix * d->invMatrix);
2647 if (lastWasNothing) {
2648 region = QRegion(info.rectf.toRect()) * matrix;
2649 lastWasNothing = false;
2652 if (info.operation == Qt::IntersectClip) {
2653 // Use rect intersection if possible.
2654 if (matrix.type() <= QTransform::TxScale)
2655 region &= matrix.mapRect(info.rectf.toRect());
2657 region &= matrix.map(QRegion(info.rectf.toRect()));
2658 } else if (info.operation == Qt::UniteClip) {
2659 region |= QRegion(info.rectf.toRect()) * matrix;
2660 } else if (info.operation == Qt::NoClip) {
2661 lastWasNothing = true;
2664 region = QRegion(info.rectf.toRect()) * matrix;
2674 extern QPainterPath qt_regionToPath(const QRegion ®ion);
2677 Returns the currently clip as a path. Note that the clip path is
2678 given in logical coordinates.
2680 \warning QPainter does not store the combined clip explicitly as
2681 this is handled by the underlying QPaintEngine, so the path is
2682 recreated on demand and transformed to the current logical
2683 coordinate system. This is potentially an expensive operation.
2685 \sa setClipPath(), clipRegion(), setClipping()
2687 QPainterPath QPainter::clipPath() const
2689 Q_D(const QPainter);
2691 // ### Since we do not support path intersections and path unions yet,
2692 // we just use clipRegion() here...
2694 qWarning("QPainter::clipPath: Painter not active");
2695 return QPainterPath();
2698 // No clip, return empty
2699 if (d->state->clipInfo.size() == 0) {
2700 return QPainterPath();
2703 // Update inverse matrix, used below.
2705 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2707 // For the simple case avoid conversion.
2708 if (d->state->clipInfo.size() == 1
2709 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2710 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2711 return d->state->clipInfo.at(0).path * matrix;
2713 } else if (d->state->clipInfo.size() == 1
2714 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2715 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2717 path.addRect(d->state->clipInfo.at(0).rect);
2718 return path * matrix;
2720 // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2721 return qt_regionToPath(clipRegion());
2727 Returns the bounding rectangle of the current clip if there is a clip;
2728 otherwise returns an empty rectangle. Note that the clip region is
2729 given in logical coordinates.
2731 The bounding rectangle is not guaranteed to be tight.
2733 \sa setClipRect(), setClipPath(), setClipRegion()
2738 QRectF QPainter::clipBoundingRect() const
2740 Q_D(const QPainter);
2743 qWarning("QPainter::clipBoundingRect: Painter not active");
2747 // Accumulate the bounding box in device space. This is not 100%
2748 // precise, but it fits within the guarantee and it is resonably
2751 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2753 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2755 if (info.clipType == QPainterClipInfo::RectClip)
2757 else if (info.clipType == QPainterClipInfo::RectFClip)
2759 else if (info.clipType == QPainterClipInfo::RegionClip)
2760 r = info.region.boundingRect();
2762 r = info.path.boundingRect();
2764 r = info.matrix.mapRect(r);
2768 else if (info.operation == Qt::IntersectClip)
2770 else if (info.operation == Qt::UniteClip)
2775 // Map the rectangle back into logical space using the inverse
2778 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2780 return d->invMatrix.mapRect(bounds);
2784 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2786 Enables clipping, and sets the clip region to the given \a
2787 rectangle using the given clip \a operation. The default operation
2788 is to replace the current clip rectangle.
2790 Note that the clip rectangle is specified in logical (painter)
2793 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2795 void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2800 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2801 op = Qt::ReplaceClip;
2804 qWarning("QPainter::setClipRect: Painter not active");
2807 qreal right = rect.x() + rect.width();
2808 qreal bottom = rect.y() + rect.height();
2809 qreal pts[] = { rect.x(), rect.y(),
2813 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2814 d->state->clipEnabled = true;
2815 d->extended->clip(vp, op);
2816 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2817 d->state->clipInfo.clear();
2818 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2819 d->state->clipOperation = op;
2823 if (qreal(int(rect.top())) == rect.top()
2824 && qreal(int(rect.bottom())) == rect.bottom()
2825 && qreal(int(rect.left())) == rect.left()
2826 && qreal(int(rect.right())) == rect.right())
2828 setClipRect(rect.toRect(), op);
2832 if (rect.isEmpty()) {
2833 setClipRegion(QRegion(), op);
2839 setClipPath(path, op);
2843 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2846 Enables clipping, and sets the clip region to the given \a rectangle using the given
2849 void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2854 qWarning("QPainter::setClipRect: Painter not active");
2858 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2859 op = Qt::ReplaceClip;
2862 d->state->clipEnabled = true;
2863 d->extended->clip(rect, op);
2864 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2865 d->state->clipInfo.clear();
2866 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2867 d->state->clipOperation = op;
2871 d->state->clipRegion = rect;
2872 d->state->clipOperation = op;
2873 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2874 d->state->clipInfo.clear();
2875 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2876 d->state->clipEnabled = true;
2877 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2878 d->updateState(d->state);
2882 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2884 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2885 with the given \a width and \a height.
2889 \fn void QPainter::setClipRegion(const QRegion ®ion, Qt::ClipOperation operation)
2891 Sets the clip region to the given \a region using the specified clip
2892 \a operation. The default clip operation is to replace the current
2895 Note that the clip region is given in logical coordinates.
2897 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2899 void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2902 #ifdef QT_DEBUG_DRAW
2903 QRect rect = r.boundingRect();
2904 if (qt_show_painter_debug_output)
2905 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2906 r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2909 qWarning("QPainter::setClipRegion: Painter not active");
2913 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2914 op = Qt::ReplaceClip;
2917 d->state->clipEnabled = true;
2918 d->extended->clip(r, op);
2919 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2920 d->state->clipInfo.clear();
2921 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2922 d->state->clipOperation = op;
2926 d->state->clipRegion = r;
2927 d->state->clipOperation = op;
2928 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2929 d->state->clipInfo.clear();
2930 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2931 d->state->clipEnabled = true;
2932 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2933 d->updateState(d->state);
2940 Sets the transformation matrix to \a matrix and enables transformations.
2942 \note It is advisable to use setWorldTransform() instead of this function to
2943 preserve the properties of perspective transformations.
2945 If \a combine is true, then \a matrix is combined with the current
2946 transformation matrix; otherwise \a matrix replaces the current
2947 transformation matrix.
2949 If \a matrix is the identity matrix and \a combine is false, this
2950 function calls setWorldMatrixEnabled(false). (The identity matrix is the
2951 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2954 The following functions can transform the coordinate system without using
2963 They operate on the painter's worldMatrix() and are implemented like this:
2965 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 4
2967 Note that when using setWorldMatrix() function you should always have
2968 \a combine be true when you are drawing into a QPicture. Otherwise
2969 it may not be possible to replay the picture with additional
2970 transformations; using the translate(), scale(), etc. convenience
2973 For more information about the coordinate system, transformations
2974 and window-viewport conversion, see \l {Coordinate System}.
2976 \sa setWorldTransform(), QTransform
2979 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2981 setWorldTransform(QTransform(matrix), combine);
2988 Returns the world transformation matrix.
2990 It is advisable to use worldTransform() because worldMatrix() does not
2991 preserve the properties of perspective transformations.
2993 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2997 const QMatrix &QPainter::worldMatrix() const
2999 Q_D(const QPainter);
3001 qWarning("QPainter::worldMatrix: Painter not active");
3002 return d->fakeState()->transform.toAffine();
3004 return d->state->worldMatrix.toAffine();
3010 Use setWorldTransform() instead.
3012 \sa setWorldTransform()
3015 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
3017 setWorldTransform(QTransform(matrix), combine);
3023 Use worldTransform() instead.
3025 \sa worldTransform()
3028 const QMatrix &QPainter::matrix() const
3030 return worldMatrix();
3038 Returns the transformation matrix combining the current
3039 window/viewport and world transformation.
3041 It is advisable to use combinedTransform() instead of this
3042 function to preserve the properties of perspective transformations.
3044 \sa setWorldTransform(), setWindow(), setViewport()
3046 QMatrix QPainter::combinedMatrix() const
3048 return combinedTransform().toAffine();
3055 Returns the matrix that transforms from logical coordinates to
3056 device coordinates of the platform dependent paint device.
3058 \note It is advisable to use deviceTransform() instead of this
3059 function to preserve the properties of perspective transformations.
3061 This function is \e only needed when using platform painting
3062 commands on the platform dependent handle (Qt::HANDLE), and the
3063 platform does not do transformations nativly.
3065 The QPaintEngine::PaintEngineFeature enum can be queried to
3066 determine whether the platform performs the transformations or
3069 \sa worldMatrix(), QPaintEngine::hasFeature(),
3071 const QMatrix &QPainter::deviceMatrix() const
3073 Q_D(const QPainter);
3075 qWarning("QPainter::deviceMatrix: Painter not active");
3076 return d->fakeState()->transform.toAffine();
3078 return d->state->matrix.toAffine();
3084 Resets any transformations that were made using translate(), scale(),
3085 shear(), rotate(), setWorldMatrix(), setViewport() and
3088 It is advisable to use resetTransform() instead of this function
3089 to preserve the properties of perspective transformations.
3091 \sa {QPainter#Coordinate Transformations}{Coordinate
3095 void QPainter::resetMatrix()
3104 Enables transformations if \a enable is true, or disables
3105 transformations if \a enable is false. The world transformation
3106 matrix is not changed.
3108 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3109 Transformations}{Coordinate Transformations}
3112 void QPainter::setWorldMatrixEnabled(bool enable)
3115 #ifdef QT_DEBUG_DRAW
3116 if (qt_show_painter_debug_output)
3117 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3121 qWarning("QPainter::setMatrixEnabled: Painter not active");
3124 if (enable == d->state->WxF)
3127 d->state->WxF = enable;
3134 Returns true if world transformation is enabled; otherwise returns
3137 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3140 bool QPainter::worldMatrixEnabled() const
3142 Q_D(const QPainter);
3144 qWarning("QPainter::worldMatrixEnabled: Painter not active");
3147 return d->state->WxF;
3153 Use setWorldMatrixEnabled() instead.
3155 \sa setWorldMatrixEnabled()
3158 void QPainter::setMatrixEnabled(bool enable)
3160 setWorldMatrixEnabled(enable);
3166 Use worldMatrixEnabled() instead
3168 \sa worldMatrixEnabled()
3171 bool QPainter::matrixEnabled() const
3173 return worldMatrixEnabled();
3177 Scales the coordinate system by (\a{sx}, \a{sy}).
3179 \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate
3183 void QPainter::scale(qreal sx, qreal sy)
3185 #ifdef QT_DEBUG_DRAW
3186 if (qt_show_painter_debug_output)
3187 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3191 qWarning("QPainter::scale: Painter not active");
3195 d->state->worldMatrix.scale(sx,sy);
3196 d->state->WxF = true;
3201 Shears the coordinate system by (\a{sh}, \a{sv}).
3203 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3207 void QPainter::shear(qreal sh, qreal sv)
3209 #ifdef QT_DEBUG_DRAW
3210 if (qt_show_painter_debug_output)
3211 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3215 qWarning("QPainter::shear: Painter not active");
3219 d->state->worldMatrix.shear(sh, sv);
3220 d->state->WxF = true;
3225 \fn void QPainter::rotate(qreal angle)
3227 Rotates the coordinate system the given \a angle clockwise.
3229 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3233 void QPainter::rotate(qreal a)
3235 #ifdef QT_DEBUG_DRAW
3236 if (qt_show_painter_debug_output)
3237 printf("QPainter::rotate(), angle=%f\n", a);
3241 qWarning("QPainter::rotate: Painter not active");
3245 d->state->worldMatrix.rotate(a);
3246 d->state->WxF = true;
3251 Translates the coordinate system by the given \a offset; i.e. the
3252 given \a offset is added to points.
3254 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3257 void QPainter::translate(const QPointF &offset)
3259 qreal dx = offset.x();
3260 qreal dy = offset.y();
3261 #ifdef QT_DEBUG_DRAW
3262 if (qt_show_painter_debug_output)
3263 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3267 qWarning("QPainter::translate: Painter not active");
3271 d->state->worldMatrix.translate(dx, dy);
3272 d->state->WxF = true;
3277 \fn void QPainter::translate(const QPoint &offset)
3280 Translates the coordinate system by the given \a offset.
3284 \fn void QPainter::translate(qreal dx, qreal dy)
3287 Translates the coordinate system by the vector (\a dx, \a dy).
3291 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3293 Enables clipping, and sets the clip path for the painter to the
3294 given \a path, with the clip \a operation.
3296 Note that the clip path is specified in logical (painter)
3299 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3302 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3304 #ifdef QT_DEBUG_DRAW
3305 if (qt_show_painter_debug_output) {
3306 QRectF b = path.boundingRect();
3307 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3308 path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3314 qWarning("QPainter::setClipPath: Painter not active");
3318 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
3319 op = Qt::ReplaceClip;
3322 d->state->clipEnabled = true;
3323 d->extended->clip(path, op);
3324 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3325 d->state->clipInfo.clear();
3326 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3327 d->state->clipOperation = op;
3331 d->state->clipPath = path;
3332 d->state->clipOperation = op;
3333 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3334 d->state->clipInfo.clear();
3335 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3336 d->state->clipEnabled = true;
3337 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3338 d->updateState(d->state);
3342 Draws the outline (strokes) the path \a path with the pen specified
3345 \sa fillPath(), {QPainter#Drawing}{Drawing}
3347 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3352 qWarning("QPainter::strokePath: Painter not active");
3360 const QGradient *g = qpen_brush(pen).gradient();
3361 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3362 d->extended->stroke(qtVectorPathForPath(path), pen);
3367 QBrush oldBrush = d->state->brush;
3368 QPen oldPen = d->state->pen;
3371 setBrush(Qt::NoBrush);
3381 Fills the given \a path using the given \a brush. The outline is
3384 Alternatively, you can specify a QColor instead of a QBrush; the
3385 QBrush constructor (taking a QColor argument) will automatically
3386 create a solid pattern brush.
3390 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3395 qWarning("QPainter::fillPath: Painter not active");
3403 const QGradient *g = brush.gradient();
3404 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3405 d->extended->fill(qtVectorPathForPath(path), brush);
3410 QBrush oldBrush = d->state->brush;
3411 QPen oldPen = d->state->pen;
3424 Draws the given painter \a path using the current pen for outline
3425 and the current brush for filling.
3429 \o \inlineimage qpainter-path.png
3431 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 5
3434 \sa {painting/painterpaths}{the Painter Paths
3435 example},{demos/deform}{the Vector Deformation demo}
3437 void QPainter::drawPath(const QPainterPath &path)
3439 #ifdef QT_DEBUG_DRAW
3440 QRectF pathBounds = path.boundingRect();
3441 if (qt_show_painter_debug_output)
3442 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3443 path.elementCount(),
3444 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3450 qWarning("QPainter::drawPath: Painter not active");
3455 d->extended->drawPath(path);
3458 d->updateState(d->state);
3460 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3461 d->engine->drawPath(path);
3463 d->draw_helper(path);
3468 \fn void QPainter::drawLine(const QLineF &line)
3470 Draws a line defined by \a line.
3474 \o \inlineimage qpainter-line.png
3476 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 6
3479 \sa drawLines(), drawPolyline(), {Coordinate System}
3483 \fn void QPainter::drawLine(const QLine &line)
3486 Draws a line defined by \a line.
3490 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3493 Draws a line from \a p1 to \a p2.
3497 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3500 Draws a line from \a p1 to \a p2.
3504 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3507 Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3508 current pen position to (\a x2, \a y2).
3512 \fn void QPainter::drawRect(const QRectF &rectangle)
3514 Draws the current \a rectangle with the current pen and brush.
3516 A filled rectangle has a size of \a{rectangle}.size(). A stroked
3517 rectangle has a size of \a{rectangle}.size() plus the pen width.
3521 \o \inlineimage qpainter-rectangle.png
3523 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 7
3526 \sa drawRects(), drawPolygon(), {Coordinate System}
3530 \fn void QPainter::drawRect(const QRect &rectangle)
3534 Draws the current \a rectangle with the current pen and brush.
3538 \fn void QPainter::drawRect(int x, int y, int width, int height)
3542 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3543 with the given \a width and \a height.
3547 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3549 Draws the first \a rectCount of the given \a rectangles using the
3550 current pen and brush.
3554 void QPainter::drawRects(const QRectF *rects, int rectCount)
3556 #ifdef QT_DEBUG_DRAW
3557 if (qt_show_painter_debug_output)
3558 printf("QPainter::drawRects(), count=%d\n", rectCount);
3563 qWarning("QPainter::drawRects: Painter not active");
3571 d->extended->drawRects(rects, rectCount);
3575 d->updateState(d->state);
3577 if (!d->state->emulationSpecifier) {
3578 d->engine->drawRects(rects, rectCount);
3582 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3583 && d->state->matrix.type() == QTransform::TxTranslate) {
3584 for (int i=0; i<rectCount; ++i) {
3585 QRectF r(rects[i].x() + d->state->matrix.dx(),
3586 rects[i].y() + d->state->matrix.dy(),
3589 d->engine->drawRects(&r, 1);
3592 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3593 for (int i=0; i<rectCount; ++i) {
3594 QPainterPath rectPath;
3595 rectPath.addRect(rects[i]);
3596 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3599 QPainterPath rectPath;
3600 for (int i=0; i<rectCount; ++i)
3601 rectPath.addRect(rects[i]);
3602 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3608 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3611 Draws the first \a rectCount of the given \a rectangles using the
3612 current pen and brush.
3614 void QPainter::drawRects(const QRect *rects, int rectCount)
3616 #ifdef QT_DEBUG_DRAW
3617 if (qt_show_painter_debug_output)
3618 printf("QPainter::drawRects(), count=%d\n", rectCount);
3623 qWarning("QPainter::drawRects: Painter not active");
3631 d->extended->drawRects(rects, rectCount);
3635 d->updateState(d->state);
3637 if (!d->state->emulationSpecifier) {
3638 d->engine->drawRects(rects, rectCount);
3642 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3643 && d->state->matrix.type() == QTransform::TxTranslate) {
3644 for (int i=0; i<rectCount; ++i) {
3645 QRectF r(rects[i].x() + d->state->matrix.dx(),
3646 rects[i].y() + d->state->matrix.dy(),
3650 d->engine->drawRects(&r, 1);
3653 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3654 for (int i=0; i<rectCount; ++i) {
3655 QPainterPath rectPath;
3656 rectPath.addRect(rects[i]);
3657 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3660 QPainterPath rectPath;
3661 for (int i=0; i<rectCount; ++i)
3662 rectPath.addRect(rects[i]);
3664 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3670 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3673 Draws the given \a rectangles using the current pen and brush.
3677 \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3681 Draws the given \a rectangles using the current pen and brush.
3685 \fn void QPainter::drawPoint(const QPointF &position)
3687 Draws a single point at the given \a position using the current
3690 \sa {Coordinate System}
3694 \fn void QPainter::drawPoint(const QPoint &position)
3697 Draws a single point at the given \a position using the current
3701 /*! \fn void QPainter::drawPoint(int x, int y)
3705 Draws a single point at position (\a x, \a y).
3709 Draws the first \a pointCount points in the array \a points using
3710 the current pen's color.
3712 \sa {Coordinate System}
3714 void QPainter::drawPoints(const QPointF *points, int pointCount)
3716 #ifdef QT_DEBUG_DRAW
3717 if (qt_show_painter_debug_output)
3718 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3723 qWarning("QPainter::drawPoints: Painter not active");
3727 if (pointCount <= 0)
3731 d->extended->drawPoints(points, pointCount);
3735 d->updateState(d->state);
3737 if (!d->state->emulationSpecifier) {
3738 d->engine->drawPoints(points, pointCount);
3742 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3743 && d->state->matrix.type() == QTransform::TxTranslate) {
3744 // ### use drawPoints function
3745 for (int i=0; i<pointCount; ++i) {
3746 QPointF pt(points[i].x() + d->state->matrix.dx(),
3747 points[i].y() + d->state->matrix.dy());
3748 d->engine->drawPoints(&pt, 1);
3751 QPen pen = d->state->pen;
3752 bool flat_pen = pen.capStyle() == Qt::FlatCap;
3755 pen.setCapStyle(Qt::SquareCap);
3759 for (int i=0; i<pointCount; ++i) {
3760 path.moveTo(points[i].x(), points[i].y());
3761 path.lineTo(points[i].x() + 0.0001, points[i].y());
3763 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3772 Draws the first \a pointCount points in the array \a points using
3773 the current pen's color.
3776 void QPainter::drawPoints(const QPoint *points, int pointCount)
3778 #ifdef QT_DEBUG_DRAW
3779 if (qt_show_painter_debug_output)
3780 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3785 qWarning("QPainter::drawPoints: Painter not active");
3789 if (pointCount <= 0)
3793 d->extended->drawPoints(points, pointCount);
3797 d->updateState(d->state);
3799 if (!d->state->emulationSpecifier) {
3800 d->engine->drawPoints(points, pointCount);
3804 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3805 && d->state->matrix.type() == QTransform::TxTranslate) {
3806 // ### use drawPoints function
3807 for (int i=0; i<pointCount; ++i) {
3808 QPointF pt(points[i].x() + d->state->matrix.dx(),
3809 points[i].y() + d->state->matrix.dy());
3810 d->engine->drawPoints(&pt, 1);
3813 QPen pen = d->state->pen;
3814 bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3817 pen.setCapStyle(Qt::SquareCap);
3821 for (int i=0; i<pointCount; ++i) {
3822 path.moveTo(points[i].x(), points[i].y());
3823 path.lineTo(points[i].x() + 0.0001, points[i].y());
3825 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3832 \fn void QPainter::drawPoints(const QPolygonF &points)
3836 Draws the points in the vector \a points.
3840 \fn void QPainter::drawPoints(const QPolygon &points)
3844 Draws the points in the vector \a points.
3848 \fn void QPainter::drawPoints(const QPolygon &polygon, int index,
3854 Draws \a count points in the vector \a polygon starting on \a index
3855 using the current pen.
3857 Use drawPoints() combined with QPolygon::constData() instead.
3860 QPainter painter(this);
3861 painter.drawPoints(polygon, index, count);
3863 int pointCount = (count == -1) ? polygon.size() - index : count;
3865 QPainter painter(this);
3866 painter.drawPoints(polygon.constData() + index, pointCount);
3871 Sets the background mode of the painter to the given \a mode
3873 Qt::TransparentMode (the default) draws stippled lines and text
3874 without setting the background pixels. Qt::OpaqueMode fills these
3875 space with the current background color.
3877 Note that in order to draw a bitmap or pixmap transparently, you
3878 must use QPixmap::setMask().
3880 \sa backgroundMode(), setBackground(),
3881 {QPainter#Settings}{Settings}
3884 void QPainter::setBackgroundMode(Qt::BGMode mode)
3886 #ifdef QT_DEBUG_DRAW
3887 if (qt_show_painter_debug_output)
3888 printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3893 qWarning("QPainter::setBackgroundMode: Painter not active");
3896 if (d->state->bgMode == mode)
3899 d->state->bgMode = mode;
3901 d->checkEmulation();
3903 d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3908 Returns the current background mode.
3910 \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3912 Qt::BGMode QPainter::backgroundMode() const
3914 Q_D(const QPainter);
3916 qWarning("QPainter::backgroundMode: Painter not active");
3917 return Qt::TransparentMode;
3919 return d->state->bgMode;
3926 Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3930 void QPainter::setPen(const QColor &color)
3932 #ifdef QT_DEBUG_DRAW
3933 if (qt_show_painter_debug_output)
3934 printf("QPainter::setPen(), color=%04x\n", color.rgb());
3938 qWarning("QPainter::setPen: Painter not active");
3942 if (d->state->pen.style() == Qt::SolidLine
3943 && d->state->pen.widthF() == 0
3944 && d->state->pen.isSolid()
3945 && d->state->pen.color() == color)
3948 QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
3950 d->state->pen = pen;
3952 d->extended->penChanged();
3954 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3958 Sets the painter's pen to be the given \a pen.
3960 The \a pen defines how to draw lines and outlines, and it also
3961 defines the text color.
3963 \sa pen(), {QPainter#Settings}{Settings}
3966 void QPainter::setPen(const QPen &pen)
3969 #ifdef QT_DEBUG_DRAW
3970 if (qt_show_painter_debug_output)
3971 printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3972 pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3976 qWarning("QPainter::setPen: Painter not active");
3980 if (d->state->pen == pen)
3983 d->state->pen = pen;
3986 d->checkEmulation();
3987 d->extended->penChanged();
3991 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3997 Sets the painter's pen to have the given \a style, width 0 and
4001 void QPainter::setPen(Qt::PenStyle style)
4005 qWarning("QPainter::setPen: Painter not active");
4009 if (d->state->pen.style() == style
4010 && (style == Qt::NoPen || (d->state->pen.widthF() == 0
4011 && d->state->pen.isSolid()
4012 && d->state->pen.color() == QColor(Qt::black))))
4015 // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
4016 // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
4017 d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
4020 d->extended->penChanged();
4022 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
4027 Returns the painter's current pen.
4029 \sa setPen(), {QPainter#Settings}{Settings}
4032 const QPen &QPainter::pen() const
4034 Q_D(const QPainter);
4036 qWarning("QPainter::pen: Painter not active");
4037 return d->fakeState()->pen;
4039 return d->state->pen;
4044 Sets the painter's brush to the given \a brush.
4046 The painter's brush defines how shapes are filled.
4048 \sa brush(), {QPainter#Settings}{Settings}
4051 void QPainter::setBrush(const QBrush &brush)
4053 #ifdef QT_DEBUG_DRAW
4054 if (qt_show_painter_debug_output)
4055 printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
4059 qWarning("QPainter::setBrush: Painter not active");
4063 if (d->state->brush.d == brush.d)
4067 d->state->brush = brush;
4068 d->checkEmulation();
4069 d->extended->brushChanged();
4073 d->state->brush = brush;
4074 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4081 Sets the painter's brush to black color and the specified \a
4085 void QPainter::setBrush(Qt::BrushStyle style)
4089 qWarning("QPainter::setBrush: Painter not active");
4092 if (d->state->brush.style() == style &&
4093 (style == Qt::NoBrush
4094 || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
4096 d->state->brush = QBrush(Qt::black, style);
4098 d->extended->brushChanged();
4100 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4104 Returns the painter's current brush.
4106 \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
4109 const QBrush &QPainter::brush() const
4111 Q_D(const QPainter);
4113 qWarning("QPainter::brush: Painter not active");
4114 return d->fakeState()->brush;
4116 return d->state->brush;
4120 \fn void QPainter::setBackground(const QBrush &brush)
4122 Sets the background brush of the painter to the given \a brush.
4124 The background brush is the brush that is filled in when drawing
4125 opaque text, stippled lines and bitmaps. The background brush has
4126 no effect in transparent background mode (which is the default).
4128 \sa background(), setBackgroundMode(),
4129 {QPainter#Settings}{Settings}
4132 void QPainter::setBackground(const QBrush &bg)
4134 #ifdef QT_DEBUG_DRAW
4135 if (qt_show_painter_debug_output)
4136 printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4141 qWarning("QPainter::setBackground: Painter not active");
4144 d->state->bgBrush = bg;
4146 d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4150 Sets the painter's font to the given \a font.
4152 This font is used by subsequent drawText() functions. The text
4153 color is the same as the pen color.
4155 If you set a font that isn't available, Qt finds a close match.
4156 font() will return what you set using setFont() and fontInfo() returns the
4157 font actually being used (which may be the same).
4159 \sa font(), drawText(), {QPainter#Settings}{Settings}
4162 void QPainter::setFont(const QFont &font)
4166 #ifdef QT_DEBUG_DRAW
4167 if (qt_show_painter_debug_output)
4168 printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4172 qWarning("QPainter::setFont: Painter not active");
4176 d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4178 d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4182 Returns the currently set font used for drawing text.
4184 \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4186 const QFont &QPainter::font() const
4188 Q_D(const QPainter);
4190 qWarning("QPainter::font: Painter not active");
4191 return d->fakeState()->font;
4193 return d->state->font;
4199 Draws the given rectangle \a rect with rounded corners.
4201 The \a xRadius and \a yRadius arguments specify the radii
4202 of the ellipses defining the corners of the rounded rectangle.
4203 When \a mode is Qt::RelativeSize, \a xRadius and
4204 \a yRadius are specified in percentage of half the rectangle's
4205 width and height respectively, and should be in the range
4208 A filled rectangle has a size of rect.size(). A stroked rectangle
4209 has a size of rect.size() plus the pen width.
4213 \o \inlineimage qpainter-roundrect.png
4215 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 8
4218 \sa drawRect(), QPen
4220 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4222 #ifdef QT_DEBUG_DRAW
4223 if (qt_show_painter_debug_output)
4224 printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4231 if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
4237 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4242 path.addRoundedRect(rect, xRadius, yRadius, mode);
4247 \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4248 Qt::SizeMode mode = Qt::AbsoluteSize);
4252 Draws the given rectangle \a rect with rounded corners.
4256 \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4257 Qt::SizeMode mode = Qt::AbsoluteSize);
4261 Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4267 Draws a rectangle \a r with rounded corners.
4269 The \a xRnd and \a yRnd arguments specify how rounded the corners
4270 should be. 0 is angled corners, 99 is maximum roundedness.
4272 A filled rectangle has a size of r.size(). A stroked rectangle
4273 has a size of r.size() plus the pen width.
4275 \sa drawRoundedRect()
4277 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4279 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4284 \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4289 Draws the rectangle \a r with rounded corners.
4295 \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4299 Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4303 \fn void QPainter::drawEllipse(const QRectF &rectangle)
4305 Draws the ellipse defined by the given \a rectangle.
4307 A filled ellipse has a size of \a{rectangle}.\l
4308 {QRect::size()}{size()}. A stroked ellipse has a size of
4309 \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4313 \o \inlineimage qpainter-ellipse.png
4315 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 9
4318 \sa drawPie(), {Coordinate System}
4320 void QPainter::drawEllipse(const QRectF &r)
4322 #ifdef QT_DEBUG_DRAW
4323 if (qt_show_painter_debug_output)
4324 printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4331 QRectF rect(r.normalized());
4334 d->extended->drawEllipse(rect);
4338 d->updateState(d->state);
4339 if (d->state->emulationSpecifier) {
4340 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4341 && d->state->matrix.type() == QTransform::TxTranslate) {
4342 rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4345 path.addEllipse(rect);
4346 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4351 d->engine->drawEllipse(rect);
4355 \fn QPainter::drawEllipse(const QRect &rectangle)
4359 Draws the ellipse defined by the given \a rectangle.
4361 void QPainter::drawEllipse(const QRect &r)
4363 #ifdef QT_DEBUG_DRAW
4364 if (qt_show_painter_debug_output)
4365 printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4372 QRect rect(r.normalized());
4375 d->extended->drawEllipse(rect);
4379 d->updateState(d->state);
4381 if (d->state->emulationSpecifier) {
4382 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4383 && d->state->matrix.type() == QTransform::TxTranslate) {
4384 rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4387 path.addEllipse(rect);
4388 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4393 d->engine->drawEllipse(rect);
4397 \fn QPainter::drawEllipse(int x, int y, int width, int height)
4401 Draws the ellipse defined by the rectangle beginning at (\a{x},
4402 \a{y}) with the given \a width and \a height.
4408 \fn QPainter::drawEllipse(const QPointF ¢er, qreal rx, qreal ry)
4412 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4418 \fn QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)
4422 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4426 \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4428 Draws the arc defined by the given \a rectangle, \a startAngle and
4431 The \a startAngle and \a spanAngle must be specified in 1/16th of
4432 a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4433 values for the angles mean counter-clockwise while negative values
4434 mean the clockwise direction. Zero degrees is at the 3 o'clock
4439 \o \inlineimage qpainter-arc.png
4441 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 10
4444 \sa drawPie(), drawChord(), {Coordinate System}
4447 void QPainter::drawArc(const QRectF &r, int a, int alen)
4449 #ifdef QT_DEBUG_DRAW
4450 if (qt_show_painter_debug_output)
4451 printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4452 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4459 QRectF rect = r.normalized();
4462 path.arcMoveTo(rect, a/16.0);
4463 path.arcTo(rect, a/16.0, alen/16.0);
4464 strokePath(path, d->state->pen);
4467 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4472 Draws the arc defined by the given \a rectangle, \a startAngle and
4477 \fn void QPainter::drawArc(int x, int y, int width, int height,
4478 int startAngle, int spanAngle)
4482 Draws the arc defined by the rectangle beginning at (\a x, \a y)
4483 with the specified \a width and \a height, and the given \a
4484 startAngle and \a spanAngle.
4488 \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4490 Draws a pie defined by the given \a rectangle, \a startAngle and
4493 The pie is filled with the current brush().
4495 The startAngle and spanAngle must be specified in 1/16th of a
4496 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4497 for the angles mean counter-clockwise while negative values mean
4498 the clockwise direction. Zero degrees is at the 3 o'clock
4503 \o \inlineimage qpainter-pie.png
4505 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 11
4508 \sa drawEllipse(), drawChord(), {Coordinate System}
4510 void QPainter::drawPie(const QRectF &r, int a, int alen)
4512 #ifdef QT_DEBUG_DRAW
4513 if (qt_show_painter_debug_output)
4514 printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4515 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4526 if (a < 0) a += (360*16);
4529 QRectF rect = r.normalized();
4532 path.moveTo(rect.center());
4533 path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4534 path.closeSubpath();
4540 \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4543 Draws a pie defined by the given \a rectangle, \a startAngle and
4548 \fn void QPainter::drawPie(int x, int y, int width, int height, int
4549 startAngle, int spanAngle)
4553 Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4554 the specified \a width and \a height, and the given \a startAngle and
4559 \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4561 Draws the chord defined by the given \a rectangle, \a startAngle and
4562 \a spanAngle. The chord is filled with the current brush().
4564 The startAngle and spanAngle must be specified in 1/16th of a
4565 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4566 for the angles mean counter-clockwise while negative values mean
4567 the clockwise direction. Zero degrees is at the 3 o'clock
4572 \o \inlineimage qpainter-chord.png
4574 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 12
4577 \sa drawArc(), drawPie(), {Coordinate System}
4579 void QPainter::drawChord(const QRectF &r, int a, int alen)
4581 #ifdef QT_DEBUG_DRAW
4582 if (qt_show_painter_debug_output)
4583 printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4584 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4591 QRectF rect = r.normalized();
4594 path.arcMoveTo(rect, a/16.0);
4595 path.arcTo(rect, a/16.0, alen/16.0);
4596 path.closeSubpath();
4600 \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4604 Draws the chord defined by the given \a rectangle, \a startAngle and
4609 \fn void QPainter::drawChord(int x, int y, int width, int height, int
4610 startAngle, int spanAngle)
4614 Draws the chord defined by the rectangle beginning at (\a x, \a y)
4615 with the specified \a width and \a height, and the given \a
4616 startAngle and \a spanAngle.
4621 \fn void QPainter::drawLineSegments(const QPolygon &polygon, int
4624 Draws \a count separate lines from points defined by the \a
4625 polygon, starting at \a{polygon}\e{[index]} (\a index defaults to
4626 0). If \a count is -1 (the default) all points until the end of
4629 Use drawLines() combined with QPolygon::constData() instead.
4632 QPainter painter(this);
4633 painter.drawLineSegments(polygon, index, count);
4635 int lineCount = (count == -1) ? (polygon.size() - index) / 2 : count;
4637 QPainter painter(this);
4638 painter.drawLines(polygon.constData() + index * 2, lineCount);
4642 void QPainter::drawLineSegments(const QPolygon &a, int index, int nlines)
4644 #ifdef QT_DEBUG_DRAW
4645 if (qt_show_painter_debug_output)
4646 printf("QPainter::drawLineSegments(), count=%d\n", a.size()/2);
4654 nlines = a.size()/2 - index/2;
4655 if (index + nlines*2 > (int)a.size())
4656 nlines = (a.size() - index)/2;
4657 if (nlines < 1 || index < 0)
4661 // FALCON: Use QVectorPath
4662 QVector<QLineF> lines;
4663 for (int i=index; i<index + nlines*2; i+=2)
4664 lines << QLineF(a.at(i), a.at(i+1));
4665 d->extended->drawLines(lines.data(), lines.size());
4669 d->updateState(d->state);
4671 QVector<QLineF> lines;
4672 if (d->state->emulationSpecifier) {
4673 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4674 && d->state->matrix.type() == QTransform::TxTranslate) {
4675 QPointF offset(d->state->matrix.dx(), d->state->matrix.dy());
4676 for (int i=index; i<index + nlines*2; i+=2)
4677 lines << QLineF(a.at(i) + offset, a.at(i+1) + offset);
4679 QPainterPath linesPath;
4680 for (int i=index; i<index + nlines*2; i+=2) {
4681 linesPath.moveTo(a.at(i));
4682 linesPath.lineTo(a.at(i+1));
4684 d->draw_helper(linesPath, QPainterPrivate::StrokeDraw);
4688 for (int i=index; i<index + nlines*2; i+=2)
4689 lines << QLineF(a.at(i), a.at(i+1));
4692 d->engine->drawLines(lines.data(), lines.size());
4694 #endif // QT3_SUPPORT
4697 Draws the first \a lineCount lines in the array \a lines
4698 using the current pen.
4700 \sa drawLine(), drawPolyline()
4702 void QPainter::drawLines(const QLineF *lines, int lineCount)
4704 #ifdef QT_DEBUG_DRAW
4705 if (qt_show_painter_debug_output)
4706 printf("QPainter::drawLines(), line count=%d\n", lineCount);
4711 if (!d->engine || lineCount < 1)
4715 d->extended->drawLines(lines, lineCount);
4719 d->updateState(d->state);
4721 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4723 if (lineEmulation) {
4724 if (lineEmulation == QPaintEngine::PrimitiveTransform
4725 && d->state->matrix.type() == QTransform::TxTranslate) {
4726 for (int i = 0; i < lineCount; ++i) {
4727 QLineF line = lines[i];
4728 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4729 d->engine->drawLines(&line, 1);
4732 QPainterPath linePath;
4733 for (int i = 0; i < lineCount; ++i) {
4734 linePath.moveTo(lines[i].p1());
4735 linePath.lineTo(lines[i].p2());
4737 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4741 d->engine->drawLines(lines, lineCount);
4745 \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4748 Draws the first \a lineCount lines in the array \a lines
4749 using the current pen.
4751 void QPainter::drawLines(const QLine *lines, int lineCount)
4753 #ifdef QT_DEBUG_DRAW
4754 if (qt_show_painter_debug_output)
4755 printf("QPainter::drawLine(), line count=%d\n", lineCount);
4760 if (!d->engine || lineCount < 1)
4764 d->extended->drawLines(lines, lineCount);
4768 d->updateState(d->state);
4770 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4772 if (lineEmulation) {
4773 if (lineEmulation == QPaintEngine::PrimitiveTransform
4774 && d->state->matrix.type() == QTransform::TxTranslate) {
4775 for (int i = 0; i < lineCount; ++i) {
4776 QLineF line = lines[i];
4777 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4778 d->engine->drawLines(&line, 1);
4781 QPainterPath linePath;
4782 for (int i = 0; i < lineCount; ++i) {
4783 linePath.moveTo(lines[i].p1());
4784 linePath.lineTo(lines[i].p2());
4786 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4790 d->engine->drawLines(lines, lineCount);
4796 Draws the first \a lineCount lines in the array \a pointPairs
4797 using the current pen. The lines are specified as pairs of points
4798 so the number of entries in \a pointPairs must be at least \a
4801 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4803 Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4805 drawLines((QLineF*)pointPairs, lineCount);
4811 Draws the first \a lineCount lines in the array \a pointPairs
4812 using the current pen.
4814 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4816 Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4818 drawLines((QLine*)pointPairs, lineCount);
4823 \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4826 Draws a line for each pair of points in the vector \a pointPairs
4827 using the current pen. If there is an odd number of points in the
4828 array, the last point will be ignored.
4832 \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4835 Draws a line for each pair of points in the vector \a pointPairs
4836 using the current pen.
4840 \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4843 Draws the set of lines defined by the list \a lines using the
4844 current pen and brush.
4848 \fn void QPainter::drawLines(const QVector<QLine> &lines)
4851 Draws the set of lines defined by the list \a lines using the
4852 current pen and brush.
4856 Draws the polyline defined by the first \a pointCount points in \a
4857 points using the current pen.
4859 Note that unlike the drawPolygon() function the last point is \e
4860 not connected to the first, neither is the polyline filled.
4865 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 13
4868 \sa drawLines(), drawPolygon(), {Coordinate System}
4870 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4872 #ifdef QT_DEBUG_DRAW
4873 if (qt_show_painter_debug_output)
4874 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4878 if (!d->engine || pointCount < 2)
4882 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4886 d->updateState(d->state);
4888 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4890 if (lineEmulation) {
4892 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4893 // && d->state->matrix.type() == QTransform::TxTranslate) {
4895 QPainterPath polylinePath(points[0]);
4896 for (int i=1; i<pointCount; ++i)
4897 polylinePath.lineTo(points[i]);
4898 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4901 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4908 Draws the polyline defined by the first \a pointCount points in \a
4909 points using the current pen.
4911 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4913 #ifdef QT_DEBUG_DRAW
4914 if (qt_show_painter_debug_output)
4915 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4919 if (!d->engine || pointCount < 2)
4923 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4927 d->updateState(d->state);
4929 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4931 if (lineEmulation) {
4933 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4934 // && d->state->matrix.type() == QTransform::TxTranslate) {
4936 QPainterPath polylinePath(points[0]);
4937 for (int i=1; i<pointCount; ++i)
4938 polylinePath.lineTo(points[i]);
4939 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4942 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4947 \fn void QPainter::drawPolyline(const QPolygon &polygon, int index, int
4953 Draws the polyline defined by the \a count lines of the given \a
4954 polygon starting at \a index (\a index defaults to 0).
4956 Use drawPolyline() combined with QPolygon::constData() instead.
4959 QPainter painter(this);
4960 painter.drawPolyline(polygon, index, count);
4962 int pointCount = (count == -1) ? polygon.size() - index : count;
4964 QPainter painter(this);
4965 painter.drawPolyline(polygon.constData() + index, pointCount);
4970 \fn void QPainter::drawPolyline(const QPolygonF &points)
4974 Draws the polyline defined by the given \a points using the
4979 \fn void QPainter::drawPolyline(const QPolygon &points)
4983 Draws the polyline defined by the given \a points using the
4988 Draws the polygon defined by the first \a pointCount points in the
4989 array \a points using the current pen and brush.
4993 \o \inlineimage qpainter-polygon.png
4995 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 14
4998 The first point is implicitly connected to the last point, and the
4999 polygon is filled with the current brush().
5001 If \a fillRule is Qt::WindingFill, the polygon is filled using the
5002 winding fill algorithm. If \a fillRule is Qt::OddEvenFill, the
5003 polygon is filled using the odd-even fill algorithm. See
5004 \l{Qt::FillRule} for a more detailed description of these fill
5007 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
5009 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
5011 #ifdef QT_DEBUG_DRAW
5012 if (qt_show_painter_debug_output)
5013 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
5018 if (!d->engine || pointCount < 2)
5022 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5026 d->updateState(d->state);
5028 uint emulationSpecifier = d->state->emulationSpecifier;
5030 if (emulationSpecifier) {
5031 QPainterPath polygonPath(points[0]);
5032 for (int i=1; i<pointCount; ++i)
5033 polygonPath.lineTo(points[i]);
5034 polygonPath.closeSubpath();
5035 polygonPath.setFillRule(fillRule);
5036 d->draw_helper(polygonPath);
5040 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5045 Draws the polygon defined by the first \a pointCount points in the
5048 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
5050 #ifdef QT_DEBUG_DRAW
5051 if (qt_show_painter_debug_output)
5052 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
5057 if (!d->engine || pointCount < 2)
5061 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5065 d->updateState(d->state);
5067 uint emulationSpecifier = d->state->emulationSpecifier;
5069 if (emulationSpecifier) {
5070 QPainterPath polygonPath(points[0]);
5071 for (int i=1; i<pointCount; ++i)
5072 polygonPath.lineTo(points[i]);
5073 polygonPath.closeSubpath();
5074 polygonPath.setFillRule(fillRule);
5075 d->draw_helper(polygonPath);
5079 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5082 /*! \fn void QPainter::drawPolygon(const QPolygonF &polygon, bool winding, int index = 0,
5087 Use drawPolygon() combined with QPolygonF::constData() instead.
5090 QPainter painter(this);
5091 painter.drawPolygon(polygon, winding, index, count);
5093 int pointCount = (count == -1) ? polygon.size() - index : count;
5094 int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
5096 QPainter painter(this);
5097 painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
5101 /*! \fn void QPainter::drawPolygon(const QPolygon &polygon, bool winding,
5102 int index = 0, int count = -1)
5107 Use drawPolygon() combined with QPolygon::constData() instead.
5110 QPainter painter(this);
5111 painter.drawPolygon(polygon, winding, index, count);
5113 int pointCount = (count == -1) ? polygon.size() - index : count;
5114 int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
5116 QPainter painter(this);
5117 painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
5121 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
5125 Draws the polygon defined by the given \a points using the fill
5129 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
5133 Draws the polygon defined by the given \a points using the fill
5138 \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
5140 Draws the convex polygon defined by the first \a pointCount points
5141 in the array \a points using the current pen.
5145 \o \inlineimage qpainter-polygon.png
5147 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 15
5150 The first point is implicitly connected to the last point, and the
5151 polygon is filled with the current brush(). If the supplied
5152 polygon is not convex, i.e. it contains at least one angle larger
5153 than 180 degrees, the results are undefined.
5155 On some platforms (e.g. X11), the drawConvexPolygon() function can
5156 be faster than the drawPolygon() function.
5158 \sa drawPolygon(), drawPolyline(), {Coordinate System}
5162 \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
5165 Draws the convex polygon defined by the first \a pointCount points
5166 in the array \a points using the current pen.
5170 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
5174 Draws the convex polygon defined by \a polygon using the current
5179 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
5182 Draws the convex polygon defined by \a polygon using the current
5187 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon, int
5193 Use drawConvexPolygon() combined with QPolygonF::constData()
5197 QPainter painter(this);
5198 painter.drawConvexPolygon(polygon, index, count);
5200 int pointCount = (count == -1) ? polygon.size() - index : count;
5202 QPainter painter(this);
5203 painter.drawConvexPolygon(polygon.constData() + index, pointCount);
5208 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon, int
5214 Use drawConvexPolygon() combined with QPolygon::constData()
5218 QPainter painter(this);
5219 painter.drawConvexPolygon(polygon, index, count);
5221 int pointCount = (count == -1) ? polygon.size() - index : count;
5223 QPainter painter(this);
5224 painter.drawConvexPolygon(polygon.constData() + index, pointCount);
5228 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
5230 #ifdef QT_DEBUG_DRAW
5231 if (qt_show_painter_debug_output)
5232 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5237 if (!d->engine || pointCount < 2)
5241 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5245 d->updateState(d->state);
5247 uint emulationSpecifier = d->state->emulationSpecifier;
5249 if (emulationSpecifier) {
5250 QPainterPath polygonPath(points[0]);
5251 for (int i=1; i<pointCount; ++i)
5252 polygonPath.lineTo(points[i]);
5253 polygonPath.closeSubpath();
5254 polygonPath.setFillRule(Qt::WindingFill);
5255 d->draw_helper(polygonPath);
5259 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5262 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
5264 #ifdef QT_DEBUG_DRAW
5265 if (qt_show_painter_debug_output)
5266 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5271 if (!d->engine || pointCount < 2)
5275 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5279 d->updateState(d->state);
5281 uint emulationSpecifier = d->state->emulationSpecifier;
5283 if (emulationSpecifier) {
5284 QPainterPath polygonPath(points[0]);
5285 for (int i=1; i<pointCount; ++i)
5286 polygonPath.lineTo(points[i]);
5287 polygonPath.closeSubpath();
5288 polygonPath.setFillRule(Qt::WindingFill);
5289 d->draw_helper(polygonPath);
5293 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5296 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5298 return m.inverted().map(QPointF(m.map(p).toPoint()));
5302 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5304 Draws the rectangular portion \a source of the given \a pixmap
5305 into the given \a target in the paint device.
5307 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5312 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 16
5315 If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5316 using the pens color. If backgroundMode is Qt::OpaqueMode, the
5317 "unset" bits are drawn using the color of the background brush; if
5318 backgroundMode is Qt::TransparentMode, the "unset" bits are
5319 transparent. Drawing bitmaps with gradient or texture colors is
5324 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5326 #if defined QT_DEBUG_DRAW
5327 if (qt_show_painter_debug_output)
5328 printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5330 pm.width(), pm.height());
5335 if (!d->engine || pm.isNull())
5339 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5343 d->extended->drawPixmap(p, pm);
5351 int h = pm.height();
5356 // Emulate opaque background for bitmaps
5357 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5358 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5361 d->updateState(d->state);
5363 if ((d->state->matrix.type() > QTransform::TxTranslate
5364 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5365 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5366 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5369 // If there is no rotation involved we have to make sure we use the
5370 // antialiased and not the aliased coordinate system by rounding the coordinates.
5371 if (d->state->matrix.type() <= QTransform::TxScale) {
5372 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5377 setBackgroundMode(Qt::TransparentMode);
5378 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5379 QBrush brush(d->state->pen.color(), pm);
5382 setBrushOrigin(QPointF(0, 0));
5384 drawRect(pm.rect());
5387 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5388 x += d->state->matrix.dx();
5389 y += d->state->matrix.dy();
5391 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5395 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5397 #if defined QT_DEBUG_DRAW
5398 if (qt_show_painter_debug_output)
5399 printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5400 r.x(), r.y(), r.width(), r.height(),
5401 pm.width(), pm.height(),
5402 sr.x(), sr.y(), sr.width(), sr.height());
5406 if (!d->engine || pm.isNull())
5409 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5414 qreal w = r.width();
5415 qreal h = r.height();
5418 qreal sw = sr.width();
5419 qreal sh = sr.height();
5421 // Sanity-check clipping
5423 sw = pm.width() - sx;
5426 sh = pm.height() - sy;
5434 qreal w_ratio = sx * w/sw;
5442 qreal h_ratio = sy * h/sh;
5449 if (sw + sx > pm.width()) {
5450 qreal delta = sw - (pm.width() - sx);
5451 qreal w_ratio = delta * w/sw;
5456 if (sh + sy > pm.height()) {
5457 qreal delta = sh - (pm.height() - sy);
5458 qreal h_ratio = delta * h/sh;
5463 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5467 d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5471 // Emulate opaque background for bitmaps
5472 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5473 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5475 d->updateState(d->state);
5477 if ((d->state->matrix.type() > QTransform::TxTranslate
5478 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5479 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5480 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5481 || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5484 // If there is no rotation involved we have to make sure we use the
5485 // antialiased and not the aliased coordinate system by rounding the coordinates.
5486 if (d->state->matrix.type() <= QTransform::TxScale) {
5487 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5492 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5500 scale(w / sw, h / sh);
5501 setBackgroundMode(Qt::TransparentMode);
5502 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5505 if (sw == pm.width() && sh == pm.height())
5506 brush = QBrush(d->state->pen.color(), pm);
5508 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5513 drawRect(QRectF(0, 0, sw, sh));
5516 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5517 x += d->state->matrix.dx();
5518 y += d->state->matrix.dy();
5520 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5526 \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5527 const QRect &source)
5530 Draws the rectangular portion \a source of the given \a pixmap
5531 into the given \a target in the paint device.
5533 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5537 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5538 const QRectF &source)
5541 Draws the rectangular portion \a source of the given \a pixmap
5542 with its origin at the given \a point.
5546 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5547 const QRect &source)
5551 Draws the rectangular portion \a source of the given \a pixmap
5552 with its origin at the given \a point.
5556 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5559 Draws the given \a pixmap with its origin at the given \a point.
5563 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5566 Draws the given \a pixmap with its origin at the given \a point.
5570 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5574 Draws the given \a pixmap at position (\a{x}, \a{y}).
5578 \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5581 Draws the given \a pixmap into the given \a rectangle.
5583 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5587 \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5588 const QPixmap &pixmap)
5592 Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5593 with the given \a width and \a height.
5597 \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5598 int sx, int sy, int sw, int sh)
5602 Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5603 width \a sw and height \a sh, of the given \a pixmap , at the
5604 point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5605 If sw or sh are equal to zero the width/height of the pixmap
5606 is used and adjusted by the offset sx/sy;
5610 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5611 int sx, int sy, int sw, int sh)
5615 Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5616 pixmap into the paint device.
5618 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5619 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5620 pixmap that is to be drawn. The default is (0, 0).
5622 (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5623 The default, (0, 0) (and negative) means all the way to the
5624 bottom-right of the pixmap.
5627 void QPainter::drawImage(const QPointF &p, const QImage &image)
5631 if (!d->engine || image.isNull())
5635 d->extended->drawImage(p, image);
5642 int w = image.width();
5643 int h = image.height();
5645 d->updateState(d->state);
5647 if (((d->state->matrix.type() > QTransform::TxTranslate)
5648 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5649 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5650 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5653 // If there is no rotation involved we have to make sure we use the
5654 // antialiased and not the aliased coordinate system by rounding the coordinates.
5655 if (d->state->matrix.type() <= QTransform::TxScale) {
5656 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5661 setBackgroundMode(Qt::TransparentMode);
5662 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5663 QBrush brush(image);
5666 setBrushOrigin(QPointF(0, 0));
5668 drawRect(image.rect());
5673 if (d->state->matrix.type() == QTransform::TxTranslate
5674 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5675 x += d->state->matrix.dx();
5676 y += d->state->matrix.dy();
5679 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5682 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5683 Qt::ImageConversionFlags flags)
5687 if (!d->engine || image.isNull())
5690 qreal x = targetRect.x();
5691 qreal y = targetRect.y();
5692 qreal w = targetRect.width();
5693 qreal h = targetRect.height();
5694 qreal sx = sourceRect.x();
5695 qreal sy = sourceRect.y();
5696 qreal sw = sourceRect.width();
5697 qreal sh = sourceRect.height();
5699 // Sanity-check clipping
5701 sw = image.width() - sx;
5704 sh = image.height() - sy;
5712 qreal w_ratio = sx * w/sw;
5720 qreal h_ratio = sy * h/sh;
5727 if (sw + sx > image.width()) {
5728 qreal delta = sw - (image.width() - sx);
5729 qreal w_ratio = delta * w/sw;
5734 if (sh + sy > image.height()) {
5735 qreal delta = sh - (image.height() - sy);
5736 qreal h_ratio = delta * h/sh;
5741 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5745 d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5749 d->updateState(d->state);
5751 if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5752 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5753 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5754 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5757 // If there is no rotation involved we have to make sure we use the
5758 // antialiased and not the aliased coordinate system by rounding the coordinates.
5759 if (d->state->matrix.type() <= QTransform::TxScale) {
5760 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5765 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5772 scale(w / sw, h / sh);
5773 setBackgroundMode(Qt::TransparentMode);
5774 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5775 QBrush brush(image);
5778 setBrushOrigin(QPointF(-sx, -sy));
5780 drawRect(QRectF(0, 0, sw, sh));
5785 if (d->state->matrix.type() == QTransform::TxTranslate
5786 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5787 x += d->state->matrix.dx();
5788 y += d->state->matrix.dy();
5791 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5795 Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5796 edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5797 selected on \a glyphs and at offsets given by the positions in \a glyphs.
5801 \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes()
5803 #if !defined(QT_NO_RAWFONT)
5804 void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
5808 QRawFont font = glyphRun.rawFont();
5809 if (!font.isValid())
5812 QVector<quint32> glyphIndexes = glyphRun.glyphIndexes();
5813 QVector<QPointF> glyphPositions = glyphRun.positions();
5815 int count = qMin(glyphIndexes.size(), glyphPositions.size());
5816 QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5818 bool paintEngineSupportsTransformations =
5820 ? qt_paintengine_supports_transformations(d->extended->type())
5821 : qt_paintengine_supports_transformations(d->engine->type());
5823 // If the matrix is not affine, the paint engine will fall back to
5824 // drawing the glyphs as paths, which in turn means we should not
5825 // preprocess the glyph positions
5826 if (!d->state->matrix.isAffine())
5827 paintEngineSupportsTransformations = true;
5829 for (int i=0; i<count; ++i) {
5830 QPointF processedPosition = position + glyphPositions.at(i);
5831 if (!paintEngineSupportsTransformations)
5832 processedPosition = d->state->transform().map(processedPosition);
5833 fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5836 d->drawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count, font, glyphRun.overline(),
5837 glyphRun.underline(), glyphRun.strikeOut());
5840 void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, int glyphCount,
5841 const QRawFont &font, bool overline, bool underline,
5848 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5849 QFontEngine *fontEngine = fontD->fontEngine;
5854 for (int i=0; i<glyphCount; ++i) {
5855 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5856 if (i == 0 || leftMost > positions[i].x)
5857 leftMost = positions[i].x;
5859 // We don't support glyphs that do not share a common baseline. If this turns out to
5860 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5861 // and do a drawTextItemDecorations call per cluster.
5862 if (i == 0 || baseLine < positions[i].y)
5863 baseLine = positions[i].y;
5865 // We use the advance rather than the actual bounds to match the algorithm in drawText()
5866 if (i == 0 || rightMost < positions[i].x + gm.xoff)
5867 rightMost = positions[i].x + gm.xoff;
5870 QFixed width = rightMost - leftMost;
5872 if (extended != 0 && state->matrix.isAffine()) {
5873 QStaticTextItem staticTextItem;
5874 staticTextItem.color = state->pen.color();
5875 staticTextItem.font = state->font;
5876 staticTextItem.setFontEngine(fontEngine);
5877 staticTextItem.numGlyphs = glyphCount;
5878 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5879 staticTextItem.glyphPositions = positions;
5881 extended->drawStaticTextItem(&staticTextItem);
5883 QTextItemInt textItem;
5884 textItem.fontEngine = fontEngine;
5886 QVarLengthArray<QFixed, 128> advances(glyphCount);
5887 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5888 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5889 qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5890 qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
5891 qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5893 textItem.glyphs.numGlyphs = glyphCount;
5894 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5895 textItem.glyphs.offsets = positions;
5896 textItem.glyphs.advances_x = advances.data();
5897 textItem.glyphs.advances_y = advances.data();
5898 textItem.glyphs.justifications = glyphJustifications.data();
5899 textItem.glyphs.attributes = glyphAttributes.data();
5901 engine->drawTextItem(QPointF(0, 0), textItem);
5904 QTextItemInt::RenderFlags flags;
5906 flags |= QTextItemInt::Underline;
5908 flags |= QTextItemInt::Overline;
5910 flags |= QTextItemInt::StrikeOut;
5912 drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5915 ? QTextCharFormat::SingleUnderline
5916 : QTextCharFormat::NoUnderline),
5917 flags, width.toReal(), QTextCharFormat());
5919 #endif // QT_NO_RAWFONT
5923 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5927 Draws the \a staticText at the \a topLeftPosition.
5929 \note The y-position is used as the top of the font.
5934 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5938 Draws the \a staticText at coordinates \a left and \a top.
5940 \note The y-position is used as the top of the font.
5944 \fn void QPainter::drawText(const QPointF &position, const QString &text)
5946 Draws the given \a text with the currently defined text direction,
5947 beginning at the given \a position.
5949 This function does not handle the newline character (\n), as it cannot
5950 break text into multiple lines, and it cannot display the newline character.
5951 Use the QPainter::drawText() overload that takes a rectangle instead
5952 if you want to draw multiple lines of text with the newline character, or
5953 if you want the text to be wrapped.
5955 By default, QPainter draws text anti-aliased.
5957 \note The y-position is used as the baseline of the font.
5960 void QPainter::drawText(const QPointF &p, const QString &str)
5962 drawText(p, str, 0, 0);
5968 Draws the given \a staticText at the given \a topLeftPosition.
5970 The text will be drawn using the font and the transformation set on the painter. If the
5971 font and/or transformation set on the painter are different from the ones used to initialize
5972 the layout of the QStaticText, then the layout will have to be recalculated. Use
5973 QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5974 it will later be drawn.
5976 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5977 last drawn, then there will be a slight overhead when translating the text to its new position.
5979 \note If the painter's transformation is not affine, then \a staticText will be drawn using
5980 regular calls to drawText(), losing any potential for performance improvement.
5982 \note The y-position is used as the top of the font.
5986 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5989 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5992 QStaticTextPrivate *staticText_d =
5993 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5995 if (font() != staticText_d->font) {
5996 staticText_d->font = font();
5997 staticText_d->needsRelayout = true;
6000 // If we don't have an extended paint engine, or if the painter is projected,
6001 // we go through standard code path
6002 if (d->extended == 0 || !d->state->matrix.isAffine()) {
6003 staticText_d->paintText(topLeftPosition, this);
6007 bool paintEngineSupportsTransformations = qt_paintengine_supports_transformations(d->extended->type());
6008 if (paintEngineSupportsTransformations && !staticText_d->untransformedCoordinates) {
6009 staticText_d->untransformedCoordinates = true;
6010 staticText_d->needsRelayout = true;
6011 } else if (!paintEngineSupportsTransformations && staticText_d->untransformedCoordinates) {
6012 staticText_d->untransformedCoordinates = false;
6013 staticText_d->needsRelayout = true;
6016 // Don't recalculate entire layout because of translation, rather add the dx and dy
6017 // into the position to move each text item the correct distance.
6018 QPointF transformedPosition = topLeftPosition;
6019 if (!staticText_d->untransformedCoordinates)
6020 transformedPosition = transformedPosition * d->state->matrix;
6021 QTransform oldMatrix;
6023 // The translation has been applied to transformedPosition. Remove translation
6024 // component from matrix.
6025 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
6026 qreal m11 = d->state->matrix.m11();
6027 qreal m12 = d->state->matrix.m12();
6028 qreal m13 = d->state->matrix.m13();
6029 qreal m21 = d->state->matrix.m21();
6030 qreal m22 = d->state->matrix.m22();
6031 qreal m23 = d->state->matrix.m23();
6032 qreal m33 = d->state->matrix.m33();
6034 oldMatrix = d->state->matrix;
6035 d->state->matrix.setMatrix(m11, m12, m13,
6040 // If the transform is not identical to the text transform,
6041 // we have to relayout the text (for other transformations than plain translation)
6042 bool staticTextNeedsReinit = staticText_d->needsRelayout;
6043 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
6044 staticText_d->matrix = d->state->matrix;
6045 staticTextNeedsReinit = true;
6048 // Recreate the layout of the static text because the matrix or font has changed
6049 if (staticTextNeedsReinit)
6050 staticText_d->init();
6052 if (transformedPosition != staticText_d->position) { // Translate to actual position
6053 QFixed fx = QFixed::fromReal(transformedPosition.x());
6054 QFixed fy = QFixed::fromReal(transformedPosition.y());
6055 QFixed oldX = QFixed::fromReal(staticText_d->position.x());
6056 QFixed oldY = QFixed::fromReal(staticText_d->position.y());
6057 for (int item=0; item<staticText_d->itemCount;++item) {
6058 QStaticTextItem *textItem = staticText_d->items + item;
6059 for (int i=0; i<textItem->numGlyphs; ++i) {
6060 textItem->glyphPositions[i].x += fx - oldX;
6061 textItem->glyphPositions[i].y += fy - oldY;
6063 textItem->userDataNeedsUpdate = true;
6066 staticText_d->position = transformedPosition;
6069 QPen oldPen = d->state->pen;
6070 QColor currentColor = oldPen.color();
6071 for (int i=0; i<staticText_d->itemCount; ++i) {
6072 QStaticTextItem *item = staticText_d->items + i;
6073 if (item->color.isValid() && currentColor != item->color) {
6074 setPen(item->color);
6075 currentColor = item->color;
6077 d->extended->drawStaticTextItem(item);
6079 qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
6080 item->numGlyphs, item->fontEngine(), staticText_d->font,
6083 if (currentColor != oldPen.color())
6086 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
6087 d->state->matrix = oldMatrix;
6093 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
6095 #ifdef QT_DEBUG_DRAW
6096 if (qt_show_painter_debug_output)
6097 printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
6102 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
6105 if (tf & Qt::TextBypassShaping) {
6106 // Skip harfbuzz complex shaping, shape using glyph advances only
6107 int len = str.length();
6108 int numGlyphs = len;
6109 QVarLengthGlyphLayoutArray glyphs(len);
6110 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
6111 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
6112 glyphs.resize(numGlyphs);
6113 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
6114 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
6117 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
6118 drawTextItem(p, gf);
6122 QStackTextEngine engine(str, d->state->font);
6123 engine.option.setTextDirection(d->state->layoutDirection);
6124 if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
6125 engine.ignoreBidi = true;
6126 engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
6130 line.length = str.length();
6131 engine.shapeLine(line);
6133 int nItems = engine.layoutData->items.size();
6134 QVarLengthArray<int> visualOrder(nItems);
6135 QVarLengthArray<uchar> levels(nItems);
6136 for (int i = 0; i < nItems; ++i)
6137 levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
6138 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
6140 if (justificationPadding > 0) {
6141 engine.option.setAlignment(Qt::AlignJustify);
6142 engine.forceJustification = true;
6143 // this works because justify() is only interested in the difference between width and textWidth
6144 line.width = justificationPadding;
6145 engine.justify(line);
6147 QFixed x = QFixed::fromReal(p.x());
6149 for (int i = 0; i < nItems; ++i) {
6150 int item = visualOrder[i];
6151 const QScriptItem &si = engine.layoutData->items.at(item);
6152 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
6156 QFont f = engine.font(si);
6157 QTextItemInt gf(si, &f);
6158 gf.glyphs = engine.shapedGlyphs(&si);
6159 gf.chars = engine.layoutData->string.unicode() + si.position;
6160 gf.num_chars = engine.length(item);
6161 if (engine.forceJustification) {
6162 for (int j=0; j<gf.glyphs.numGlyphs; ++j)
6163 gf.width += gf.glyphs.effectiveAdvance(j);
6165 gf.width = si.width;
6167 gf.logClusters = engine.logClusters(&si);
6169 drawTextItem(QPointF(x.toReal(), p.y()), gf);
6175 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
6177 #ifdef QT_DEBUG_DRAW
6178 if (qt_show_painter_debug_output)
6179 printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
6180 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6185 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6189 d->updateState(d->state);
6192 qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
6194 *br = bounds.toAlignedRect();
6198 \fn void QPainter::drawText(const QPoint &position, const QString &text)
6202 Draws the given \a text with the currently defined text direction,
6203 beginning at the given \a position.
6205 By default, QPainter draws text anti-aliased.
6207 \note The y-position is used as the baseline of the font.
6212 \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
6215 Draws the given \a text within the provided \a rectangle.
6219 \o \inlineimage qpainter-text.png
6221 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 17
6224 The \a boundingRect (if not null) is set to the what the bounding rectangle
6225 should be in order to enclose the whole text. The \a flags argument is a bitwise
6226 OR of the following flags:
6238 \o Qt::TextSingleLine
6239 \o Qt::TextExpandTabs
6240 \o Qt::TextShowMnemonic
6242 \o Qt::TextIncludeTrailingSpaces
6245 \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
6247 By default, QPainter draws text anti-aliased.
6249 \note The y-coordinate of \a rectangle is used as the top of the font.
6251 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
6253 #ifdef QT_DEBUG_DRAW
6254 if (qt_show_painter_debug_output)
6255 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
6256 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6261 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6265 d->updateState(d->state);
6267 qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
6271 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
6274 Draws the given \a text within the provided \a rectangle according
6275 to the specified \a flags. The \a boundingRect (if not null) is set to
6276 the what the bounding rectangle should be in order to enclose the whole text.
6278 By default, QPainter draws text anti-aliased.
6280 \note The y-coordinate of \a rectangle is used as the top of the font.
6284 \fn void QPainter::drawText(int x, int y, const QString &text)
6288 Draws the given \a text at position (\a{x}, \a{y}), using the painter's
6289 currently defined text direction.
6291 By default, QPainter draws text anti-aliased.
6293 \note The y-position is used as the baseline of the font.
6298 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6299 const QString &text, QRect *boundingRect)
6303 Draws the given \a text within the rectangle with origin (\a{x},
6304 \a{y}), \a width and \a height.
6306 The \a boundingRect (if not null) is set to the actual bounding
6307 rectangle of the output. The \a flags argument is a bitwise OR of
6308 the following flags:
6319 \o Qt::TextSingleLine
6320 \o Qt::TextExpandTabs
6321 \o Qt::TextShowMnemonic
6325 By default, QPainter draws text anti-aliased.
6327 \note The y-position is used as the top of the font.
6329 \sa Qt::AlignmentFlag, Qt::TextFlag
6333 \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6334 const QTextOption &option)
6337 Draws the given \a text in the \a rectangle specified using the \a option
6338 to control its positioning and orientation.
6340 By default, QPainter draws text anti-aliased.
6342 \note The y-coordinate of \a rectangle is used as the top of the font.
6344 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6346 #ifdef QT_DEBUG_DRAW
6347 if (qt_show_painter_debug_output)
6348 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6349 r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6354 if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6358 d->updateState(d->state);
6360 qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6364 \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6371 \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6376 Draws the text item \a ti at position \a p.
6380 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6385 Draws the text item \a ti at position \a p.
6387 This method ignores the painters background mode and
6388 color. drawText and qt_format_text have to do it themselves, as
6389 only they know the extents of the complete string.
6391 It ignores the font set on the painter as the text item has one of its own.
6393 The underline and strikeout parameters of the text items font are
6394 ignored aswell. You'll need to pass in the correct flags to get
6395 underlining and strikeout.
6398 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6400 const qreal radiusBase = qMax(qreal(1), maxRadius);
6402 QString key = QLatin1Literal("WaveUnderline-")
6403 % pen.color().name()
6404 % HexString<qreal>(radiusBase);
6407 if (QPixmapCache::find(key, pixmap))
6410 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6411 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6412 const int radius = qFloor(radiusBase);
6419 while (xs < width) {
6422 path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6425 pixmap = QPixmap(width, radius * 2);
6426 pixmap.fill(Qt::transparent);
6429 wavePen.setCapStyle(Qt::SquareCap);
6431 // This is to protect against making the line too fat, as happens on Mac OS X
6432 // due to it having a rather thick width for the regular underline.
6433 const qreal maxPenWidth = .8 * radius;
6434 if (wavePen.widthF() > maxPenWidth)
6435 wavePen.setWidth(maxPenWidth);
6437 QPainter imgPainter(&pixmap);
6438 imgPainter.setPen(wavePen);
6439 imgPainter.setRenderHint(QPainter::Antialiasing);
6440 imgPainter.translate(0, radius);
6441 imgPainter.drawPath(path);
6444 QPixmapCache::insert(key, pixmap);
6449 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
6450 QTextCharFormat::UnderlineStyle underlineStyle,
6451 QTextItem::RenderFlags flags, qreal width,
6452 const QTextCharFormat &charFormat)
6454 if (underlineStyle == QTextCharFormat::NoUnderline
6455 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6458 const QPen oldPen = painter->pen();
6459 const QBrush oldBrush = painter->brush();
6460 painter->setBrush(Qt::NoBrush);
6462 pen.setStyle(Qt::SolidLine);
6463 pen.setWidthF(fe->lineThickness().toReal());
6464 pen.setCapStyle(Qt::FlatCap);
6466 QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6468 const qreal underlineOffset = fe->underlinePosition().toReal();
6469 // deliberately ceil the offset to avoid the underline coming too close to
6470 // the text above it.
6471 const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
6472 const qreal underlinePos = pos.y() + qCeil(underlineOffset) - aliasedCoordinateDelta;
6474 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6475 underlineStyle = QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle));
6478 if (underlineStyle == QTextCharFormat::WaveUnderline) {
6480 painter->translate(0, pos.y() + 1);
6482 QColor uc = charFormat.underlineColor();
6486 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6487 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6488 const int descent = (int) fe->descent().toReal();
6490 painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6491 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6493 } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6494 QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos);
6496 QColor uc = charFormat.underlineColor();
6500 pen.setStyle((Qt::PenStyle)(underlineStyle));
6501 painter->setPen(pen);
6502 painter->drawLine(underLine);
6505 pen.setStyle(Qt::SolidLine);
6506 pen.setColor(oldPen.color());
6508 if (flags & QTextItem::StrikeOut) {
6509 QLineF strikeOutLine = line;
6510 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6511 painter->setPen(pen);
6512 painter->drawLine(strikeOutLine);
6515 if (flags & QTextItem::Overline) {
6516 QLineF overLine = line;
6517 overLine.translate(0., - fe->ascent().toReal());
6518 painter->setPen(pen);
6519 painter->drawLine(overLine);
6522 painter->setPen(oldPen);
6523 painter->setBrush(oldBrush);
6526 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6527 const QFixedPoint *positions, int glyphCount,
6528 QFontEngine *fontEngine, const QFont &font,
6529 const QTextCharFormat &charFormat)
6531 if (!(font.underline() || font.strikeOut() || font.overline()))
6537 for (int i=0; i<glyphCount; ++i) {
6538 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6539 if (i == 0 || leftMost > positions[i].x)
6540 leftMost = positions[i].x;
6542 // We don't support glyphs that do not share a common baseline. If this turns out to
6543 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6544 // and do a drawTextItemDecorations call per cluster.
6545 if (i == 0 || baseLine < positions[i].y)
6546 baseLine = positions[i].y;
6548 // We use the advance rather than the actual bounds to match the algorithm in drawText()
6549 if (i == 0 || rightMost < positions[i].x + gm.xoff)
6550 rightMost = positions[i].x + gm.xoff;
6553 QFixed width = rightMost - leftMost;
6554 QTextItem::RenderFlags flags = 0;
6556 if (font.underline())
6557 flags |= QTextItem::Underline;
6558 if (font.overline())
6559 flags |= QTextItem::Overline;
6560 if (font.strikeOut())
6561 flags |= QTextItem::StrikeOut;
6563 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6565 font.underline() ? QTextCharFormat::SingleUnderline
6566 : QTextCharFormat::NoUnderline, flags,
6567 width.toReal(), charFormat);
6570 void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
6572 #ifdef QT_DEBUG_DRAW
6573 if (qt_show_painter_debug_output)
6574 printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6575 p.x(), p.y(), qPrintable(_ti.text()));
6584 qt_painter_thread_test(d->device->devType(),
6586 QFontDatabase::supportsThreadedFontRendering());
6589 QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6591 if (!d->extended && d->state->bgMode == Qt::OpaqueMode) {
6592 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6593 fillRect(rect, d->state->bgBrush);
6596 if (pen().style() == Qt::NoPen)
6599 const RenderHints oldRenderHints = d->state->renderHints;
6600 if (!d->state->renderHints & QPainter::Antialiasing && d->state->matrix.type() >= QTransform::TxScale) {
6601 // draw antialias decoration (underline/overline/strikeout) with
6605 const QTransform &m = d->state->matrix;
6606 if (d->state->matrix.type() < QTransform::TxShear) {
6607 bool isPlain90DegreeRotation =
6608 (qFuzzyIsNull(m.m11())
6609 && qFuzzyIsNull(m.m12() - qreal(1))
6610 && qFuzzyIsNull(m.m21() + qreal(1))
6611 && qFuzzyIsNull(m.m22())
6614 (qFuzzyIsNull(m.m11() + qreal(1))
6615 && qFuzzyIsNull(m.m12())
6616 && qFuzzyIsNull(m.m21())
6617 && qFuzzyIsNull(m.m22() + qreal(1))
6620 (qFuzzyIsNull(m.m11())
6621 && qFuzzyIsNull(m.m12() + qreal(1))
6622 && qFuzzyIsNull(m.m21() - qreal(1))
6623 && qFuzzyIsNull(m.m22())
6626 aa = !isPlain90DegreeRotation;
6629 setRenderHint(QPainter::Antialiasing, true);
6633 d->updateState(d->state);
6635 if (!ti.glyphs.numGlyphs) {
6637 } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6638 QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6640 const QGlyphLayout &glyphs = ti.glyphs;
6641 int which = glyphs.glyphs[0] >> 24;
6648 for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6649 const int e = glyphs.glyphs[end] >> 24;
6654 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6656 // set the high byte to zero and calc the width
6657 for (i = start; i < end; ++i) {
6658 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6659 ti2.width += ti.glyphs.effectiveAdvance(i);
6662 d->engine->drawTextItem(QPointF(x, y), ti2);
6664 // reset the high byte for all glyphs and advance to the next sub-string
6665 const int hi = which << 24;
6666 for (i = start; i < end; ++i) {
6667 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6669 x += ti2.width.toReal();
6676 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6678 // set the high byte to zero and calc the width
6679 for (i = start; i < end; ++i) {
6680 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6681 ti2.width += ti.glyphs.effectiveAdvance(i);
6685 d->extended->drawTextItem(QPointF(x, y), ti2);
6687 d->engine->drawTextItem(QPointF(x,y), ti2);
6689 // reset the high byte for all glyphs
6690 const int hi = which << 24;
6691 for (i = start; i < end; ++i)
6692 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6696 d->extended->drawTextItem(p, ti);
6698 d->engine->drawTextItem(p, ti);
6700 drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(),
6703 if (d->state->renderHints != oldRenderHints) {
6704 d->state->renderHints = oldRenderHints;
6706 d->extended->renderHintsChanged();
6708 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
6713 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6715 Returns the bounding rectangle of the \a text as it will appear
6716 when drawn inside the given \a rectangle with the specified \a
6717 flags using the currently set font(); i.e the function tells you
6718 where the drawText() function will draw when given the same
6721 If the \a text does not fit within the given \a rectangle using
6722 the specified \a flags, the function returns the required
6725 The \a flags argument is a bitwise OR of the following flags:
6734 \o Qt::TextSingleLine
6735 \o Qt::TextExpandTabs
6736 \o Qt::TextShowMnemonic
6738 \o Qt::TextIncludeTrailingSpaces
6740 If several of the horizontal or several of the vertical alignment
6741 flags are set, the resulting alignment is undefined.
6743 \sa drawText(), Qt::Alignment, Qt::TextFlag
6747 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6748 const QString &text)
6752 Returns the bounding rectangle of the \a text as it will appear
6753 when drawn inside the given \a rectangle with the specified \a
6754 flags using the currently set font().
6758 \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6759 const QString &text);
6763 Returns the bounding rectangle of the given \a text as it will
6764 appear when drawn inside the rectangle beginning at the point
6765 (\a{x}, \a{y}) with width \a w and height \a h.
6767 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6770 return QRect(rect.x(),rect.y(), 0,0);
6772 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6778 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6781 return QRectF(rect.x(),rect.y(), 0,0);
6783 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6788 \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6789 const QString &text, const QTextOption &option)
6793 Instead of specifying flags as a bitwise OR of the
6794 Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6795 an \a option argument. The QTextOption class provides a
6796 description of general rich text properties.
6800 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6804 if (!d->engine || text.length() == 0)
6805 return QRectF(r.x(),r.y(), 0,0);
6808 qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6813 \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6815 Draws a tiled \a pixmap, inside the given \a rectangle with its
6816 origin at the given \a position.
6818 Calling drawTiledPixmap() is similar to calling drawPixmap()
6819 several times to fill (tile) an area with a pixmap, but is
6820 potentially much more efficient depending on the underlying window
6825 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6827 #ifdef QT_DEBUG_DRAW
6828 if (qt_show_painter_debug_output)
6829 printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6830 r.x(), r.y(), r.width(), r.height(),
6831 pixmap.width(), pixmap.height(),
6836 if (!d->engine || pixmap.isNull() || r.isEmpty())
6840 qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6843 qreal sw = pixmap.width();
6844 qreal sh = pixmap.height();
6848 sx = qRound(sw) - qRound(-sx) % qRound(sw);
6850 sx = qRound(sx) % qRound(sw);
6852 sy = qRound(sh) - -qRound(sy) % qRound(sh);
6854 sy = qRound(sy) % qRound(sh);
6858 d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6862 if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6863 fillRect(r, d->state->bgBrush);
6865 d->updateState(d->state);
6866 if ((d->state->matrix.type() > QTransform::TxTranslate
6867 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6868 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6871 setBackgroundMode(Qt::TransparentMode);
6872 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6873 setBrush(QBrush(d->state->pen.color(), pixmap));
6876 // If there is no rotation involved we have to make sure we use the
6877 // antialiased and not the aliased coordinate system by rounding the coordinates.
6878 if (d->state->matrix.type() <= QTransform::TxScale) {
6879 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6881 if (d->state->matrix.type() <= QTransform::TxTranslate) {
6886 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6887 drawRect(QRectF(p, r.size()));
6889 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6898 if (d->state->matrix.type() == QTransform::TxTranslate
6899 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6900 x += d->state->matrix.dx();
6901 y += d->state->matrix.dy();
6904 d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6908 \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6909 const QPoint &position = QPoint())
6912 Draws a tiled \a pixmap, inside the given \a rectangle with its
6913 origin at the given \a position.
6917 \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6918 QPixmap &pixmap, int sx, int sy);
6921 Draws a tiled \a pixmap in the specified rectangle.
6923 (\a{x}, \a{y}) specifies the top-left point in the paint device
6924 that is to be drawn onto; with the given \a width and \a
6925 height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6926 pixmap that is to be drawn; this defaults to (0, 0).
6929 #ifndef QT_NO_PICTURE
6932 \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6934 Replays the given \a picture at the given \a point.
6936 The QPicture class is a paint device that records and replays
6937 QPainter commands. A picture serializes the painter commands to an
6938 IO device in a platform-independent format. Everything that can be
6939 painted on a widget or pixmap can also be stored in a picture.
6941 This function does exactly the same as QPicture::play() when
6942 called with \a point = QPoint(0, 0).
6947 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 18
6950 \sa QPicture::play()
6953 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6961 d->updateState(d->state);
6965 const_cast<QPicture *>(&picture)->play(this);
6970 \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6973 Replays the given \a picture at the given \a point.
6977 \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6980 Draws the given \a picture at point (\a x, \a y).
6983 #endif // QT_NO_PICTURE
6986 \fn void QPainter::eraseRect(const QRectF &rectangle)
6988 Erases the area inside the given \a rectangle. Equivalent to
6990 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 19
6994 void QPainter::eraseRect(const QRectF &r)
6998 fillRect(r, d->state->bgBrush);
7001 static inline bool needsResolving(const QBrush &brush)
7003 Qt::BrushStyle s = brush.style();
7004 return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
7005 s == Qt::ConicalGradientPattern) &&
7006 brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
7010 \fn void QPainter::eraseRect(const QRect &rectangle)
7013 Erases the area inside the given \a rectangle.
7017 \fn void QPainter::eraseRect(int x, int y, int width, int height)
7020 Erases the area inside the rectangle beginning at (\a x, \a y)
7021 with the given \a width and \a height.
7026 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
7029 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7030 width and \a height, using the brush \a style specified.
7036 \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
7039 Fills the given \a rectangle with the brush \a style specified.
7045 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
7048 Fills the given \a rectangle with the brush \a style specified.
7054 \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
7056 Fills the given \a rectangle with the \a brush specified.
7058 Alternatively, you can specify a QColor instead of a QBrush; the
7059 QBrush constructor (taking a QColor argument) will automatically
7060 create a solid pattern brush.
7064 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
7072 const QGradient *g = brush.gradient();
7073 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
7074 d->extended->fillRect(r, brush);
7079 QPen oldPen = pen();
7080 QBrush oldBrush = this->brush();
7082 if (brush.style() == Qt::SolidPattern) {
7083 d->colorBrush.setStyle(Qt::SolidPattern);
7084 d->colorBrush.setColor(brush.color());
7085 setBrush(d->colorBrush);
7096 \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
7099 Fills the given \a rectangle with the specified \a brush.
7102 void QPainter::fillRect(const QRect &r, const QBrush &brush)
7110 const QGradient *g = brush.gradient();
7111 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
7112 d->extended->fillRect(r, brush);
7117 QPen oldPen = pen();
7118 QBrush oldBrush = this->brush();
7120 if (brush.style() == Qt::SolidPattern) {
7121 d->colorBrush.setStyle(Qt::SolidPattern);
7122 d->colorBrush.setColor(brush.color());
7123 setBrush(d->colorBrush);
7136 \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
7139 Fills the given \a rectangle with the \a color specified.
7143 void QPainter::fillRect(const QRect &r, const QColor &color)
7151 d->extended->fillRect(r, color);
7155 fillRect(r, QBrush(color));
7160 \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
7163 Fills the given \a rectangle with the \a color specified.
7167 void QPainter::fillRect(const QRectF &r, const QColor &color)
7175 d->extended->fillRect(r, color);
7179 fillRect(r, QBrush(color));
7183 \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
7187 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7188 width and \a height, using the given \a brush.
7192 \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
7196 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7197 width and \a height, using the given \a color.
7203 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
7207 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7208 width and \a height, using the given \a color.
7214 \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
7218 Fills the given \a rectangle with the specified \a color.
7224 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
7228 Fills the given \a rectangle with the specified \a color.
7234 Sets the given render \a hint on the painter if \a on is true;
7235 otherwise clears the render hint.
7237 \sa setRenderHints(), renderHints(), {QPainter#Rendering
7238 Quality}{Rendering Quality}
7240 void QPainter::setRenderHint(RenderHint hint, bool on)
7242 #ifdef QT_DEBUG_DRAW
7243 if (qt_show_painter_debug_output)
7244 printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
7248 static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
7249 if (hint == QPainter::Antialiasing && antialiasingDisabled)
7253 setRenderHints(hint, on);
7259 Sets the given render \a hints on the painter if \a on is true;
7260 otherwise clears the render hints.
7262 \sa setRenderHint(), renderHints(), {QPainter#Rendering
7263 Quality}{Rendering Quality}
7266 void QPainter::setRenderHints(RenderHints hints, bool on)
7271 qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7276 d->state->renderHints |= hints;
7278 d->state->renderHints &= ~hints;
7281 d->extended->renderHintsChanged();
7283 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7287 Returns a flag that specifies the rendering hints that are set for
7290 \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7292 QPainter::RenderHints QPainter::renderHints() const
7294 Q_D(const QPainter);
7299 return d->state->renderHints;
7303 \fn bool QPainter::testRenderHint(RenderHint hint) const
7306 Returns true if \a hint is set; otherwise returns false.
7308 \sa renderHints(), setRenderHint()
7312 Returns true if view transformation is enabled; otherwise returns
7315 \sa setViewTransformEnabled(), worldTransform()
7318 bool QPainter::viewTransformEnabled() const
7320 Q_D(const QPainter);
7322 qWarning("QPainter::viewTransformEnabled: Painter not active");
7325 return d->state->VxF;
7329 \fn void QPainter::setWindow(const QRect &rectangle)
7331 Sets the painter's window to the given \a rectangle, and enables
7332 view transformations.
7334 The window rectangle is part of the view transformation. The
7335 window specifies the logical coordinate system. Its sister, the
7336 viewport(), specifies the device coordinate system.
7338 The default window rectangle is the same as the device's
7341 \sa window(), viewTransformEnabled(), {Coordinate
7342 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7346 \fn void QPainter::setWindow(int x, int y, int width, int height)
7349 Sets the painter's window to the rectangle beginning at (\a x, \a
7350 y) and the given \a width and \a height.
7353 void QPainter::setWindow(const QRect &r)
7355 #ifdef QT_DEBUG_DRAW
7356 if (qt_show_painter_debug_output)
7357 printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7363 qWarning("QPainter::setWindow: Painter not active");
7367 d->state->wx = r.x();
7368 d->state->wy = r.y();
7369 d->state->ww = r.width();
7370 d->state->wh = r.height();
7372 d->state->VxF = true;
7377 Returns the window rectangle.
7379 \sa setWindow(), setViewTransformEnabled()
7382 QRect QPainter::window() const
7384 Q_D(const QPainter);
7386 qWarning("QPainter::window: Painter not active");
7389 return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7393 \fn void QPainter::setViewport(const QRect &rectangle)
7395 Sets the painter's viewport rectangle to the given \a rectangle,
7396 and enables view transformations.
7398 The viewport rectangle is part of the view transformation. The
7399 viewport specifies the device coordinate system. Its sister, the
7400 window(), specifies the logical coordinate system.
7402 The default viewport rectangle is the same as the device's
7405 \sa viewport(), viewTransformEnabled() {Coordinate
7406 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7410 \fn void QPainter::setViewport(int x, int y, int width, int height)
7413 Sets the painter's viewport rectangle to be the rectangle
7414 beginning at (\a x, \a y) with the given \a width and \a height.
7417 void QPainter::setViewport(const QRect &r)
7419 #ifdef QT_DEBUG_DRAW
7420 if (qt_show_painter_debug_output)
7421 printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7427 qWarning("QPainter::setViewport: Painter not active");
7431 d->state->vx = r.x();
7432 d->state->vy = r.y();
7433 d->state->vw = r.width();
7434 d->state->vh = r.height();
7436 d->state->VxF = true;
7441 Returns the viewport rectangle.
7443 \sa setViewport(), setViewTransformEnabled()
7446 QRect QPainter::viewport() const
7448 Q_D(const QPainter);
7450 qWarning("QPainter::viewport: Painter not active");
7453 return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7456 /*! \fn bool QPainter::hasViewXForm() const
7459 Use viewTransformEnabled() instead.
7462 /*! \fn bool QPainter::hasWorldXForm() const
7465 Use worldMatrixEnabled() instead.
7468 /*! \fn void QPainter::resetXForm()
7471 Use resetTransform() instead.
7474 /*! \fn void QPainter::setViewXForm(bool enabled)
7477 Use setViewTransformEnabled() instead.
7480 /*! \fn void QPainter::setWorldXForm(bool enabled)
7483 Use setWorldMatrixEnabled() instead.
7486 Enables view transformations if \a enable is true, or disables
7487 view transformations if \a enable is false.
7489 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7490 Conversion}{Window-Viewport Conversion}
7493 void QPainter::setViewTransformEnabled(bool enable)
7495 #ifdef QT_DEBUG_DRAW
7496 if (qt_show_painter_debug_output)
7497 printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7503 qWarning("QPainter::setViewTransformEnabled: Painter not active");
7507 if (enable == d->state->VxF)
7510 d->state->VxF = enable;
7519 Use the worldTransform() combined with QTransform::dx() instead.
7522 QPainter painter(this);
7523 qreal x = painter.translationX();
7525 QPainter painter(this);
7526 qreal x = painter.worldTransform().dx();
7529 qreal QPainter::translationX() const
7531 Q_D(const QPainter);
7533 qWarning("QPainter::translationX: Painter not active");
7536 return d->state->worldMatrix.dx();
7542 Use the worldTransform() combined with QTransform::dy() instead.
7545 QPainter painter(this);
7546 qreal y = painter.translationY();
7548 QPainter painter(this);
7549 qreal y = painter.worldTransform().dy();
7552 qreal QPainter::translationY() const
7554 Q_D(const QPainter);
7556 qWarning("QPainter::translationY: Painter not active");
7559 return d->state->worldMatrix.dy();
7563 \fn void QPainter::map(int x, int y, int *rx, int *ry) const
7567 Sets (\a{rx}, \a{ry}) to the point that results from applying the
7568 painter's current transformation on the point (\a{x}, \a{y}).
7570 void QPainter::map(int x, int y, int *rx, int *ry) const
7573 p = p * combinedMatrix();
7579 \fn QPoint QPainter::xForm(const QPoint &point) const
7581 Use combinedTransform() instead.
7584 QPoint QPainter::xForm(const QPoint &p) const
7586 Q_D(const QPainter);
7588 qWarning("QPainter::xForm: Painter not active");
7591 if (d->state->matrix.type() == QTransform::TxNone)
7593 return p * combinedMatrix();
7598 \fn QRect QPainter::xForm(const QRect &rectangle) const
7601 Use combinedTransform() instead of this function and call
7602 mapRect() on the result to obtain a QRect.
7605 QRect QPainter::xForm(const QRect &r) const
7607 Q_D(const QPainter);
7609 qWarning("QPainter::xForm: Painter not active");
7612 if (d->state->matrix.type() == QTransform::TxNone)
7614 return combinedMatrix().mapRect(r);
7618 \fn QPolygon QPainter::xForm(const QPolygon &polygon) const
7621 Use combinedTransform() instead.
7624 QPolygon QPainter::xForm(const QPolygon &a) const
7626 Q_D(const QPainter);
7628 qWarning("QPainter::xForm: Painter not active");
7631 if (d->state->matrix.type() == QTransform::TxNone)
7633 return a * combinedMatrix();
7637 \fn QPolygon QPainter::xForm(const QPolygon &polygon, int index, int count) const
7640 Use combinedTransform() combined with QPolygon::mid() instead.
7643 QPainter painter(this);
7644 QPolygon transformed = painter.xForm(polygon, index, count)
7646 QPainter painter(this);
7647 QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform();
7651 QPolygon QPainter::xForm(const QPolygon &av, int index, int npoints) const
7653 int lastPoint = npoints < 0 ? av.size() : index+npoints;
7654 QPolygon a(lastPoint-index);
7655 memcpy(a.data(), av.data()+index, (lastPoint-index)*sizeof(QPoint));
7656 return a * combinedMatrix();
7660 \fn QPoint QPainter::xFormDev(const QPoint &point) const
7664 Use combinedTransform() combined with QTransform::inverted() instead.
7667 QPainter painter(this);
7668 QPoint transformed = painter.xFormDev(point);
7670 QPainter painter(this);
7671 QPoint transformed = point * painter.combinedTransform().inverted();
7675 QPoint QPainter::xFormDev(const QPoint &p) const
7677 Q_D(const QPainter);
7679 qWarning("QPainter::xFormDev: Painter not active");
7682 if(d->state->matrix.type() == QTransform::TxNone)
7684 return p * combinedMatrix().inverted();
7688 \fn QRect QPainter::xFormDev(const QRect &rectangle) const
7692 Use combinedTransform() combined with QTransform::inverted() instead.
7695 QPainter painter(this);
7696 QRect transformed = painter.xFormDev(rectangle);
7698 QPainter painter(this);
7699 QRegion region = QRegion(rectangle) * painter.combinedTransform().inverted();
7700 QRect transformed = region.boundingRect();
7704 QRect QPainter::xFormDev(const QRect &r) const
7706 Q_D(const QPainter);
7708 qWarning("QPainter::xFormDev: Painter not active");
7711 if (d->state->matrix.type() == QTransform::TxNone)
7713 return combinedMatrix().inverted().mapRect(r);
7719 \fn QPoint QPainter::xFormDev(const QPolygon &polygon) const
7722 Use combinedTransform() combined with QTransform::inverted() instead.
7725 QPainter painter(this);
7726 QPolygon transformed = painter.xFormDev(rectangle);
7728 QPainter painter(this);
7729 QPolygon transformed = polygon * painter.combinedTransform().inverted();
7733 QPolygon QPainter::xFormDev(const QPolygon &a) const
7735 Q_D(const QPainter);
7737 qWarning("QPainter::xFormDev: Painter not active");
7740 if (d->state->matrix.type() == QTransform::TxNone)
7742 return a * combinedMatrix().inverted();
7746 \fn QPolygon QPainter::xFormDev(const QPolygon &polygon, int index, int count) const
7750 Use combinedTransform() combined with QPolygon::mid() and QTransform::inverted() instead.
7753 QPainter painter(this);
7754 QPolygon transformed = painter.xFormDev(polygon, index, count);
7756 QPainter painter(this);
7757 QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform().inverted();
7761 QPolygon QPainter::xFormDev(const QPolygon &ad, int index, int npoints) const
7763 Q_D(const QPainter);
7764 int lastPoint = npoints < 0 ? ad.size() : index+npoints;
7765 QPolygon a(lastPoint-index);
7766 memcpy(a.data(), ad.data()+index, (lastPoint-index)*sizeof(QPoint));
7767 if (d->state->matrix.type() == QTransform::TxNone)
7769 return a * combinedMatrix().inverted();
7773 \fn void QPainter::drawCubicBezier(const QPolygon &controlPoints, int index)
7775 Draws a cubic Bezier curve defined by the \a controlPoints,
7776 starting at \a{controlPoints}\e{[index]} (\a index defaults to 0).
7777 Points after \a{controlPoints}\e{[index + 3]} are ignored. Nothing
7778 happens if there aren't enough control points.
7780 Use strokePath() instead.
7783 QPainter painter(this);
7784 painter.drawCubicBezier(controlPoints, index)
7787 path.moveTo(controlPoints.at(index));
7788 path.cubicTo(controlPoints.at(index+1),
7789 controlPoints.at(index+2),
7790 controlPoints.at(index+3));
7792 QPainter painter(this);
7793 painter.strokePath(path, painter.pen());
7796 void QPainter::drawCubicBezier(const QPolygon &a, int index)
7803 if ((int)a.size() - index < 4) {
7804 qWarning("QPainter::drawCubicBezier: Cubic Bezier needs 4 control "
7810 path.moveTo(a.at(index));
7811 path.cubicTo(a.at(index+1), a.at(index+2), a.at(index+3));
7812 strokePath(path, d->state->pen);
7816 struct QPaintDeviceRedirection
7818 QPaintDeviceRedirection() : device(0), replacement(0), internalWidgetRedirectionIndex(-1) {}
7819 QPaintDeviceRedirection(const QPaintDevice *device, QPaintDevice *replacement,
7820 const QPoint& offset, int internalWidgetRedirectionIndex)
7821 : device(device), replacement(replacement), offset(offset),
7822 internalWidgetRedirectionIndex(internalWidgetRedirectionIndex) { }
7823 const QPaintDevice *device;
7824 QPaintDevice *replacement;
7826 int internalWidgetRedirectionIndex;
7827 bool operator==(const QPaintDevice *pdev) const { return device == pdev; }
7828 Q_DUMMY_COMPARISON_OPERATOR(QPaintDeviceRedirection)
7831 typedef QList<QPaintDeviceRedirection> QPaintDeviceRedirectionList;
7832 Q_GLOBAL_STATIC(QPaintDeviceRedirectionList, globalRedirections)
7833 Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex)
7834 Q_GLOBAL_STATIC(QAtomicInt, globalRedirectionAtomic)
7841 Please use QWidget::render() instead.
7843 Redirects all paint commands for the given paint \a device, to the
7844 \a replacement device. The optional point \a offset defines an
7845 offset within the source device.
7847 The redirection will not be effective until the begin() function
7848 has been called; make sure to call end() for the given \a
7849 device's painter (if any) before redirecting. Call
7850 restoreRedirected() to restore the previous redirection.
7852 \warning Making use of redirections in the QPainter API implies
7853 that QPainter::begin() and QPaintDevice destructors need to hold
7854 a mutex for a short period. This can impact performance. Use of
7855 QWidget::render is strongly encouraged.
7857 \sa redirected(), restoreRedirected()
7859 void QPainter::setRedirected(const QPaintDevice *device,
7860 QPaintDevice *replacement,
7861 const QPoint &offset)
7863 Q_ASSERT(device != 0);
7865 bool hadInternalWidgetRedirection = false;
7866 if (device->devType() == QInternal::Widget) {
7867 const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
7868 // This is the case when the widget is in a paint event.
7869 if (widgetPrivate->redirectDev) {
7870 // Remove internal redirection and put it back into the global redirection list.
7872 QPaintDevice *oldReplacement = widgetPrivate->redirected(&oldOffset);
7873 const_cast<QWidgetPrivate *>(widgetPrivate)->restoreRedirected();
7874 setRedirected(device, oldReplacement, oldOffset);
7875 hadInternalWidgetRedirection = true;
7880 QPaintDevice *rdev = redirected(replacement, &roffset);
7882 QMutexLocker locker(globalRedirectionsMutex());
7883 QPaintDeviceRedirectionList *redirections = globalRedirections();
7884 Q_ASSERT(redirections != 0);
7885 *redirections += QPaintDeviceRedirection(device, rdev ? rdev : replacement, offset + roffset,
7886 hadInternalWidgetRedirection ? redirections->size() - 1 : -1);
7887 globalRedirectionAtomic()->ref();
7895 Using QWidget::render() obsoletes the use of this function.
7897 Restores the previous redirection for the given \a device after a
7898 call to setRedirected().
7900 \warning Making use of redirections in the QPainter API implies
7901 that QPainter::begin() and QPaintDevice destructors need to hold
7902 a mutex for a short period. This can impact performance. Use of
7903 QWidget::render is strongly encouraged.
7907 void QPainter::restoreRedirected(const QPaintDevice *device)
7909 Q_ASSERT(device != 0);
7910 QMutexLocker locker(globalRedirectionsMutex());
7911 QPaintDeviceRedirectionList *redirections = globalRedirections();
7912 Q_ASSERT(redirections != 0);
7913 for (int i = redirections->size()-1; i >= 0; --i) {
7914 if (redirections->at(i) == device) {
7915 globalRedirectionAtomic()->deref();
7916 const int internalWidgetRedirectionIndex = redirections->at(i).internalWidgetRedirectionIndex;
7917 redirections->removeAt(i);
7918 // Restore the internal widget redirection, i.e. remove it from the global
7919 // redirection list and put it back into QWidgetPrivate. The index is only set when
7920 // someone call QPainter::setRedirected in a widget's paint event and we internally
7921 // have a redirection set (typically set in QWidgetPrivate::drawWidget).
7922 if (internalWidgetRedirectionIndex >= 0) {
7923 Q_ASSERT(internalWidgetRedirectionIndex < redirections->size());
7924 const QPaintDeviceRedirection &redirectionDevice = redirections->at(internalWidgetRedirectionIndex);
7925 QWidget *widget = static_cast<QWidget *>(const_cast<QPaintDevice *>(device));
7926 widget->d_func()->setRedirected(redirectionDevice.replacement, redirectionDevice.offset);
7927 redirections->removeAt(internalWidgetRedirectionIndex);
7939 Using QWidget::render() obsoletes the use of this function.
7941 Returns the replacement for given \a device. The optional out
7942 parameter \a offset returns the offset within the replaced device.
7944 \warning Making use of redirections in the QPainter API implies
7945 that QPainter::begin() and QPaintDevice destructors need to hold
7946 a mutex for a short period. This can impact performance. Use of
7947 QWidget::render is strongly encouraged.
7949 \sa setRedirected(), restoreRedirected()
7951 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7953 Q_ASSERT(device != 0);
7955 if (device->devType() == QInternal::Widget) {
7956 const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
7957 if (widgetPrivate->redirectDev)
7958 return widgetPrivate->redirected(offset);
7961 if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
7964 QMutexLocker locker(globalRedirectionsMutex());
7965 QPaintDeviceRedirectionList *redirections = globalRedirections();
7966 Q_ASSERT(redirections != 0);
7967 for (int i = redirections->size()-1; i >= 0; --i)
7968 if (redirections->at(i) == device) {
7970 *offset = redirections->at(i).offset;
7971 return redirections->at(i).replacement;
7974 *offset = QPoint(0, 0);
7979 void qt_painter_removePaintDevice(QPaintDevice *dev)
7981 if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
7986 mutex = globalRedirectionsMutex();
7988 // ignore the missing mutex, since we could be called from
7989 // a destructor, and destructors shall not throw
7991 QMutexLocker locker(mutex);
7992 QPaintDeviceRedirectionList *redirections = 0;
7994 redirections = globalRedirections();
7996 // do nothing - code below is safe with redirections being 0.
7999 for (int i = 0; i < redirections->size(); ) {
8000 if(redirections->at(i) == dev || redirections->at(i).replacement == dev)
8001 redirections->removeAt(i);
8008 void qt_format_text(const QFont &fnt, const QRectF &_r,
8009 int tf, const QString& str, QRectF *brect,
8010 int tabstops, int *ta, int tabarraylen,
8013 qt_format_text(fnt, _r,
8015 tabstops, ta, tabarraylen,
8018 void qt_format_text(const QFont &fnt, const QRectF &_r,
8019 int tf, const QTextOption *option, const QString& str, QRectF *brect,
8020 int tabstops, int *ta, int tabarraylen,
8024 Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
8027 tf |= option->alignment();
8028 if (option->wrapMode() != QTextOption::NoWrap)
8029 tf |= Qt::TextWordWrap;
8031 if (option->flags() & QTextOption::IncludeTrailingSpaces)
8032 tf |= Qt::TextIncludeTrailingSpaces;
8034 if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
8035 tf |= Qt::TextExpandTabs;
8038 // we need to copy r here to protect against the case (&r == brect).
8041 bool dontclip = (tf & Qt::TextDontClip);
8042 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
8043 bool singleline = (tf & Qt::TextSingleLine);
8044 bool showmnemonic = (tf & Qt::TextShowMnemonic);
8045 bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
8047 Qt::LayoutDirection layout_direction;
8048 if (tf & Qt::TextForceLeftToRight)
8049 layout_direction = Qt::LeftToRight;
8050 else if (tf & Qt::TextForceRightToLeft)
8051 layout_direction = Qt::RightToLeft;
8053 layout_direction = option->textDirection();
8055 layout_direction = painter->layoutDirection();
8057 layout_direction = Qt::LeftToRight;
8059 tf = QStyle::visualAlignment(layout_direction, QFlag(tf));
8061 bool isRightToLeft = layout_direction == Qt::RightToLeft;
8062 bool expandtabs = ((tf & Qt::TextExpandTabs) &&
8063 (((tf & Qt::AlignLeft) && !isRightToLeft) ||
8064 ((tf & Qt::AlignRight) && isRightToLeft)));
8067 tf |= Qt::TextDontPrint;
8069 uint maxUnderlines = 0;
8070 int numUnderlines = 0;
8071 QVarLengthArray<int, 32> underlinePositions(1);
8073 QFontMetricsF fm(fnt);
8076 start_lengthVariant:
8077 bool hasMoreLengthVariants = false;
8078 // compatible behaviour to the old implementation. Replace
8080 int old_offset = offset;
8081 for (; offset < text.length(); offset++) {
8082 QChar chr = text.at(offset);
8083 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
8084 text[offset] = QLatin1Char(' ');
8085 } else if (chr == QLatin1Char('\n')) {
8086 text[offset] = QChar::LineSeparator;
8087 } else if (chr == QLatin1Char('&')) {
8089 } else if (chr == QLatin1Char('\t')) {
8091 text[offset] = QLatin1Char(' ');
8092 } else if (!tabarraylen && !tabstops) {
8093 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
8095 } else if (chr == QChar(ushort(0x9c))) {
8096 // string with multiple length variants
8097 hasMoreLengthVariants = true;
8102 int length = offset - old_offset;
8103 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
8104 underlinePositions.resize(maxUnderlines + 1);
8106 QChar *cout = text.data() + old_offset;
8110 if (*cin == QLatin1Char('&')) {
8116 if (*cin != QLatin1Char('&') && !hidemnmemonic)
8117 underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
8126 // no need to do extra work for underlines if we don't paint
8127 if (tf & Qt::TextDontPrint)
8130 underlinePositions[numUnderlines] = -1;
8134 QString finalText = text.mid(old_offset, length);
8135 QStackTextEngine engine(finalText, fnt);
8137 engine.option = *option;
8140 if (engine.option.tabStop() < 0 && tabstops > 0)
8141 engine.option.setTabStop(tabstops);
8143 if (engine.option.tabs().isEmpty() && ta) {
8145 for (int i = 0; i < tabarraylen; i++)
8146 tabs.append(qreal(ta[i]));
8147 engine.option.setTabArray(tabs);
8150 engine.option.setTextDirection(layout_direction);
8151 if (tf & Qt::AlignJustify)
8152 engine.option.setAlignment(Qt::AlignJustify);
8154 engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
8156 if (!option && (tf & Qt::TextWrapAnywhere))
8157 engine.option.setWrapMode(QTextOption::WrapAnywhere);
8159 if (tf & Qt::TextJustificationForced)
8160 engine.forceJustification = true;
8161 QTextLayout textLayout(&engine);
8162 textLayout.setCacheEnabled(true);
8163 textLayout.engine()->underlinePositions = underlinePositions.data();
8165 if (finalText.isEmpty()) {
8166 height = fm.height();
8168 tf |= Qt::TextDontPrint;
8170 qreal lineWidth = 0x01000000;
8171 if (wordwrap || (tf & Qt::TextJustificationForced))
8172 lineWidth = qMax<qreal>(0, r.width());
8174 tf |= Qt::TextIncludeTrailingSpaces;
8175 textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
8176 textLayout.beginLayout();
8178 qreal leading = fm.leading();
8182 QTextLine l = textLayout.createLine();
8186 l.setLineWidth(lineWidth);
8188 l.setPosition(QPointF(0., height));
8189 height += l.height();
8190 width = qMax(width, l.naturalTextWidth());
8191 if (!dontclip && !brect && height >= r.height())
8194 textLayout.endLayout();
8199 if (tf & Qt::AlignBottom) {
8200 yoff = r.height() - height;
8201 } else if (tf & Qt::AlignVCenter) {
8202 yoff = (r.height() - height)/2;
8204 QTransform::TransformationType type = painter->transform().type();
8205 if (type <= QTransform::TxScale) {
8206 // do the rounding manually to work around inconsistencies
8207 // in the paint engines when drawing on floating point offsets
8208 const qreal scale = painter->transform().m22();
8210 yoff = -qRound(-yoff * scale) / scale;
8214 if (tf & Qt::AlignRight) {
8215 xoff = r.width() - width;
8216 } else if (tf & Qt::AlignHCenter) {
8217 xoff = (r.width() - width)/2;
8219 QTransform::TransformationType type = painter->transform().type();
8220 if (type <= QTransform::TxScale) {
8221 // do the rounding manually to work around inconsistencies
8222 // in the paint engines when drawing on floating point offsets
8223 const qreal scale = painter->transform().m11();
8225 xoff = qRound(xoff * scale) / scale;
8229 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
8231 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
8233 goto start_lengthVariant;
8238 if (!(tf & Qt::TextDontPrint)) {
8239 bool restore = false;
8240 if (!dontclip && !r.contains(bounds)) {
8243 painter->setClipRect(r, Qt::IntersectClip);
8246 for (int i = 0; i < textLayout.lineCount(); i++) {
8247 QTextLine line = textLayout.lineAt(i);
8249 qreal advance = line.horizontalAdvance();
8251 if (tf & Qt::AlignRight) {
8252 QTextEngine *eng = textLayout.engine();
8253 xoff = r.width() - advance -
8254 eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
8256 else if (tf & Qt::AlignHCenter)
8257 xoff = (r.width() - advance) / 2;
8259 line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
8269 Sets the layout direction used by the painter when drawing text,
8270 to the specified \a direction.
8272 The default is Qt::LayoutDirectionAuto, which will implicitly determine the
8273 direction from the text drawn.
8275 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
8277 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
8281 d->state->layoutDirection = direction;
8285 Returns the layout direction used by the painter when drawing text.
8287 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
8289 Qt::LayoutDirection QPainter::layoutDirection() const
8291 Q_D(const QPainter);
8292 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
8295 QPainterState::QPainterState(const QPainterState *s)
8296 : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
8297 pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
8298 clipRegion(s->clipRegion), clipPath(s->clipPath),
8299 clipOperation(s->clipOperation),
8300 renderHints(s->renderHints), clipInfo(s->clipInfo),
8301 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
8302 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
8303 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
8304 opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
8305 clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
8306 layoutDirection(s->layoutDirection),
8307 composition_mode(s->composition_mode),
8308 emulationSpecifier(s->emulationSpecifier), changeFlags(0)
8310 dirtyFlags = s->dirtyFlags;
8313 QPainterState::QPainterState()
8314 : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
8316 wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
8317 opacity(1), WxF(false), VxF(false), clipEnabled(true),
8318 bgMode(Qt::TransparentMode), painter(0),
8319 layoutDirection(QApplication::layoutDirection()),
8320 composition_mode(QPainter::CompositionMode_SourceOver),
8321 emulationSpecifier(0), changeFlags(0)
8326 QPainterState::~QPainterState()
8330 void QPainterState::init(QPainter *p) {
8331 bgBrush = Qt::white;
8332 bgMode = Qt::TransparentMode;
8336 wx = wy = ww = wh = 0;
8337 vx = vy = vw = vh = 0;
8340 brushOrigin = QPointF(0, 0);
8342 font = deviceFont = QFont();
8343 clipRegion = QRegion();
8344 clipPath = QPainterPath();
8345 clipOperation = Qt::NoClip;
8347 worldMatrix.reset();
8349 layoutDirection = QApplication::layoutDirection();
8350 composition_mode = QPainter::CompositionMode_SourceOver;
8351 emulationSpecifier = 0;
8359 static void bitBlt_helper(QPaintDevice *dst, const QPoint &dp,
8360 const QPaintDevice *src, const QRect &sr, bool)
8365 if (src->devType() == QInternal::Pixmap) {
8366 const QPixmap *pixmap = static_cast<const QPixmap *>(src);
8368 pt.drawPixmap(dp, *pixmap, sr);
8371 qWarning("QPainter: bitBlt only works when source is of type pixmap");
8375 void bitBlt(QPaintDevice *dst, int dx, int dy,
8376 const QPaintDevice *src, int sx, int sy, int sw, int sh,
8379 bitBlt_helper(dst, QPoint(dx, dy), src, QRect(sx, sy, sw, sh), ignoreMask);
8382 void bitBlt(QPaintDevice *dst, const QPoint &dp, const QPaintDevice *src, const QRect &sr, bool ignoreMask)
8384 bitBlt_helper(dst, dp, src, sr, ignoreMask);
8387 void bitBlt(QPaintDevice *dst, int dx, int dy,
8388 const QImage *src, int sx, int sy, int sw, int sh, int fl)
8390 Qt::ImageConversionFlags flags(fl);
8391 QPixmap srcPixmap = QPixmap::fromImage(*src, flags);
8392 bitBlt_helper(dst, QPoint(dx, dy), &srcPixmap, QRect(sx, sy, sw, sh), false);
8395 #endif // QT3_SUPPORT
8398 \fn void QPainter::setBackgroundColor(const QColor &color)
8400 Use setBackground() instead.
8404 \fn const QColor &QPainter::backgroundColor() const
8406 Use background() and QBrush::color() instead.
8409 QColor myColor = backgroundColor();
8411 QColor myColor = background().color();
8414 Note that the background can be a complex brush such as a texture
8419 \fn void QPainter::drawText(int x, int y, const QString &text, int pos, int length)
8422 Use drawText() combined with QString::mid() instead.
8425 QPainter painter(this);
8426 painter.drawText(x, y, text, pos, length);
8428 QPainter painter(this);
8429 painter.drawText(x, y, text.mid(pos, length));
8434 \fn void QPainter::drawText(const QPoint &point, const QString &text, int pos, int length)
8437 Use drawText() combined with QString::mid() instead.
8440 QPainter painter(this);
8441 painter.drawText(point, text, pos, length);
8443 QPainter painter(this);
8444 painter.drawText(point, text.mid(pos, length));
8449 \fn void QPainter::drawText(int x, int y, const QString &text, int length)
8452 Use drawText() combined with QString::left() instead.
8455 QPainter painter(this);
8456 painter.drawText(x, y, text, length);
8458 QPainter painter(this);
8459 painter.drawText(x, y, text.left(length));
8464 \fn void QPainter::drawText(const QPoint &point, const QString &text, int length)
8467 Use drawText() combined with QString::left() instead.
8470 QPainter painter(this);
8471 painter.drawText(point, text, length);
8473 QPainter painter(this);
8474 painter.drawText(point, text.left(length));
8479 \fn bool QPainter::begin(QPaintDevice *device, const QWidget *init)
8482 Use begin() instead.
8484 If the paint \a device is a QWidget, QPainter is initialized after
8485 the widget's settings automatically. Otherwise, you must call the
8486 initFrom() function to initialize the painters pen, background and
8487 font to the same as any given widget.
8490 QPainter painter(this);
8491 painter.begin(device, init);
8493 QPainter painter(this);
8494 painter.begin(device);
8495 painter.initFrom(init);
8500 \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
8501 Qt::ImageConversionFlags flags)
8503 Draws the rectangular portion \a source of the given \a image
8504 into the \a target rectangle in the paint device.
8506 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8508 If the image needs to be modified to fit in a lower-resolution
8509 result (e.g. converting from 32-bit to 8-bit), use the \a flags to
8510 specify how you would prefer this to happen.
8515 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 20
8522 \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
8523 Qt::ImageConversionFlags flags)
8526 Draws the rectangular portion \a source of the given \a image
8527 into the \a target rectangle in the paint device.
8529 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8533 \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
8537 Draws the given \a image at the given \a point.
8541 \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
8545 Draws the given \a image at the given \a point.
8549 \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
8550 Qt::ImageConversionFlags flags = 0)
8554 Draws the rectangular portion \a source of the given \a image with
8555 its origin at the given \a point.
8559 \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
8560 Qt::ImageConversionFlags flags = 0)
8563 Draws the rectangular portion \a source of the given \a image with
8564 its origin at the given \a point.
8568 \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
8572 Draws the given \a image into the given \a rectangle.
8574 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8578 \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
8582 Draws the given \a image into the given \a rectangle.
8584 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8588 \fn void QPainter::drawImage(int x, int y, const QImage &image,
8589 int sx, int sy, int sw, int sh,
8590 Qt::ImageConversionFlags flags)
8593 Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
8596 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
8597 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
8598 image that is to be drawn. The default is (0, 0).
8600 (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
8601 The default, (0, 0) (and negative) means all the way to the
8602 bottom-right of the image.
8606 \fn void QPainter::redirect(QPaintDevice *pdev, QPaintDevice *replacement)
8608 Use setRedirected() instead.
8612 \fn QPaintDevice *QPainter::redirect(QPaintDevice *pdev)
8614 Use redirected() instead.
8618 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
8619 const QString &text, int length)
8622 Returns the bounding rectangle for the given \a length of the \a
8623 text constrained by the provided \a rectangle.
8625 Use boundingRect() combined with QString::left() instead.
8628 QRect rectangle = boundingRect(rect, flags, text, length);
8630 QRect rectangle = boundingRect(rect, flags, text.left(length));
8635 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text,
8636 int length, QRect *br)
8639 Use drawText() combined with QString::left() instead.
8642 QPainter painter(this);
8643 painter.drawText(rectangle, flags, text, length, br );
8645 QPainter painter(this);
8646 painter.drawText(rectangle, flags, text.left(length), br );
8651 \fn QRect QPainter::boundingRect(int x, int y, int width, int height, int flags,
8652 const QString &text, int length);
8656 Returns the bounding rectangle for the given \a length of the \a
8657 text constrained by the rectangle that begins at point (\a{x},
8658 \a{y}) with the given \a width and \a height.
8660 Use boundingRect() combined with QString::left() instead.
8663 QRect rectangle = boundingRect(x, y, width, height, flags, text, length);
8665 QRect rectangle = boundingRect(x, y, width, height, flags, text.left(length));
8670 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
8671 const QString &text, int length, QRect *br)
8675 Use drawText() combined with QString::left() instead.
8678 QPainter painter(this);
8679 painter.drawText(x, y, width, height, flags, text, length, br );
8681 QPainter painter(this);
8682 painter.drawText(x, y, width, height, flags, text.left(length), br );
8688 \class QPaintEngineState
8691 \brief The QPaintEngineState class provides information about the
8692 active paint engine's current state.
8695 QPaintEngineState records which properties that have changed since
8696 the last time the paint engine was updated, as well as their
8699 Which properties that have changed can at any time be retrieved
8700 using the state() function. This function returns an instance of
8701 the QPaintEngine::DirtyFlags type which stores an OR combination
8702 of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
8703 enum defines whether a property has changed since the last update
8706 If a property is marked with a dirty flag, its current value can
8707 be retrieved using the corresponding get function:
8712 \header \o Property Flag \o Current Property Value
8713 \row \o QPaintEngine::DirtyBackground \o backgroundBrush()
8714 \row \o QPaintEngine::DirtyBackgroundMode \o backgroundMode()
8715 \row \o QPaintEngine::DirtyBrush \o brush()
8716 \row \o QPaintEngine::DirtyBrushOrigin \o brushOrigin()
8717 \row \o QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
8719 \row \o QPaintEngine::DirtyClipPath \o clipPath()
8720 \row \o QPaintEngine::DirtyClipRegion \o clipRegion()
8721 \row \o QPaintEngine::DirtyCompositionMode \o compositionMode()
8722 \row \o QPaintEngine::DirtyFont \o font()
8723 \row \o QPaintEngine::DirtyTransform \o transform()
8724 \row \o QPaintEngine::DirtyClipEnabled \o isClipEnabled()
8725 \row \o QPaintEngine::DirtyPen \o pen()
8726 \row \o QPaintEngine::DirtyHints \o renderHints()
8729 The QPaintEngineState class also provide the painter() function
8730 which returns a pointer to the painter that is currently updating
8733 An instance of this class, representing the current state of the
8734 active paint engine, is passed as argument to the
8735 QPaintEngine::updateState() function. The only situation in which
8736 you will have to use this class directly is when implementing your
8744 \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
8746 Returns a combination of flags identifying the set of properties
8747 that need to be updated when updating the paint engine's state
8748 (i.e. during a call to the QPaintEngine::updateState() function).
8750 \sa QPaintEngine::updateState()
8755 Returns the pen in the current paint engine state.
8757 This variable should only be used when the state() returns a
8758 combination which includes the QPaintEngine::DirtyPen flag.
8760 \sa state(), QPaintEngine::updateState()
8763 QPen QPaintEngineState::pen() const
8765 return static_cast<const QPainterState *>(this)->pen;
8769 Returns the brush in the current paint engine state.
8771 This variable should only be used when the state() returns a
8772 combination which includes the QPaintEngine::DirtyBrush flag.
8774 \sa state(), QPaintEngine::updateState()
8777 QBrush QPaintEngineState::brush() const
8779 return static_cast<const QPainterState *>(this)->brush;
8783 Returns the brush origin in the current paint engine state.
8785 This variable should only be used when the state() returns a
8786 combination which includes the QPaintEngine::DirtyBrushOrigin flag.
8788 \sa state(), QPaintEngine::updateState()
8791 QPointF QPaintEngineState::brushOrigin() const
8793 return static_cast<const QPainterState *>(this)->brushOrigin;
8797 Returns the background brush in the current paint engine state.
8799 This variable should only be used when the state() returns a
8800 combination which includes the QPaintEngine::DirtyBackground flag.
8802 \sa state(), QPaintEngine::updateState()
8805 QBrush QPaintEngineState::backgroundBrush() const
8807 return static_cast<const QPainterState *>(this)->bgBrush;
8811 Returns the background mode in the current paint engine
8814 This variable should only be used when the state() returns a
8815 combination which includes the QPaintEngine::DirtyBackgroundMode flag.
8817 \sa state(), QPaintEngine::updateState()
8820 Qt::BGMode QPaintEngineState::backgroundMode() const
8822 return static_cast<const QPainterState *>(this)->bgMode;
8826 Returns the font in the current paint engine
8829 This variable should only be used when the state() returns a
8830 combination which includes the QPaintEngine::DirtyFont flag.
8832 \sa state(), QPaintEngine::updateState()
8835 QFont QPaintEngineState::font() const
8837 return static_cast<const QPainterState *>(this)->font;
8844 Returns the matrix in the current paint engine
8847 \note It is advisable to use transform() instead of this function to
8848 preserve the properties of perspective transformations.
8850 This variable should only be used when the state() returns a
8851 combination which includes the QPaintEngine::DirtyTransform flag.
8853 \sa state(), QPaintEngine::updateState()
8856 QMatrix QPaintEngineState::matrix() const
8858 const QPainterState *st = static_cast<const QPainterState *>(this);
8860 return st->matrix.toAffine();
8866 Returns the matrix in the current paint engine state.
8868 This variable should only be used when the state() returns a
8869 combination which includes the QPaintEngine::DirtyTransform flag.
8871 \sa state(), QPaintEngine::updateState()
8875 QTransform QPaintEngineState::transform() const
8877 const QPainterState *st = static_cast<const QPainterState *>(this);
8884 Returns the clip operation in the current paint engine
8887 This variable should only be used when the state() returns a
8888 combination which includes either the QPaintEngine::DirtyClipPath
8889 or the QPaintEngine::DirtyClipRegion flag.
8891 \sa state(), QPaintEngine::updateState()
8894 Qt::ClipOperation QPaintEngineState::clipOperation() const
8896 return static_cast<const QPainterState *>(this)->clipOperation;
8902 Returns whether the coordinate of the fill have been specified
8903 as bounded by the current rendering operation and have to be
8904 resolved (about the currently rendered primitive).
8906 bool QPaintEngineState::brushNeedsResolving() const
8908 const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
8909 return needsResolving(brush);
8916 Returns whether the coordinate of the stroke have been specified
8917 as bounded by the current rendering operation and have to be
8918 resolved (about the currently rendered primitive).
8920 bool QPaintEngineState::penNeedsResolving() const
8922 const QPen &pen = static_cast<const QPainterState *>(this)->pen;
8923 return needsResolving(pen.brush());
8927 Returns the clip region in the current paint engine state.
8929 This variable should only be used when the state() returns a
8930 combination which includes the QPaintEngine::DirtyClipRegion flag.
8932 \sa state(), QPaintEngine::updateState()
8935 QRegion QPaintEngineState::clipRegion() const
8937 return static_cast<const QPainterState *>(this)->clipRegion;
8941 Returns the clip path in the current paint engine state.
8943 This variable should only be used when the state() returns a
8944 combination which includes the QPaintEngine::DirtyClipPath flag.
8946 \sa state(), QPaintEngine::updateState()
8949 QPainterPath QPaintEngineState::clipPath() const
8951 return static_cast<const QPainterState *>(this)->clipPath;
8955 Returns whether clipping is enabled or not in the current paint
8958 This variable should only be used when the state() returns a
8959 combination which includes the QPaintEngine::DirtyClipEnabled
8962 \sa state(), QPaintEngine::updateState()
8965 bool QPaintEngineState::isClipEnabled() const
8967 return static_cast<const QPainterState *>(this)->clipEnabled;
8971 Returns the render hints in the current paint engine state.
8973 This variable should only be used when the state() returns a
8974 combination which includes the QPaintEngine::DirtyHints
8977 \sa state(), QPaintEngine::updateState()
8980 QPainter::RenderHints QPaintEngineState::renderHints() const
8982 return static_cast<const QPainterState *>(this)->renderHints;
8986 Returns the composition mode in the current paint engine state.
8988 This variable should only be used when the state() returns a
8989 combination which includes the QPaintEngine::DirtyCompositionMode
8992 \sa state(), QPaintEngine::updateState()
8995 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8997 return static_cast<const QPainterState *>(this)->composition_mode;
9002 Returns a pointer to the painter currently updating the paint
9006 QPainter *QPaintEngineState::painter() const
9008 return static_cast<const QPainterState *>(this)->painter;
9015 Returns the opacity in the current paint engine state.
9018 qreal QPaintEngineState::opacity() const
9020 return static_cast<const QPainterState *>(this)->opacity;
9026 Sets the world transformation matrix.
9027 If \a combine is true, the specified \a transform is combined with
9028 the current matrix; otherwise it replaces the current matrix.
9030 \sa transform() setWorldTransform()
9033 void QPainter::setTransform(const QTransform &transform, bool combine )
9035 setWorldTransform(transform, combine);
9039 Returns the world transformation matrix.
9041 \sa worldTransform()
9044 const QTransform & QPainter::transform() const
9046 return worldTransform();
9051 Returns the matrix that transforms from logical coordinates to
9052 device coordinates of the platform dependent paint device.
9054 This function is \e only needed when using platform painting
9055 commands on the platform dependent handle (Qt::HANDLE), and the
9056 platform does not do transformations nativly.
9058 The QPaintEngine::PaintEngineFeature enum can be queried to
9059 determine whether the platform performs the transformations or
9062 \sa worldTransform(), QPaintEngine::hasFeature(),
9065 const QTransform & QPainter::deviceTransform() const
9067 Q_D(const QPainter);
9069 qWarning("QPainter::deviceTransform: Painter not active");
9070 return d->fakeState()->transform;
9072 return d->state->matrix;
9077 Resets any transformations that were made using translate(),
9078 scale(), shear(), rotate(), setWorldTransform(), setViewport()
9081 \sa {Coordinate Transformations}
9084 void QPainter::resetTransform()
9087 #ifdef QT_DEBUG_DRAW
9088 if (qt_show_painter_debug_output)
9089 printf("QPainter::resetMatrix()\n");
9092 qWarning("QPainter::resetMatrix: Painter not active");
9096 d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins
9097 d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
9098 d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
9099 d->state->worldMatrix = QTransform();
9100 setMatrixEnabled(false);
9101 setViewTransformEnabled(false);
9103 d->extended->transformChanged();
9105 d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
9109 Sets the world transformation matrix.
9110 If \a combine is true, the specified \a matrix is combined with the current matrix;
9111 otherwise it replaces the current matrix.
9113 \sa transform(), setTransform()
9116 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
9121 qWarning("QPainter::setWorldTransform: Painter not active");
9126 d->state->worldMatrix = matrix * d->state->worldMatrix; // combines
9128 d->state->worldMatrix = matrix; // set new matrix
9130 d->state->WxF = true;
9135 Returns the world transformation matrix.
9138 const QTransform & QPainter::worldTransform() const
9140 Q_D(const QPainter);
9142 qWarning("QPainter::worldTransform: Painter not active");
9143 return d->fakeState()->transform;
9145 return d->state->worldMatrix;
9149 Returns the transformation matrix combining the current
9150 window/viewport and world transformation.
9152 \sa setWorldTransform(), setWindow(), setViewport()
9155 QTransform QPainter::combinedTransform() const
9157 Q_D(const QPainter);
9159 qWarning("QPainter::combinedTransform: Painter not active");
9160 return QTransform();
9162 return d->state->worldMatrix * d->viewTransform();
9168 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
9169 at multiple positions with different scale, rotation and opacity. \a
9170 fragments is an array of \a fragmentCount elements specifying the
9171 parameters used to draw each pixmap fragment. The \a hints
9172 parameter can be used to pass in drawing hints.
9174 This function is potentially faster than multiple calls to drawPixmap(),
9175 since the backend can optimize state changes.
9177 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
9180 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
9181 const QPixmap &pixmap, PixmapFragmentHints hints)
9185 if (!d->engine || pixmap.isNull())
9189 for (int i = 0; i < fragmentCount; ++i) {
9190 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
9191 fragments[i].width, fragments[i].height);
9192 if (!(QRectF(pixmap.rect()).contains(sourceRect)))
9193 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
9197 if (d->engine->isExtended()) {
9198 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
9200 qreal oldOpacity = opacity();
9201 QTransform oldTransform = transform();
9203 for (int i = 0; i < fragmentCount; ++i) {
9204 QTransform transform = oldTransform;
9207 if (fragments[i].rotation == 0) {
9208 xOffset = fragments[i].x;
9209 yOffset = fragments[i].y;
9211 transform.translate(fragments[i].x, fragments[i].y);
9212 transform.rotate(fragments[i].rotation);
9214 setOpacity(oldOpacity * fragments[i].opacity);
9215 setTransform(transform);
9217 qreal w = fragments[i].scaleX * fragments[i].width;
9218 qreal h = fragments[i].scaleY * fragments[i].height;
9219 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
9220 fragments[i].width, fragments[i].height);
9221 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
9224 setOpacity(oldOpacity);
9225 setTransform(oldTransform);
9231 \class QPainter::PixmapFragment
9233 \brief This class is used in conjunction with the
9234 QPainter::drawPixmapFragments() function to specify how a pixmap, or
9235 sub-rect of a pixmap, is drawn.
9237 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
9238 as a source rectangle within the pixmap passed into the
9239 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
9240 width and \a height are used to calculate the target rectangle that is
9241 drawn. \a x and \a y denotes the center of the target rectangle. The \a
9242 width and \a height in the target rectangle is scaled by the \a scaleX and
9243 \a scaleY values. The resulting target rectangle is then rotated \a
9244 rotation degrees around the \a x, \a y center point.
9246 \sa QPainter::drawPixmapFragments()
9252 This is a convenience function that returns a QPainter::PixmapFragment that is
9253 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
9254 rotation, \a opacity parameters.
9257 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
9258 qreal scaleX, qreal scaleY, qreal rotation,
9261 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
9262 sourceRect.height(), scaleX, scaleY, rotation, opacity};
9267 \variable QPainter::PixmapFragment::x
9268 \brief the x coordinate of center point in the target rectangle.
9272 \variable QPainter::PixmapFragment::y
9273 \brief the y coordinate of the center point in the target rectangle.
9277 \variable QPainter::PixmapFragment::sourceLeft
9278 \brief the left coordinate of the source rectangle.
9282 \variable QPainter::PixmapFragment::sourceTop
9283 \brief the top coordinate of the source rectangle.
9287 \variable QPainter::PixmapFragment::width
9289 \brief the width of the source rectangle and is used to calculate the width
9290 of the target rectangle.
9294 \variable QPainter::PixmapFragment::height
9296 \brief the height of the source rectangle and is used to calculate the
9297 height of the target rectangle.
9301 \variable QPainter::PixmapFragment::scaleX
9302 \brief the horizontal scale of the target rectangle.
9306 \variable QPainter::PixmapFragment::scaleY
9307 \brief the vertical scale of the target rectangle.
9311 \variable QPainter::PixmapFragment::rotation
9313 \brief the rotation of the target rectangle in degrees. The target
9314 rectangle is rotated after it has been scaled.
9318 \variable QPainter::PixmapFragment::opacity
9320 \brief the opacity of the target rectangle, where 0.0 is fully transparent
9321 and 1.0 is fully opaque.
9327 \enum QPainter::PixmapFragmentHint
9329 \value OpaqueHint Indicates that the pixmap fragments to be drawn are
9330 opaque. Opaque fragments are potentially faster to draw.
9332 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
9335 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
9337 p->draw_helper(path, operation);
9340 /*! \fn Display *QPaintDevice::x11Display() const
9341 Use QX11Info::display() instead.
9344 Display *display = widget->x11Display();
9346 Display *display = QX11Info::display();
9349 \sa QWidget::x11Info(), QX11Info::display()
9352 /*! \fn int QPaintDevice::x11Screen() const
9353 Use QX11Info::screen() instead.
9356 int screen = widget->x11Screen();
9358 int screen = widget->x11Info().screen();
9361 \sa QWidget::x11Info(), QPixmap::x11Info()
9364 /*! \fn void *QPaintDevice::x11Visual() const
9365 Use QX11Info::visual() instead.
9368 void *visual = widget->x11Visual();
9370 void *visual = widget->x11Info().visual();
9373 \sa QWidget::x11Info(), QPixmap::x11Info()
9376 /*! \fn int QPaintDevice::x11Depth() const
9377 Use QX11Info::depth() instead.
9380 int depth = widget->x11Depth();
9382 int depth = widget->x11Info().depth();
9385 \sa QWidget::x11Info(), QPixmap::x11Info()
9388 /*! \fn int QPaintDevice::x11Cells() const
9389 Use QX11Info::cells() instead.
9392 int cells = widget->x11Cells();
9394 int cells = widget->x11Info().cells();
9397 \sa QWidget::x11Info(), QPixmap::x11Info()
9400 /*! \fn Qt::HANDLE QPaintDevice::x11Colormap() const
9401 Use QX11Info::colormap() instead.
9404 unsigned long screen = widget->x11Colormap();
9406 unsigned long screen = widget->x11Info().colormap();
9409 \sa QWidget::x11Info(), QPixmap::x11Info()
9412 /*! \fn bool QPaintDevice::x11DefaultColormap() const
9413 Use QX11Info::defaultColormap() instead.
9416 bool isDefault = widget->x11DefaultColormap();
9418 bool isDefault = widget->x11Info().defaultColormap();
9421 \sa QWidget::x11Info(), QPixmap::x11Info()
9424 /*! \fn bool QPaintDevice::x11DefaultVisual() const
9425 Use QX11Info::defaultVisual() instead.
9428 bool isDefault = widget->x11DefaultVisual();
9430 bool isDefault = widget->x11Info().defaultVisual();
9433 \sa QWidget::x11Info(), QPixmap::x11Info()
9436 /*! \fn void *QPaintDevice::x11AppVisual(int screen)
9437 Use QX11Info::visual() instead.
9440 void *visual = QPaintDevice::x11AppVisual(screen);
9442 void *visual = qApp->x11Info(screen).visual();
9445 \sa QWidget::x11Info(), QPixmap::x11Info()
9448 /*! \fn Qt::HANDLE QPaintDevice::x11AppColormap(int screen)
9449 Use QX11Info::colormap() instead.
9452 unsigned long colormap = QPaintDevice::x11AppColormap(screen);
9454 unsigned long colormap = qApp->x11Info(screen).colormap();
9457 \sa QWidget::x11Info(), QPixmap::x11Info()
9460 /*! \fn Display *QPaintDevice::x11AppDisplay()
9461 Use QX11Info::display() instead.
9464 Display *display = QPaintDevice::x11AppDisplay();
9466 Display *display = qApp->x11Info().display();
9469 \sa QWidget::x11Info(), QPixmap::x11Info()
9472 /*! \fn int QPaintDevice::x11AppScreen()
9473 Use QX11Info::screen() instead.
9476 int screen = QPaintDevice::x11AppScreen();
9478 int screen = qApp->x11Info().screen();
9481 \sa QWidget::x11Info(), QPixmap::x11Info()
9484 /*! \fn int QPaintDevice::x11AppDepth(int screen)
9485 Use QX11Info::depth() instead.
9488 int depth = QPaintDevice::x11AppDepth(screen);
9490 int depth = qApp->x11Info(screen).depth();
9493 \sa QWidget::x11Info(), QPixmap::x11Info()
9496 /*! \fn int QPaintDevice::x11AppCells(int screen)
9497 Use QX11Info::cells() instead.
9500 int cells = QPaintDevice::x11AppCells(screen);
9502 int cells = qApp->x11Info(screen).cells();
9505 \sa QWidget::x11Info(), QPixmap::x11Info()
9508 /*! \fn Qt::HANDLE QPaintDevice::x11AppRootWindow(int screen)
9509 Use QX11Info::appRootWindow() instead.
9512 unsigned long window = QPaintDevice::x11AppRootWindow(screen);
9514 unsigned long window = qApp->x11Info(screen).appRootWindow();
9517 \sa QWidget::x11Info(), QPixmap::x11Info()
9520 /*! \fn bool QPaintDevice::x11AppDefaultColormap(int screen)
9521 Use QX11Info::defaultColormap() instead.
9524 bool isDefault = QPaintDevice::x11AppDefaultColormap(screen);
9526 bool isDefault = qApp->x11Info(screen).defaultColormap();
9529 \sa QWidget::x11Info(), QPixmap::x11Info()
9532 /*! \fn bool QPaintDevice::x11AppDefaultVisual(int screen)
9533 Use QX11Info::defaultVisual() instead.
9536 bool isDefault = QPaintDevice::x11AppDefaultVisual(screen);
9538 bool isDefault = qApp->x11Info(screen).defaultVisual();
9541 \sa QWidget::x11Info(), QPixmap::x11Info()
9544 /*! \fn void QPaintDevice::x11SetAppDpiX(int dpi, int screen)
9545 Use QX11Info::setAppDpiX() instead.
9548 /*! \fn void QPaintDevice::x11SetAppDpiY(int dpi, int screen)
9549 Use QX11Info::setAppDpiY() instead.
9552 /*! \fn int QPaintDevice::x11AppDpiX(int screen)
9553 Use QX11Info::appDpiX() instead.
9556 bool isDefault = QPaintDevice::x11AppDpiX(screen);
9558 bool isDefault = qApp->x11Info(screen).appDpiX();
9561 \sa QWidget::x11Info(), QPixmap::x11Info()
9564 /*! \fn int QPaintDevice::x11AppDpiY(int screen)
9565 Use QX11Info::appDpiY() instead.
9568 bool isDefault = QPaintDevice::x11AppDpiY(screen);
9570 bool isDefault = qApp->x11Info(screen).appDpiY();
9573 \sa QWidget::x11Info(), QPixmap::x11Info()
9576 /*! \fn HDC QPaintDevice::getDC() const
9580 /*! \fn void QPaintDevice::releaseDC(HDC) const
9584 /*! \fn QWSDisplay *QPaintDevice::qwsDisplay()