1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
50 #include "qpaintdevice.h"
51 #include "qpaintengine.h"
53 #include "qpainter_p.h"
54 #include "qpainterpath.h"
56 #include "qpixmapcache.h"
58 #include "qtextlayout.h"
60 #include "qvarlengtharray.h"
61 #include "qstatictext.h"
62 #include "qglyphrun.h"
64 #include <qpa/qplatformtheme.h>
66 #include <private/qfontengine_p.h>
67 #include <private/qpaintengine_p.h>
68 #include <private/qemulationpaintengine_p.h>
69 #include <private/qpainterpath_p.h>
70 #include <private/qtextengine_p.h>
71 #include <private/qpaintengine_raster_p.h>
72 #include <private/qmath_p.h>
73 #include <private/qstatictext_p.h>
74 #include <private/qglyphrun_p.h>
75 #include <private/qhexstring_p.h>
76 #include <private/qguiapplication_p.h>
77 #include <private/qrawfont_p.h>
81 #define QGradient_StretchToDevice 0x10000000
82 #define QPaintEngine_OpaqueBackground 0x40000000
84 // #define QT_DEBUG_DRAW
86 bool qt_show_painter_debug_output = true;
89 extern QPixmap qt_pixmapForBrush(int style, bool invert);
91 void qt_format_text(const QFont &font,
92 const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
93 int tabstops, int* tabarray, int tabarraylen,
95 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
96 QTextCharFormat::UnderlineStyle underlineStyle,
97 QTextItem::RenderFlags flags, qreal width,
98 const QTextCharFormat &charFormat);
99 // Helper function to calculate left most position, width and flags for decoration drawing
100 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
101 const QFixedPoint *positions, int glyphCount,
102 QFontEngine *fontEngine, const QFont &font,
103 const QTextCharFormat &charFormat);
105 static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush)
107 switch (brush.style()) {
108 case Qt::LinearGradientPattern:
109 case Qt::RadialGradientPattern:
110 case Qt::ConicalGradientPattern:
111 return brush.gradient()->coordinateMode();
115 return QGradient::LogicalMode;
118 /* Returns true if the gradient requires stretch to device...*/
119 static inline bool check_gradient(const QBrush &brush)
121 return coordinateMode(brush) == QGradient::StretchToDeviceMode;
124 extern bool qHasPixmapTexture(const QBrush &);
126 static inline bool is_brush_transparent(const QBrush &brush) {
127 Qt::BrushStyle s = brush.style();
128 bool brushBitmap = qHasPixmapTexture(brush)
129 ? brush.texture().isQBitmap()
130 : (brush.textureImage().depth() == 1);
131 return ((s >= Qt::Dense1Pattern && s <= Qt::DiagCrossPattern)
132 || (s == Qt::TexturePattern && brushBitmap));
135 static inline bool is_pen_transparent(const QPen &pen) {
136 return pen.style() > Qt::SolidLine || is_brush_transparent(pen.brush());
139 /* Discards the emulation flags that are not relevant for line drawing
140 and returns the result
142 static inline uint line_emulation(uint emulation)
144 return emulation & (QPaintEngine::PrimitiveTransform
145 | QPaintEngine::AlphaBlend
146 | QPaintEngine::Antialiasing
147 | QPaintEngine::BrushStroke
148 | QPaintEngine::ConstantOpacity
149 | QGradient_StretchToDevice
150 | QPaintEngine::ObjectBoundingModeGradients
151 | QPaintEngine_OpaqueBackground);
155 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
158 case QInternal::Image:
159 case QInternal::Printer:
160 case QInternal::Picture:
161 // can be drawn onto these devices safely from any thread
165 if (!extraCondition && QThread::currentThread() != qApp->thread()) {
166 qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
175 void QPainterPrivate::checkEmulation()
178 if (extended->flags() & QPaintEngineEx::DoNotEmulate)
181 bool doEmulation = false;
182 if (state->bgMode == Qt::OpaqueMode)
185 const QGradient *bg = state->brush.gradient();
186 if (bg && bg->coordinateMode() > QGradient::LogicalMode)
189 const QGradient *pg = qpen_brush(state->pen).gradient();
190 if (pg && pg->coordinateMode() > QGradient::LogicalMode)
194 if (extended != emulationEngine) {
195 if (!emulationEngine)
196 emulationEngine = new QEmulationPaintEngine(extended);
197 extended = emulationEngine;
198 extended->setState(state);
200 } else if (emulationEngine == extended) {
201 extended = emulationEngine->real_engine;
206 QPainterPrivate::~QPainterPrivate()
208 delete emulationEngine;
209 for (int i=0; i<states.size(); ++i)
217 QTransform QPainterPrivate::viewTransform() const
220 qreal scaleW = qreal(state->vw)/qreal(state->ww);
221 qreal scaleH = qreal(state->vh)/qreal(state->wh);
222 return QTransform(scaleW, 0, 0, scaleH,
223 state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
231 Returns true if using a shared painter; otherwise false.
233 bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
238 QPainter *sp = pdev->sharedPainter();
242 // Save the current state of the shared painter and assign
243 // the current d_ptr to the shared painter's d_ptr.
245 if (!sp->d_ptr->d_ptrs) {
246 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
247 // redirections within the same paintEvent(), which should be enough
248 // in 99% of all cases). E.g: A renders B which renders C which renders D.
249 sp->d_ptr->d_ptrs_size = 4;
250 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
251 Q_CHECK_PTR(sp->d_ptr->d_ptrs);
252 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
253 // However, to support corner cases we grow the array dynamically if needed.
254 sp->d_ptr->d_ptrs_size <<= 1;
255 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
256 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
258 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
260 q->d_ptr.reset(sp->d_ptr.data());
262 Q_ASSERT(q->d_ptr->state);
264 // Now initialize the painter with correct widget properties.
267 pdev->redirected(&offset);
268 offset += q->d_ptr->engine->coordinateOffset();
270 // Update system rect.
271 q->d_ptr->state->ww = q->d_ptr->state->vw = pdev->width();
272 q->d_ptr->state->wh = q->d_ptr->state->vh = pdev->height();
275 if (q->d_ptr->state->WxF) {
276 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix;
277 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
278 q->d_ptr->state->worldMatrix = QTransform();
279 q->d_ptr->state->WxF = false;
281 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
283 q->d_ptr->updateMatrix();
285 QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
286 if (enginePrivate->currentClipDevice == pdev) {
287 enginePrivate->systemStateChanged();
291 // Update system transform and clip.
292 enginePrivate->currentClipDevice = pdev;
293 enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
297 void QPainterPrivate::detachPainterPrivate(QPainter *q)
299 Q_ASSERT(refcount > 1);
302 QPainterPrivate *original = d_ptrs[--refcount - 1];
304 inDestructor = false;
306 original->inDestructor = true;
307 } else if (!original) {
308 original = new QPainterPrivate(q);
311 d_ptrs[refcount - 1] = 0;
314 q->d_ptr.reset(original);
316 if (emulationEngine) {
317 extended = emulationEngine->real_engine;
318 delete emulationEngine;
324 void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op)
327 if (qt_show_painter_debug_output) {
328 printf("QPainter::drawHelper\n");
332 if (originalPath.isEmpty())
335 QPaintEngine::PaintEngineFeatures gradientStretch =
336 QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
337 | QPaintEngine::ObjectBoundingModeGradients);
339 const bool mustEmulateObjectBoundingModeGradients = extended
340 || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients)
341 && !engine->hasFeature(QPaintEngine::PatternTransform));
343 if (!(state->emulationSpecifier & ~gradientStretch)
344 && !mustEmulateObjectBoundingModeGradients) {
345 drawStretchedGradient(originalPath, op);
347 } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {
348 drawOpaqueBackground(originalPath, op);
354 qreal strokeOffsetX = 0, strokeOffsetY = 0;
356 QPainterPath path = originalPath * state->matrix;
357 QRectF pathBounds = path.boundingRect();
359 bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
361 qreal penWidth = state->pen.widthF();
366 // In case of complex xform
367 if (state->matrix.type() > QTransform::TxScale) {
368 QPainterPathStroker stroker;
369 stroker.setWidth(penWidth);
370 stroker.setJoinStyle(state->pen.joinStyle());
371 stroker.setCapStyle(state->pen.capStyle());
372 QPainterPath stroke = stroker.createStroke(originalPath);
373 strokeBounds = (stroke * state->matrix).boundingRect();
375 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);
376 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);
382 if (!strokeBounds.isEmpty()) {
383 absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
385 absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
386 .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
389 if (q->hasClipping()) {
390 bool hasPerspectiveTransform = false;
391 for (int i = 0; i < state->clipInfo.size(); ++i) {
392 const QPainterClipInfo &info = state->clipInfo.at(i);
393 if (info.matrix.type() == QTransform::TxProject) {
394 hasPerspectiveTransform = true;
398 // avoid mapping QRegions with perspective transforms
399 if (!hasPerspectiveTransform) {
400 // The trick with txinv and invMatrix is done in order to
401 // avoid transforming the clip to logical coordinates, and
402 // then back to device coordinates. This is a problem with
403 // QRegion/QRect based clips, since they use integer
404 // coordinates and converting to/from logical coordinates will
406 bool old_txinv = txinv;
407 QTransform old_invMatrix = invMatrix;
409 invMatrix = QTransform();
410 QPainterPath clipPath = q->clipPath();
411 QRectF r = clipPath.boundingRect().intersected(absPathRect);
412 absPathRect = r.toAlignedRect();
414 invMatrix = old_invMatrix;
418 // qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
419 // devMinX, devMinY, device->width(), device->height());
420 // qDebug() << " - matrix" << state->matrix;
421 // qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
422 // qDebug() << " - path.bounds" << path.boundingRect();
424 if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
427 QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
432 p.d_ptr->helper_device = helper_device;
434 p.setOpacity(state->opacity);
435 p.translate(-absPathRect.x(), -absPathRect.y());
436 p.setTransform(state->matrix, true);
437 p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
438 p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
439 p.setBackground(state->bgBrush);
440 p.setBackgroundMode(state->bgMode);
441 p.setBrushOrigin(state->brushOrigin);
443 p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);
444 p.setRenderHint(QPainter::SmoothPixmapTransform,
445 state->renderHints & QPainter::SmoothPixmapTransform);
447 p.drawPath(originalPath);
450 static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0;
451 if (do_fallback_overlay) {
452 QImage block(8, 8, QImage::Format_ARGB32_Premultiplied);
454 pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
455 pt.drawLine(0, 0, 8, 8);
458 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
460 p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
467 state->matrix = QTransform();
469 extended->transformChanged();
471 state->dirtyFlags |= QPaintEngine::DirtyTransform;
474 engine->drawImage(absPathRect,
476 QRectF(0, 0, absPathRect.width(), absPathRect.height()),
477 Qt::OrderedDither | Qt::OrderedAlphaDither);
481 void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op)
485 q->setBackgroundMode(Qt::TransparentMode);
487 if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
488 q->fillPath(path, state->bgBrush.color());
489 q->fillPath(path, state->brush);
492 if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
493 q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
494 q->strokePath(path, state->pen);
497 q->setBackgroundMode(Qt::OpaqueMode);
500 static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
502 Q_ASSERT(brush.style() >= Qt::LinearGradientPattern
503 && brush.style() <= Qt::ConicalGradientPattern);
505 QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
506 boundingRect.x(), boundingRect.y());
508 QGradient g = *brush.gradient();
509 g.setCoordinateMode(QGradient::LogicalMode);
512 b.setTransform(gradientToUser * b.transform());
516 void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op)
520 const qreal sw = helper_device->width();
521 const qreal sh = helper_device->height();
523 bool changedPen = false;
524 bool changedBrush = false;
525 bool needsFill = false;
527 const QPen pen = state->pen;
528 const QBrush brush = state->brush;
530 const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
531 const QGradient::CoordinateMode brushMode = coordinateMode(brush);
535 // Draw the xformed fill if the brush is a stretch gradient.
536 if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
537 if (brushMode == QGradient::StretchToDeviceMode) {
538 q->setPen(Qt::NoPen);
539 changedPen = pen.style() != Qt::NoPen;
543 const qreal isw = 1.0 / sw;
544 const qreal ish = 1.0 / sh;
545 QTransform inv(isw, 0, 0, ish, 0, 0);
546 engine->drawPath(path * inv);
551 if (brushMode == QGradient::ObjectBoundingMode) {
552 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
553 boundingRect = path.boundingRect();
554 q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
560 if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
561 // Draw the xformed outline if the pen is a stretch gradient.
562 if (penMode == QGradient::StretchToDeviceMode) {
563 q->setPen(Qt::NoPen);
568 engine->drawPath(path);
572 q->setBrush(pen.brush());
576 QPainterPathStroker stroker;
577 stroker.setDashPattern(pen.style());
578 stroker.setWidth(pen.widthF());
579 stroker.setJoinStyle(pen.joinStyle());
580 stroker.setCapStyle(pen.capStyle());
581 stroker.setMiterLimit(pen.miterLimit());
582 QPainterPath stroke = stroker.createStroke(path);
584 const qreal isw = 1.0 / sw;
585 const qreal ish = 1.0 / sh;
586 QTransform inv(isw, 0, 0, ish, 0, 0);
587 engine->drawPath(stroke * inv);
590 if (!needsFill && brush.style() != Qt::NoBrush) {
591 q->setBrush(Qt::NoBrush);
595 if (penMode == QGradient::ObjectBoundingMode) {
596 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
598 // avoid computing the bounding rect twice
599 if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
600 boundingRect = path.boundingRect();
603 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect));
606 } else if (changedPen) {
612 engine->drawPath(path);
614 } else if (needsFill) {
615 if (pen.style() != Qt::NoPen) {
616 q->setPen(Qt::NoPen);
621 engine->drawPath(path);
631 void QPainterPrivate::updateMatrix()
633 state->matrix = state->WxF ? state->worldMatrix : QTransform();
635 state->matrix *= viewTransform();
637 txinv = false; // no inverted matrix
638 state->matrix *= state->redirectionMatrix;
640 extended->transformChanged();
642 state->dirtyFlags |= QPaintEngine::DirtyTransform;
644 // printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
645 // qDebug() << " --- using matrix" << state->matrix << redirection_offset;
649 void QPainterPrivate::updateInvMatrix()
651 Q_ASSERT(txinv == false);
652 txinv = true; // creating inverted matrix
653 invMatrix = state->matrix.inverted();
656 extern bool qt_isExtendedRadialGradient(const QBrush &brush);
658 void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
661 bool linearGradient = false;
662 bool radialGradient = false;
663 bool extendedRadialGradient = false;
664 bool conicalGradient = false;
665 bool patternBrush = false;
667 bool complexXform = false;
671 // Pen and brush properties (we have to check both if one changes because the
672 // one that's unchanged can still be in a state which requires emulation)
673 if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) {
674 // Check Brush stroke emulation
675 if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke))
676 s->emulationSpecifier |= QPaintEngine::BrushStroke;
678 s->emulationSpecifier &= ~QPaintEngine::BrushStroke;
682 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
683 Qt::BrushStyle brushStyle = qbrush_style(s->brush);
684 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
685 alpha = (penBrushStyle != Qt::NoBrush
686 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
687 && !penBrush.isOpaque())
688 || (brushStyle != Qt::NoBrush
689 && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
690 && !s->brush.isOpaque());
691 linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
692 (brushStyle == Qt::LinearGradientPattern));
693 radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
694 (brushStyle == Qt::RadialGradientPattern));
695 extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
696 conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
697 (brushStyle == Qt::ConicalGradientPattern));
698 patternBrush = (((penBrushStyle > Qt::SolidPattern
699 && penBrushStyle < Qt::LinearGradientPattern)
700 || penBrushStyle == Qt::TexturePattern) ||
701 ((brushStyle > Qt::SolidPattern
702 && brushStyle < Qt::LinearGradientPattern)
703 || brushStyle == Qt::TexturePattern));
705 bool penTextureAlpha = false;
706 if (penBrush.style() == Qt::TexturePattern)
707 penTextureAlpha = qHasPixmapTexture(penBrush)
708 ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
709 : penBrush.textureImage().hasAlphaChannel();
710 bool brushTextureAlpha = false;
711 if (s->brush.style() == Qt::TexturePattern) {
712 brushTextureAlpha = qHasPixmapTexture(s->brush)
713 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
714 : s->brush.textureImage().hasAlphaChannel();
716 if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
717 || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
718 && !engine->hasFeature(QPaintEngine::MaskedBrush))
719 s->emulationSpecifier |= QPaintEngine::MaskedBrush;
721 s->emulationSpecifier &= ~QPaintEngine::MaskedBrush;
724 if (s->state() & (QPaintEngine::DirtyHints
725 | QPaintEngine::DirtyOpacity
726 | QPaintEngine::DirtyBackgroundMode)) {
734 qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
736 " - linearGradient: %d\n"
737 " - radialGradient: %d\n"
738 " - conicalGradient: %d\n"
739 " - patternBrush: %d\n"
748 uint(s->renderHints),
753 if (s->state() & QPaintEngine::DirtyTransform) {
754 xform = !s->matrix.isIdentity();
755 complexXform = !s->matrix.isAffine();
756 } else if (s->matrix.type() >= QTransform::TxTranslate) {
758 complexXform = !s->matrix.isAffine();
761 const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone);
762 const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone);
764 const bool patternXform = patternBrush && (xform || brushXform || penXform);
766 // Check alphablending
767 if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend))
768 s->emulationSpecifier |= QPaintEngine::AlphaBlend;
770 s->emulationSpecifier &= ~QPaintEngine::AlphaBlend;
772 // Linear gradient emulation
773 if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill))
774 s->emulationSpecifier |= QPaintEngine::LinearGradientFill;
776 s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
778 // Radial gradient emulation
779 if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
780 s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
782 s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
784 // Conical gradient emulation
785 if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
786 s->emulationSpecifier |= QPaintEngine::ConicalGradientFill;
788 s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill;
791 if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
792 s->emulationSpecifier |= QPaintEngine::PatternBrush;
794 s->emulationSpecifier &= ~QPaintEngine::PatternBrush;
797 if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform))
798 s->emulationSpecifier |= QPaintEngine::PatternTransform;
800 s->emulationSpecifier &= ~QPaintEngine::PatternTransform;
803 if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform))
804 s->emulationSpecifier |= QPaintEngine::PrimitiveTransform;
806 s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform;
808 // Perspective XForms
809 if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform))
810 s->emulationSpecifier |= QPaintEngine::PerspectiveTransform;
812 s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform;
815 if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity))
816 s->emulationSpecifier |= QPaintEngine::ConstantOpacity;
818 s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity;
820 bool gradientStretch = false;
821 bool objectBoundingMode = false;
822 if (linearGradient || conicalGradient || radialGradient) {
823 QGradient::CoordinateMode brushMode = coordinateMode(s->brush);
824 QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush());
826 gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
827 gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
829 objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
830 objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
833 s->emulationSpecifier |= QGradient_StretchToDevice;
835 s->emulationSpecifier &= ~QGradient_StretchToDevice;
837 if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
838 s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients;
840 s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients;
842 // Opaque backgrounds...
843 if (s->bgMode == Qt::OpaqueMode &&
844 (is_pen_transparent(s->pen) || is_brush_transparent(s->brush)))
845 s->emulationSpecifier |= QPaintEngine_OpaqueBackground;
847 s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground;
850 //won't be correct either way because the device can already have
851 // something rendered to it in which case subsequent emulation
852 // on a fully transparent qimage and then blitting the results
853 // won't produce correct results
855 if (state->composition_mode > QPainter::CompositionMode_Xor &&
856 !engine->hasFeature(QPaintEngine::BlendModes))
857 s->emulationSpecifier |= QPaintEngine::BlendModes;
859 s->emulationSpecifier &= ~QPaintEngine::BlendModes;
863 void QPainterPrivate::updateStateImpl(QPainterState *newState)
865 // ### we might have to call QPainter::begin() here...
866 if (!engine->state) {
867 engine->state = newState;
868 engine->setDirty(QPaintEngine::AllDirty);
871 if (engine->state->painter() != newState->painter)
872 // ### this could break with clip regions vs paths.
873 engine->setDirty(QPaintEngine::AllDirty);
875 // Upon restore, revert all changes since last save
876 else if (engine->state != newState)
877 newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
879 // We need to store all changes made so that restore can deal with them
881 newState->changeFlags |= newState->dirtyFlags;
883 updateEmulationSpecifier(newState);
885 // Unset potential dirty background mode
886 newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode
887 | QPaintEngine::DirtyBackground);
889 engine->state = newState;
890 engine->updateState(*newState);
891 engine->clearDirty(QPaintEngine::AllDirty);
895 void QPainterPrivate::updateState(QPainterState *newState)
899 engine->state = newState;
901 } else if (newState->state() || engine->state!=newState) {
902 bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
903 && newState->pen.widthF() == 0;
904 if (setNonCosmeticPen) {
905 // Override the default pen's cosmetic state if the
906 // NonCosmeticDefaultPen render hint is used.
907 QPen oldPen = newState->pen;
908 newState->pen.setWidth(1);
909 newState->pen.setCosmetic(false);
910 newState->dirtyFlags |= QPaintEngine::DirtyPen;
912 updateStateImpl(newState);
914 // Restore the state pen back to its default to preserve visible
916 newState->pen = oldPen;
918 updateStateImpl(newState);
926 \brief The QPainter class performs low-level painting on widgets and
934 QPainter provides highly optimized functions to do most of the
935 drawing GUI programs require. It can draw everything from simple
936 lines to complex shapes like pies and chords. It can also draw
937 aligned text and pixmaps. Normally, it draws in a "natural"
938 coordinate system, but it can also do view and world
939 transformation. QPainter can operate on any object that inherits
940 the QPaintDevice class.
942 The common use of QPainter is inside a widget's paint event:
943 Construct and customize (e.g. set the pen or the brush) the
944 painter. Then draw. Remember to destroy the QPainter object after
945 drawing. For example:
947 \snippet code/src_gui_painting_qpainter.cpp 0
949 The core functionality of QPainter is drawing, but the class also
950 provide several functions that allows you to customize QPainter's
951 settings and its rendering quality, and others that enable
952 clipping. In addition you can control how different shapes are
953 merged together by specifying the painter's composition mode.
955 The isActive() function indicates whether the painter is active. A
956 painter is activated by the begin() function and the constructor
957 that takes a QPaintDevice argument. The end() function, and the
958 destructor, deactivates it.
960 Together with the QPaintDevice and QPaintEngine classes, QPainter
961 form the basis for Qt's paint system. QPainter is the class used
962 to perform drawing operations. QPaintDevice represents a device
963 that can be painted on using a QPainter. QPaintEngine provides the
964 interface that the painter uses to draw onto different types of
965 devices. If the painter is active, device() returns the paint
966 device on which the painter paints, and paintEngine() returns the
967 paint engine that the painter is currently operating on. For more
968 information, see the \l {Paint System}.
970 Sometimes it is desirable to make someone else paint on an unusual
971 QPaintDevice. QPainter supports a static function to do this,
974 \warning When the paintdevice is a widget, QPainter can only be
975 used inside a paintEvent() function or in a function called by
982 There are several settings that you can customize to make QPainter
983 draw according to your preferences:
987 \li font() is the font used for drawing text. If the painter
988 isActive(), you can retrieve information about the currently set
989 font, and its metrics, using the fontInfo() and fontMetrics()
990 functions respectively.
992 \li brush() defines the color or pattern that is used for filling
995 \li pen() defines the color or stipple that is used for drawing
998 \li backgroundMode() defines whether there is a background() or
999 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
1001 \li background() only applies when backgroundMode() is \l
1002 Qt::OpaqueMode and pen() is a stipple. In that case, it
1003 describes the color of the background pixels in the stipple.
1005 \li brushOrigin() defines the origin of the tiled brushes, normally
1006 the origin of widget's background.
1008 \li viewport(), window(), worldTransform() make up the painter's coordinate
1009 transformation system. For more information, see the \l
1010 {Coordinate Transformations} section and the \l {Coordinate
1011 System} documentation.
1013 \li hasClipping() tells whether the painter clips at all. (The paint
1014 device clips, too.) If the painter clips, it clips to clipRegion().
1016 \li layoutDirection() defines the layout direction used by the
1017 painter when drawing text.
1019 \li worldMatrixEnabled() tells whether world transformation is enabled.
1021 \li viewTransformEnabled() tells whether view transformation is
1026 Note that some of these settings mirror settings in some paint
1027 devices, e.g. QWidget::font(). The QPainter::begin() function (or
1028 equivalently the QPainter constructor) copies these attributes
1029 from the paint device.
1031 You can at any time save the QPainter's state by calling the
1032 save() function which saves all the available settings on an
1033 internal stack. The restore() function pops them back.
1037 QPainter provides functions to draw most primitives: drawPoint(),
1038 drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1039 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1040 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
1041 convenience functions, drawRects() and drawLines(), draw the given
1042 number of rectangles or lines in the given array of \l
1043 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1046 The QPainter class also provides the fillRect() function which
1047 fills the given QRect, with the given QBrush, and the eraseRect()
1048 function that erases the area inside the given rectangle.
1050 All of these functions have both integer and floating point
1055 \li \inlineimage qpainter-basicdrawing.png
1057 \b {Basic Drawing Example}
1059 The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1060 display basic graphics primitives in a variety of styles using the
1065 If you need to draw a complex shape, especially if you need to do
1066 so repeatedly, consider creating a QPainterPath and drawing it
1072 \b {Painter Paths example}
1074 The QPainterPath class provides a container for painting
1075 operations, enabling graphical shapes to be constructed and
1078 The \l {painting/painterpaths}{Painter Paths} example shows how
1079 painter paths can be used to build complex shapes for rendering.
1081 \li \inlineimage qpainter-painterpaths.png
1084 QPainter also provides the fillPath() function which fills the
1085 given QPainterPath with the given QBrush, and the strokePath()
1086 function that draws the outline of the given path (i.e. strokes
1089 See also the \l {painting/deform}{Vector Deformation} example which
1090 shows how to use advanced vector techniques to draw text using a
1091 QPainterPath, the \l {painting/gradients}{Gradients} example which shows
1092 the different types of gradients that are available in Qt, and the \l
1093 {painting/pathstroke}{Path Stroking} example which shows Qt's built-in
1094 dash patterns and shows how custom patterns can be used to extend
1095 the range of available patterns.
1099 \li \l {painting/deform}{Vector Deformation}
1100 \li \l {painting/gradients}{Gradients}
1101 \li \l {painting/pathstroke}{Path Stroking}
1103 \li \inlineimage qpainter-vectordeformation.png
1104 \li \inlineimage qpainter-gradients.png
1105 \li \inlineimage qpainter-pathstroking.png
1109 There are functions to draw pixmaps/images, namely drawPixmap(),
1110 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1111 produce the same result, except that drawPixmap() is faster
1112 on-screen while drawImage() may be faster on a QPrinter or other
1115 Text drawing is done using drawText(). When you need
1116 fine-grained positioning, boundingRect() tells you where a given
1117 drawText() command will draw.
1119 There is a drawPicture() function that draws the contents of an
1120 entire QPicture. The drawPicture() function is the only function
1121 that disregards all the painter's settings as QPicture has its own
1124 \section1 Rendering Quality
1126 To get the optimal rendering result using QPainter, you should use
1127 the platform independent QImage as paint device; i.e. using QImage
1128 will ensure that the result has an identical pixel representation
1131 The QPainter class also provides a means of controlling the
1132 rendering quality through its RenderHint enum and the support for
1133 floating point precision: All the functions for drawing primitives
1134 has a floating point version. These are often used in combination
1135 with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1139 \li \inlineimage qpainter-concentriccircles.png
1141 \b {Concentric Circles Example}
1143 The \l {painting/concentriccircles}{Concentric Circles} example
1144 shows the improved rendering quality that can be obtained using
1145 floating point precision and anti-aliasing when drawing custom
1148 The application's main window displays several widgets which are
1149 drawn using the various combinations of precision and
1154 The RenderHint enum specifies flags to QPainter that may or may
1155 not be respected by any given engine. \l
1156 {RenderHint}{QPainter::Antialiasing} indicates that the engine
1157 should antialias edges of primitives if possible, \l
1158 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1159 should antialias text if possible, and the \l
1160 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1161 engine should use a smooth pixmap transformation algorithm.
1162 \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
1163 indicating that the engine should use fragment programs and offscreen
1164 rendering for antialiasing.
1166 The renderHints() function returns a flag that specifies the
1167 rendering hints that are set for this painter. Use the
1168 setRenderHint() function to set or clear the currently set
1171 \section1 Coordinate Transformations
1173 Normally, the QPainter operates on the device's own coordinate
1174 system (usually pixels), but QPainter has good support for
1175 coordinate transformations.
1179 \li nop \li rotate() \li scale() \li translate()
1181 \li \inlineimage qpainter-clock.png
1182 \li \inlineimage qpainter-rotation.png
1183 \li \inlineimage qpainter-scale.png
1184 \li \inlineimage qpainter-translation.png
1187 The most commonly used transformations are scaling, rotation,
1188 translation and shearing. Use the scale() function to scale the
1189 coordinate system by a given offset, the rotate() function to
1190 rotate it clockwise and translate() to translate it (i.e. adding a
1191 given offset to the points). You can also twist the coordinate
1192 system around the origin using the shear() function. See the \l
1193 {painting/affine}{Affine Transformations} example for a visualization of
1194 a sheared coordinate system.
1196 See also the \l {painting/transformations}{Transformations}
1197 example which shows how transformations influence the way that
1198 QPainter renders graphics primitives. In particular it shows how
1199 the order of transformations affects the result.
1204 \b {Affine Transformations Example}
1206 The \l {painting/affine}{Affine Transformations} example shows Qt's
1207 ability to perform affine transformations on painting
1208 operations. The demo also allows the user to experiment with the
1209 transformation operations and see the results immediately.
1211 \li \inlineimage qpainter-affinetransformations.png
1214 All the tranformation operations operate on the transformation
1215 worldTransform(). A matrix transforms a point in the plane to another
1216 point. For more information about the transformation matrix, see
1217 the \l {Coordinate System} and QTransform documentation.
1219 The setWorldTransform() function can replace or add to the currently
1220 set worldTransform(). The resetTransform() function resets any
1221 transformations that were made using translate(), scale(),
1222 shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1223 functions. The deviceTransform() returns the matrix that transforms
1224 from logical coordinates to device coordinates of the platform
1225 dependent paint device. The latter function is only needed when
1226 using platform painting commands on the platform dependent handle,
1227 and the platform does not do transformations nativly.
1229 When drawing with QPainter, we specify points using logical
1230 coordinates which then are converted into the physical coordinates
1231 of the paint device. The mapping of the logical coordinates to the
1232 physical coordinates are handled by QPainter's combinedTransform(), a
1233 combination of viewport() and window() and worldTransform(). The
1234 viewport() represents the physical coordinates specifying an
1235 arbitrary rectangle, the window() describes the same rectangle in
1236 logical coordinates, and the worldTransform() is identical with the
1237 transformation matrix.
1239 See also \l {Coordinate System}
1243 QPainter can clip any drawing operation to a rectangle, a region,
1244 or a vector path. The current clip is available using the
1245 functions clipRegion() and clipPath(). Whether paths or regions are
1246 preferred (faster) depends on the underlying paintEngine(). For
1247 example, the QImage paint engine prefers paths while the X11 paint
1248 engine prefers regions. Setting a clip is done in the painters
1249 logical coordinates.
1251 After QPainter's clipping, the paint device may also clip. For
1252 example, most widgets clip away the pixels used by child widgets,
1253 and most printers clip away an area near the edges of the paper.
1254 This additional clipping is not reflected by the return value of
1255 clipRegion() or hasClipping().
1257 \section1 Composition Modes
1258 \target Composition Modes
1260 QPainter provides the CompositionMode enum which defines the
1261 Porter-Duff rules for digital image compositing; it describes a
1262 model for combining the pixels in one image, the source, with the
1263 pixels in another image, the destination.
1265 The two most common forms of composition are \l
1266 {QPainter::CompositionMode}{Source} and \l
1267 {QPainter::CompositionMode}{SourceOver}. \l
1268 {QPainter::CompositionMode}{Source} is used to draw opaque objects
1269 onto a paint device. In this mode, each pixel in the source
1270 replaces the corresponding pixel in the destination. In \l
1271 {QPainter::CompositionMode}{SourceOver} composition mode, the
1272 source object is transparent and is drawn on top of the
1275 Note that composition transformation operates pixelwise. For that
1276 reason, there is a difference between using the graphic primitive
1277 itself and its bounding rectangle: The bounding rect contains
1278 pixels with alpha == 0 (i.e the pixels surrounding the
1279 primitive). These pixels will overwrite the other image's pixels,
1280 affectively clearing those, while the primitive only overwrites
1285 \li \inlineimage qpainter-compositiondemo.png
1288 \b {Composition Modes Example}
1290 The \l {painting/composition}{Composition Modes} example, available in
1291 Qt's examples directory, allows you to experiment with the various
1292 composition modes and see the results immediately.
1296 \section1 Limitations
1299 If you are using coordinates with Qt's raster-based paint engine, it is
1300 important to note that, while coordinates greater than +/- 2\sup 15 can
1301 be used, any painting performed with coordinates outside this range is not
1302 guaranteed to be shown; the drawing may be clipped. This is due to the
1303 use of \c{short int} in the implementation.
1305 The outlines generated by Qt's stroker are only an approximation when dealing
1306 with curved shapes. It is in most cases impossible to represent the outline of
1307 a bezier curve segment using another bezier curve segment, and so Qt approximates
1308 the curve outlines by using several smaller curves. For performance reasons there
1309 is a limit to how many curves Qt uses for these outlines, and thus when using
1310 large pen widths or scales the outline error increases. To generate outlines with
1311 smaller errors it is possible to use the QPainterPathStroker class, which has the
1312 setCurveThreshold member function which let's the user specify the error tolerance.
1313 Another workaround is to convert the paths to polygons first and then draw the
1316 \section1 Performance
1318 QPainter is a rich framework that allows developers to do a great
1319 variety of graphical operations, such as gradients, composition
1320 modes and vector graphics. And QPainter can do this across a
1321 variety of different hardware and software stacks. Naturally the
1322 underlying combination of hardware and software has some
1323 implications for performance, and ensuring that every single
1324 operation is fast in combination with all the various combinations
1325 of composition modes, brushes, clipping, transformation, etc, is
1326 close to an impossible task because of the number of
1327 permutations. As a compromise we have selected a subset of the
1328 QPainter API and backends, where performance is guaranteed to be as
1329 good as we can sensibly get it for the given combination of
1330 hardware and software.
1332 The backends we focus on as high-performance engines are:
1336 \li Raster - This backend implements all rendering in pure software
1337 and is always used to render into QImages. For optimal performance
1338 only use the format types QImage::Format_ARGB32_Premultiplied,
1339 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1340 including QImage::Format_ARGB32, has significantly worse
1341 performance. This engine is used by default for QWidget and QPixmap.
1343 \li OpenGL 2.0 (ES) - This backend is the primary backend for
1344 hardware accelerated graphics. It can be run on desktop machines
1345 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1346 specification. This includes most graphics chips produced in the
1347 last couple of years. The engine can be enabled by using QPainter
1348 onto a QOpenGLWidget or by passing \c {-graphicssystem opengl} on the
1349 command line when the underlying system supports it.
1351 \li OpenVG - This backend implements the Khronos standard for 2D
1352 and Vector Graphics. It is primarily for embedded devices with
1353 hardware support for OpenVG. The engine can be enabled by
1354 passing \c {-graphicssystem openvg} on the command line when
1355 the underlying system supports it.
1359 These operations are:
1363 \li Simple transformations, meaning translation and scaling, pluss
1364 0, 90, 180, 270 degree rotations.
1366 \li \c drawPixmap() in combination with simple transformations and
1367 opacity with non-smooth transformation mode
1368 (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1370 \li Rectangle fills with solid color, two-color linear gradients
1371 and simple transforms.
1373 \li Rectangular clipping with simple transformations and intersect
1376 \li Composition Modes \c QPainter::CompositionMode_Source and
1377 QPainter::CompositionMode_SourceOver
1379 \li Rounded rectangle filling using solid color and two-color
1380 linear gradients fills.
1382 \li 3x3 patched pixmaps, via qDrawBorderPixmap.
1386 This list gives an indication of which features to safely use in
1387 an application where performance is critical. For certain setups,
1388 other operations may be fast too, but before making extensive use
1389 of them, it is recommended to benchmark and verify them on the
1390 system where the software will run in the end. There are also
1391 cases where expensive operations are ok to use, for instance when
1392 the result is cached in a QPixmap.
1394 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
1395 {Drawing Utility Functions}
1399 \enum QPainter::RenderHint
1401 Renderhints are used to specify flags to QPainter that may or
1402 may not be respected by any given engine.
1404 \value Antialiasing Indicates that the engine should antialias
1405 edges of primitives if possible.
1407 \value TextAntialiasing Indicates that the engine should antialias
1408 text if possible. To forcibly disable antialiasing for text, do not
1409 use this hint. Instead, set QFont::NoAntialias on your font's style
1412 \value SmoothPixmapTransform Indicates that the engine should use
1413 a smooth pixmap transformation algorithm (such as bilinear) rather
1414 than nearest neighbor.
1416 \value HighQualityAntialiasing An OpenGL-specific rendering hint
1417 indicating that the engine should use fragment programs and offscreen
1418 rendering for antialiasing.
1420 \value NonCosmeticDefaultPen The engine should interpret pens with a width
1421 of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
1422 pen with a width of 1.
1424 \value Qt4CompatiblePainting Compatibility hint telling the engine to use the
1425 same X11 based fill rules as in Qt 4, where aliased rendering is offset
1426 by slightly less than half a pixel. Potentially useful when porting a
1427 Qt 4 application to Qt 5.
1429 \sa renderHints(), setRenderHint(), {QPainter#Rendering
1430 Quality}{Rendering Quality}, {Concentric Circles Example}
1435 Constructs a painter.
1440 QPainter::QPainter()
1441 : d_ptr(new QPainterPrivate(this))
1446 \fn QPainter::QPainter(QPaintDevice *device)
1448 Constructs a painter that begins painting the paint \a device
1451 This constructor is convenient for short-lived painters, e.g. in a
1452 QWidget::paintEvent() and should be used only once. The
1453 constructor calls begin() for you and the QPainter destructor
1454 automatically calls end().
1456 Here's an example using begin() and end():
1457 \snippet code/src_gui_painting_qpainter.cpp 1
1459 The same example using this constructor:
1460 \snippet code/src_gui_painting_qpainter.cpp 2
1462 Since the constructor cannot provide feedback when the initialization
1463 of the painter failed you should rather use begin() and end() to paint
1464 on external devices, e.g. printers.
1469 QPainter::QPainter(QPaintDevice *pd)
1473 if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1474 d_ptr.reset(new QPainterPrivate(this));
1481 Destroys the painter.
1483 QPainter::~QPainter()
1485 d_ptr->inDestructor = true;
1489 else if (d_ptr->refcount > 1)
1490 d_ptr->detachPainterPrivate(this);
1492 // don't throw anything in the destructor.
1495 // Make sure we haven't messed things up.
1496 Q_ASSERT(d_ptr->inDestructor);
1497 d_ptr->inDestructor = false;
1498 Q_ASSERT(d_ptr->refcount == 1);
1500 free(d_ptr->d_ptrs);
1505 Returns the paint device on which this painter is currently
1506 painting, or 0 if the painter is not active.
1511 QPaintDevice *QPainter::device() const
1513 Q_D(const QPainter);
1514 if (isActive() && d->engine->d_func()->currentClipDevice)
1515 return d->engine->d_func()->currentClipDevice;
1516 return d->original_device;
1520 Returns true if begin() has been called and end() has not yet been
1521 called; otherwise returns false.
1523 \sa begin(), QPaintDevice::paintingActive()
1526 bool QPainter::isActive() const
1528 Q_D(const QPainter);
1533 Initializes the painters pen, background and font to the same as
1534 the given \a device.
1538 \sa begin(), {QPainter#Settings}{Settings}
1540 void QPainter::initFrom(const QPaintDevice *device)
1542 Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0");
1545 qWarning("QPainter::initFrom: Painter not active, aborted");
1549 device->initPainter(this);
1552 d->extended->penChanged();
1553 } else if (d->engine) {
1554 d->engine->setDirty(QPaintEngine::DirtyPen);
1555 d->engine->setDirty(QPaintEngine::DirtyBrush);
1556 d->engine->setDirty(QPaintEngine::DirtyFont);
1562 Saves the current painter state (pushes the state onto a stack). A
1563 save() must be followed by a corresponding restore(); the end()
1564 function unwinds the stack.
1569 void QPainter::save()
1571 #ifdef QT_DEBUG_DRAW
1572 if (qt_show_painter_debug_output)
1573 printf("QPainter::save()\n");
1577 qWarning("QPainter::save: Painter not active");
1582 d->state = d->extended->createState(d->states.back());
1583 d->extended->setState(d->state);
1585 d->updateState(d->state);
1586 d->state = new QPainterState(d->states.back());
1587 d->engine->state = d->state;
1589 d->states.push_back(d->state);
1593 Restores the current painter state (pops a saved state off the
1599 void QPainter::restore()
1601 #ifdef QT_DEBUG_DRAW
1602 if (qt_show_painter_debug_output)
1603 printf("QPainter::restore()\n");
1606 if (d->states.size()<=1) {
1607 qWarning("QPainter::restore: Unbalanced save/restore");
1609 } else if (!d->engine) {
1610 qWarning("QPainter::restore: Painter not active");
1614 QPainterState *tmp = d->state;
1615 d->states.pop_back();
1616 d->state = d->states.back();
1620 d->checkEmulation();
1621 d->extended->setState(d->state);
1626 // trigger clip update if the clip path/region has changed since
1628 if (!d->state->clipInfo.isEmpty()
1629 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1630 // reuse the tmp state to avoid any extra allocs...
1631 tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1632 tmp->clipOperation = Qt::NoClip;
1633 tmp->clipPath = QPainterPath();
1634 d->engine->updateState(*tmp);
1635 // replay the list of clip states,
1636 for (int i=0; i<d->state->clipInfo.size(); ++i) {
1637 const QPainterClipInfo &info = d->state->clipInfo.at(i);
1638 tmp->matrix = info.matrix;
1639 tmp->matrix *= d->state->redirectionMatrix;
1640 tmp->clipOperation = info.operation;
1641 if (info.clipType == QPainterClipInfo::RectClip) {
1642 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1643 tmp->clipRegion = info.rect;
1644 } else if (info.clipType == QPainterClipInfo::RegionClip) {
1645 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1646 tmp->clipRegion = info.region;
1647 } else { // clipType == QPainterClipInfo::PathClip
1648 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1649 tmp->clipPath = info.path;
1651 d->engine->updateState(*tmp);
1655 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1656 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1657 tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1658 tmp->changeFlags |= QPaintEngine::DirtyTransform;
1661 d->updateState(d->state);
1668 \fn bool QPainter::begin(QPaintDevice *device)
1670 Begins painting the paint \a device and returns true if
1671 successful; otherwise returns false.
1673 Notice that all painter settings (setPen(), setBrush() etc.) are reset
1674 to default values when begin() is called.
1676 The errors that can occur are serious problems, such as these:
1678 \snippet code/src_gui_painting_qpainter.cpp 3
1680 Note that most of the time, you can use one of the constructors
1681 instead of begin(), and that end() is automatically done at
1684 \warning A paint device can only be painted by one painter at a
1687 \warning Painting on a QImage with the format
1688 QImage::Format_Indexed8 is not supported.
1690 \sa end(), QPainter()
1693 static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1702 bool QPainter::begin(QPaintDevice *pd)
1706 if (pd->painters > 0) {
1707 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1711 if (d_ptr->engine) {
1712 qWarning("QPainter::begin: Painter already active");
1716 if (QPainterPrivate::attachPainterPrivate(this, pd))
1721 d->helper_device = pd;
1722 d->original_device = pd;
1724 QPoint redirectionOffset;
1725 QPaintDevice *rpd = pd->redirected(&redirectionOffset);
1729 #ifdef QT_DEBUG_DRAW
1730 if (qt_show_painter_debug_output)
1731 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1734 if (pd->devType() == QInternal::Pixmap)
1735 static_cast<QPixmap *>(pd)->detach();
1736 else if (pd->devType() == QInternal::Image)
1737 static_cast<QImage *>(pd)->detach();
1739 d->engine = pd->paintEngine();
1742 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1748 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1749 if (d->emulationEngine)
1750 d->emulationEngine->real_engine = d->extended;
1752 // Setup new state...
1753 Q_ASSERT(!d->state);
1754 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1755 d->state->painter = this;
1756 d->states.push_back(d->state);
1758 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1759 d->state->brushOrigin = QPointF();
1761 // Slip a painter state into the engine before we do any other operations
1763 d->extended->setState(d->state);
1765 d->engine->state = d->state;
1767 switch (pd->devType()) {
1768 case QInternal::Pixmap:
1770 QPixmap *pm = static_cast<QPixmap *>(pd);
1773 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1774 qt_cleanup_painter_state(d);
1778 if (pm->depth() == 1) {
1779 d->state->pen = QPen(Qt::color1);
1780 d->state->brush = QBrush(Qt::color0);
1784 case QInternal::Image:
1786 QImage *img = static_cast<QImage *>(pd);
1788 if (img->isNull()) {
1789 qWarning("QPainter::begin: Cannot paint on a null image");
1790 qt_cleanup_painter_state(d);
1792 } else if (img->format() == QImage::Format_Indexed8) {
1793 // Painting on indexed8 images is not supported.
1794 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1795 qt_cleanup_painter_state(d);
1798 if (img->depth() == 1) {
1799 d->state->pen = QPen(Qt::color1);
1800 d->state->brush = QBrush(Qt::color0);
1807 if (d->state->ww == 0) // For compat with 3.x painter defaults
1808 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1810 d->engine->setPaintDevice(pd);
1812 bool begun = d->engine->begin(pd);
1814 qWarning("QPainter::begin(): Returned false");
1815 if (d->engine->isActive()) {
1818 qt_cleanup_painter_state(d);
1822 d->engine->setActive(begun);
1825 // Copy painter properties from original paint device,
1826 // required for QPixmap::grabWidget()
1827 if (d->original_device->devType() == QInternal::Widget) {
1828 initFrom(d->original_device);
1830 d->state->layoutDirection = Qt::LayoutDirectionAuto;
1831 // make sure we have a font compatible with the paintdevice
1832 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1835 QRect systemRect = d->engine->systemRect();
1836 if (!systemRect.isEmpty()) {
1837 d->state->ww = d->state->vw = systemRect.width();
1838 d->state->wh = d->state->vh = systemRect.height();
1840 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1841 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1844 const QPoint coordinateOffset = d->engine->coordinateOffset();
1845 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1847 Q_ASSERT(d->engine->isActive());
1849 if (!d->state->redirectionMatrix.isIdentity())
1852 Q_ASSERT(d->engine->isActive());
1853 d->state->renderHints = QPainter::TextAntialiasing;
1854 ++d->device->painters;
1856 d->state->emulationSpecifier = 0;
1862 Ends painting. Any resources used while painting are released. You
1863 don't normally need to call this since it is called by the
1866 Returns true if the painter is no longer active; otherwise returns false.
1868 \sa begin(), isActive()
1871 bool QPainter::end()
1873 #ifdef QT_DEBUG_DRAW
1874 if (qt_show_painter_debug_output)
1875 printf("QPainter::end()\n");
1880 qWarning("QPainter::end: Painter not active, aborted");
1881 qt_cleanup_painter_state(d);
1885 if (d->refcount > 1) {
1886 d->detachPainterPrivate(this);
1892 if (d->engine->isActive()) {
1893 ended = d->engine->end();
1896 --d->device->painters;
1897 if (d->device->painters == 0) {
1898 d->engine->setPaintDevice(0);
1899 d->engine->setActive(false);
1903 if (d->states.size() > 1) {
1904 qWarning("QPainter::end: Painter ended with %d saved states",
1908 if (d->engine->autoDestruct()) {
1912 if (d->emulationEngine) {
1913 delete d->emulationEngine;
1914 d->emulationEngine = 0;
1921 qt_cleanup_painter_state(d);
1928 Returns the paint engine that the painter is currently operating
1929 on if the painter is active; otherwise 0.
1933 QPaintEngine *QPainter::paintEngine() const
1935 Q_D(const QPainter);
1942 Flushes the painting pipeline and prepares for the user issuing commands
1943 directly to the underlying graphics context. Must be followed by a call to
1944 endNativePainting().
1946 Note that only the states the underlying paint engine changes will be reset
1947 to their respective default states. The states we reset may change from
1948 release to release. The following states are currently reset in the OpenGL
1952 \li blending is disabled
1953 \li the depth, stencil and scissor tests are disabled
1954 \li the active texture unit is reset to 0
1955 \li the depth mask, depth function and the clear depth are reset to their
1957 \li the stencil mask, stencil operation and stencil function are reset to
1958 their default values
1959 \li the current color is reset to solid white
1962 If, for example, the OpenGL polygon mode is changed by the user inside a
1963 beginNativePaint()/endNativePainting() block, it will not be reset to the
1964 default state by endNativePainting(). Here is an example that shows
1965 intermixing of painter commands and raw OpenGL commands:
1967 \snippet code/src_gui_painting_qpainter.cpp 21
1969 \sa endNativePainting()
1971 void QPainter::beginNativePainting()
1975 qWarning("QPainter::beginNativePainting: Painter not active");
1980 d->extended->beginNativePainting();
1986 Restores the painter after manually issuing native painting commands. Lets
1987 the painter restore any native state that it relies on before calling any
1988 other painter commands.
1990 \sa beginNativePainting()
1992 void QPainter::endNativePainting()
1994 Q_D(const QPainter);
1996 qWarning("QPainter::beginNativePainting: Painter not active");
2001 d->extended->endNativePainting();
2003 d->engine->syncState();
2007 Returns the font metrics for the painter if the painter is
2008 active. Otherwise, the return value is undefined.
2010 \sa font(), isActive(), {QPainter#Settings}{Settings}
2013 QFontMetrics QPainter::fontMetrics() const
2015 Q_D(const QPainter);
2017 qWarning("QPainter::fontMetrics: Painter not active");
2018 return QFontMetrics(QFont());
2020 return QFontMetrics(d->state->font);
2025 Returns the font info for the painter if the painter is
2026 active. Otherwise, the return value is undefined.
2028 \sa font(), isActive(), {QPainter#Settings}{Settings}
2031 QFontInfo QPainter::fontInfo() const
2033 Q_D(const QPainter);
2035 qWarning("QPainter::fontInfo: Painter not active");
2036 return QFontInfo(QFont());
2038 return QFontInfo(d->state->font);
2044 Returns the opacity of the painter. The default value is
2048 qreal QPainter::opacity() const
2050 Q_D(const QPainter);
2052 qWarning("QPainter::opacity: Painter not active");
2055 return d->state->opacity;
2061 Sets the opacity of the painter to \a opacity. The value should
2062 be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2063 1.0 is fully opaque.
2065 Opacity set on the painter will apply to all drawing operations
2069 void QPainter::setOpacity(qreal opacity)
2074 qWarning("QPainter::setOpacity: Painter not active");
2078 opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2080 if (opacity == d->state->opacity)
2083 d->state->opacity = opacity;
2086 d->extended->opacityChanged();
2088 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2093 Returns the currently set brush origin.
2095 \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2098 QPoint QPainter::brushOrigin() const
2100 Q_D(const QPainter);
2102 qWarning("QPainter::brushOrigin: Painter not active");
2105 return QPointF(d->state->brushOrigin).toPoint();
2109 \fn void QPainter::setBrushOrigin(const QPointF &position)
2111 Sets the brush origin to \a position.
2113 The brush origin specifies the (0, 0) coordinate of the painter's
2116 Note that while the brushOrigin() was necessary to adopt the
2117 parent's background for a widget in Qt 3, this is no longer the
2118 case since the Qt 4 painter doesn't paint the background unless
2119 you explicitly tell it to do so by setting the widget's \l
2120 {QWidget::autoFillBackground}{autoFillBackground} property to
2123 \sa brushOrigin(), {QPainter#Settings}{Settings}
2126 void QPainter::setBrushOrigin(const QPointF &p)
2129 #ifdef QT_DEBUG_DRAW
2130 if (qt_show_painter_debug_output)
2131 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2135 qWarning("QPainter::setBrushOrigin: Painter not active");
2139 d->state->brushOrigin = p;
2142 d->extended->brushOriginChanged();
2146 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2150 \fn void QPainter::setBrushOrigin(const QPoint &position)
2153 Sets the brush's origin to the given \a position.
2157 \fn void QPainter::setBrushOrigin(int x, int y)
2161 Sets the brush's origin to point (\a x, \a y).
2165 \enum QPainter::CompositionMode
2167 Defines the modes supported for digital image compositing.
2168 Composition modes are used to specify how the pixels in one image,
2169 the source, are merged with the pixel in another image, the
2172 Please note that the bitwise raster operation modes, denoted with
2173 a RasterOp prefix, are only natively supported in the X11 and
2174 raster paint engines. This means that the only way to utilize
2175 these modes on the Mac is via a QImage. The RasterOp denoted blend
2176 modes are \e not supported for pens and brushes with alpha
2177 components. Also, turning on the QPainter::Antialiasing render
2178 hint will effectively disable the RasterOp modes.
2181 \image qpainter-compositionmode1.png
2182 \image qpainter-compositionmode2.png
2184 The most common type is SourceOver (often referred to as just
2185 alpha blending) where the source pixel is blended on top of the
2186 destination pixel in such a way that the alpha component of the
2187 source defines the translucency of the pixel.
2189 When the paint device is a QImage, the image format must be set to
2190 \l {QImage::Format}{Format_ARGB32_Premultiplied} or
2191 \l {QImage::Format}{Format_ARGB32} for the composition modes to have
2192 any effect. For performance the premultiplied version is the preferred
2195 When a composition mode is set it applies to all painting
2196 operator, pens, brushes, gradients and pixmap/image drawing.
2198 \value CompositionMode_SourceOver This is the default mode. The
2199 alpha of the source is used to blend the pixel on top of the
2202 \value CompositionMode_DestinationOver The alpha of the
2203 destination is used to blend it on top of the source pixels. This
2204 mode is the inverse of CompositionMode_SourceOver.
2206 \value CompositionMode_Clear The pixels in the destination are
2207 cleared (set to fully transparent) independent of the source.
2209 \value CompositionMode_Source The output is the source
2210 pixel. (This means a basic copy operation and is identical to
2211 SourceOver when the source pixel is opaque).
2213 \value CompositionMode_Destination The output is the destination
2214 pixel. This means that the blending has no effect. This mode is
2215 the inverse of CompositionMode_Source.
2217 \value CompositionMode_SourceIn The output is the source, where
2218 the alpha is reduced by that of the destination.
2220 \value CompositionMode_DestinationIn The output is the
2221 destination, where the alpha is reduced by that of the
2222 source. This mode is the inverse of CompositionMode_SourceIn.
2224 \value CompositionMode_SourceOut The output is the source, where
2225 the alpha is reduced by the inverse of destination.
2227 \value CompositionMode_DestinationOut The output is the
2228 destination, where the alpha is reduced by the inverse of the
2229 source. This mode is the inverse of CompositionMode_SourceOut.
2231 \value CompositionMode_SourceAtop The source pixel is blended on
2232 top of the destination, with the alpha of the source pixel reduced
2233 by the alpha of the destination pixel.
2235 \value CompositionMode_DestinationAtop The destination pixel is
2236 blended on top of the source, with the alpha of the destination
2237 pixel is reduced by the alpha of the destination pixel. This mode
2238 is the inverse of CompositionMode_SourceAtop.
2240 \value CompositionMode_Xor The source, whose alpha is reduced with
2241 the inverse of the destination alpha, is merged with the
2242 destination, whose alpha is reduced by the inverse of the source
2243 alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2245 \value CompositionMode_Plus Both the alpha and color of the source
2246 and destination pixels are added together.
2248 \value CompositionMode_Multiply The output is the source color
2249 multiplied by the destination. Multiplying a color with white
2250 leaves the color unchanged, while multiplying a color
2251 with black produces black.
2253 \value CompositionMode_Screen The source and destination colors
2254 are inverted and then multiplied. Screening a color with white
2255 produces white, whereas screening a color with black leaves the
2258 \value CompositionMode_Overlay Multiplies or screens the colors
2259 depending on the destination color. The destination color is mixed
2260 with the source color to reflect the lightness or darkness of the
2263 \value CompositionMode_Darken The darker of the source and
2264 destination colors is selected.
2266 \value CompositionMode_Lighten The lighter of the source and
2267 destination colors is selected.
2269 \value CompositionMode_ColorDodge The destination color is
2270 brightened to reflect the source color. A black source color
2271 leaves the destination color unchanged.
2273 \value CompositionMode_ColorBurn The destination color is darkened
2274 to reflect the source color. A white source color leaves the
2275 destination color unchanged.
2277 \value CompositionMode_HardLight Multiplies or screens the colors
2278 depending on the source color. A light source color will lighten
2279 the destination color, whereas a dark source color will darken the
2282 \value CompositionMode_SoftLight Darkens or lightens the colors
2283 depending on the source color. Similar to
2284 CompositionMode_HardLight.
2286 \value CompositionMode_Difference Subtracts the darker of the
2287 colors from the lighter. Painting with white inverts the
2288 destination color, whereas painting with black leaves the
2289 destination color unchanged.
2291 \value CompositionMode_Exclusion Similar to
2292 CompositionMode_Difference, but with a lower contrast. Painting
2293 with white inverts the destination color, whereas painting with
2294 black leaves the destination color unchanged.
2296 \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2297 the source and destination pixels (src OR dst).
2299 \value RasterOp_SourceAndDestination Does a bitwise AND operation
2300 on the source and destination pixels (src AND dst).
2302 \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2303 on the source and destination pixels (src XOR dst).
2305 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2306 operation on the source and destination pixels ((NOT src) AND (NOT
2309 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2310 operation on the source and destination pixels ((NOT src) OR (NOT
2313 \value RasterOp_NotSourceXorDestination Does a bitwise operation
2314 where the source pixels are inverted and then XOR'ed with the
2315 destination ((NOT src) XOR dst).
2317 \value RasterOp_NotSource Does a bitwise operation where the
2318 source pixels are inverted (NOT src).
2320 \value RasterOp_NotSourceAndDestination Does a bitwise operation
2321 where the source is inverted and then AND'ed with the destination
2322 ((NOT src) AND dst).
2324 \value RasterOp_SourceAndNotDestination Does a bitwise operation
2325 where the source is AND'ed with the inverted destination pixels
2326 (src AND (NOT dst)).
2328 \value RasterOp_NotSourceOrDestination Does a bitwise operation
2329 where the source is inverted and then OR'ed with the destination
2332 \value RasterOp_ClearDestination The pixels in the destination are
2333 cleared (set to 0) independent of the source.
2335 \value RasterOp_SetDestination The pixels in the destination are
2336 set (set to 1) independent of the source.
2338 \value RasterOp_NotDestination Does a bitwise operation
2339 where the destination pixels are inverted (NOT dst).
2341 \value RasterOp_SourceOrNotDestination Does a bitwise operation
2342 where the source is OR'ed with the inverted destination pixels
2345 \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2346 Modes}{Composition Modes}, {Image Composition Example}
2350 Sets the composition mode to the given \a mode.
2352 \warning Only a QPainter operating on a QImage fully supports all
2353 composition modes. The RasterOp modes are supported for X11 as
2354 described in compositionMode().
2356 \sa compositionMode()
2358 void QPainter::setCompositionMode(CompositionMode mode)
2362 qWarning("QPainter::setCompositionMode: Painter not active");
2365 if (d->state->composition_mode == mode)
2368 d->state->composition_mode = mode;
2369 d->extended->compositionModeChanged();
2373 if (mode >= QPainter::RasterOp_SourceOrDestination) {
2374 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2375 qWarning("QPainter::setCompositionMode: "
2376 "Raster operation modes not supported on device");
2379 } else if (mode >= QPainter::CompositionMode_Plus) {
2380 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2381 qWarning("QPainter::setCompositionMode: "
2382 "Blend modes not supported on device");
2385 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2386 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2387 qWarning("QPainter::setCompositionMode: "
2388 "PorterDuff modes not supported on device");
2393 d->state->composition_mode = mode;
2394 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2398 Returns the current composition mode.
2400 \sa CompositionMode, setCompositionMode()
2402 QPainter::CompositionMode QPainter::compositionMode() const
2404 Q_D(const QPainter);
2406 qWarning("QPainter::compositionMode: Painter not active");
2407 return QPainter::CompositionMode_SourceOver;
2409 return d->state->composition_mode;
2413 Returns the current background brush.
2415 \sa setBackground(), {QPainter#Settings}{Settings}
2418 const QBrush &QPainter::background() const
2420 Q_D(const QPainter);
2422 qWarning("QPainter::background: Painter not active");
2423 return d->fakeState()->brush;
2425 return d->state->bgBrush;
2430 Returns true if clipping has been set; otherwise returns false.
2432 \sa setClipping(), {QPainter#Clipping}{Clipping}
2435 bool QPainter::hasClipping() const
2437 Q_D(const QPainter);
2439 qWarning("QPainter::hasClipping: Painter not active");
2442 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2447 Enables clipping if \a enable is true, or disables clipping if \a
2450 \sa hasClipping(), {QPainter#Clipping}{Clipping}
2453 void QPainter::setClipping(bool enable)
2456 #ifdef QT_DEBUG_DRAW
2457 if (qt_show_painter_debug_output)
2458 printf("QPainter::setClipping(), enable=%s, was=%s\n",
2459 enable ? "on" : "off",
2460 hasClipping() ? "on" : "off");
2463 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2467 if (hasClipping() == enable)
2470 // we can't enable clipping if we don't have a clip
2472 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2474 d->state->clipEnabled = enable;
2477 d->extended->clipEnabledChanged();
2481 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2482 d->updateState(d->state);
2487 Returns the currently set clip region. Note that the clip region
2488 is given in logical coordinates.
2490 \warning QPainter does not store the combined clip explicitly as
2491 this is handled by the underlying QPaintEngine, so the path is
2492 recreated on demand and transformed to the current logical
2493 coordinate system. This is potentially an expensive operation.
2495 \sa setClipRegion(), clipPath(), setClipping()
2498 QRegion QPainter::clipRegion() const
2500 Q_D(const QPainter);
2502 qWarning("QPainter::clipRegion: Painter not active");
2507 bool lastWasNothing = true;
2510 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2512 // ### Falcon: Use QPainterPath
2513 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2514 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2515 switch (info.clipType) {
2517 case QPainterClipInfo::RegionClip: {
2518 QTransform matrix = (info.matrix * d->invMatrix);
2519 if (lastWasNothing) {
2520 region = info.region * matrix;
2521 lastWasNothing = false;
2524 if (info.operation == Qt::IntersectClip)
2525 region &= info.region * matrix;
2526 else if (info.operation == Qt::NoClip) {
2527 lastWasNothing = true;
2530 region = info.region * matrix;
2534 case QPainterClipInfo::PathClip: {
2535 QTransform matrix = (info.matrix * d->invMatrix);
2536 if (lastWasNothing) {
2537 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2538 info.path.fillRule());
2539 lastWasNothing = false;
2542 if (info.operation == Qt::IntersectClip) {
2543 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2544 info.path.fillRule());
2545 } else if (info.operation == Qt::NoClip) {
2546 lastWasNothing = true;
2549 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2550 info.path.fillRule());
2555 case QPainterClipInfo::RectClip: {
2556 QTransform matrix = (info.matrix * d->invMatrix);
2557 if (lastWasNothing) {
2558 region = QRegion(info.rect) * matrix;
2559 lastWasNothing = false;
2562 if (info.operation == Qt::IntersectClip) {
2563 // Use rect intersection if possible.
2564 if (matrix.type() <= QTransform::TxScale)
2565 region &= matrix.mapRect(info.rect);
2567 region &= matrix.map(QRegion(info.rect));
2568 } else if (info.operation == Qt::NoClip) {
2569 lastWasNothing = true;
2572 region = QRegion(info.rect) * matrix;
2577 case QPainterClipInfo::RectFClip: {
2578 QTransform matrix = (info.matrix * d->invMatrix);
2579 if (lastWasNothing) {
2580 region = QRegion(info.rectf.toRect()) * matrix;
2581 lastWasNothing = false;
2584 if (info.operation == Qt::IntersectClip) {
2585 // Use rect intersection if possible.
2586 if (matrix.type() <= QTransform::TxScale)
2587 region &= matrix.mapRect(info.rectf.toRect());
2589 region &= matrix.map(QRegion(info.rectf.toRect()));
2590 } else if (info.operation == Qt::NoClip) {
2591 lastWasNothing = true;
2594 region = QRegion(info.rectf.toRect()) * matrix;
2604 extern QPainterPath qt_regionToPath(const QRegion ®ion);
2607 Returns the currently clip as a path. Note that the clip path is
2608 given in logical coordinates.
2610 \warning QPainter does not store the combined clip explicitly as
2611 this is handled by the underlying QPaintEngine, so the path is
2612 recreated on demand and transformed to the current logical
2613 coordinate system. This is potentially an expensive operation.
2615 \sa setClipPath(), clipRegion(), setClipping()
2617 QPainterPath QPainter::clipPath() const
2619 Q_D(const QPainter);
2621 // ### Since we do not support path intersections and path unions yet,
2622 // we just use clipRegion() here...
2624 qWarning("QPainter::clipPath: Painter not active");
2625 return QPainterPath();
2628 // No clip, return empty
2629 if (d->state->clipInfo.size() == 0) {
2630 return QPainterPath();
2633 // Update inverse matrix, used below.
2635 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2637 // For the simple case avoid conversion.
2638 if (d->state->clipInfo.size() == 1
2639 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2640 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2641 return d->state->clipInfo.at(0).path * matrix;
2643 } else if (d->state->clipInfo.size() == 1
2644 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2645 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2647 path.addRect(d->state->clipInfo.at(0).rect);
2648 return path * matrix;
2650 // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2651 return qt_regionToPath(clipRegion());
2657 Returns the bounding rectangle of the current clip if there is a clip;
2658 otherwise returns an empty rectangle. Note that the clip region is
2659 given in logical coordinates.
2661 The bounding rectangle is not guaranteed to be tight.
2663 \sa setClipRect(), setClipPath(), setClipRegion()
2668 QRectF QPainter::clipBoundingRect() const
2670 Q_D(const QPainter);
2673 qWarning("QPainter::clipBoundingRect: Painter not active");
2677 // Accumulate the bounding box in device space. This is not 100%
2678 // precise, but it fits within the guarantee and it is reasonably
2681 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2683 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2685 if (info.clipType == QPainterClipInfo::RectClip)
2687 else if (info.clipType == QPainterClipInfo::RectFClip)
2689 else if (info.clipType == QPainterClipInfo::RegionClip)
2690 r = info.region.boundingRect();
2692 r = info.path.boundingRect();
2694 r = info.matrix.mapRect(r);
2698 else if (info.operation == Qt::IntersectClip)
2703 // Map the rectangle back into logical space using the inverse
2706 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2708 return d->invMatrix.mapRect(bounds);
2712 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2714 Enables clipping, and sets the clip region to the given \a
2715 rectangle using the given clip \a operation. The default operation
2716 is to replace the current clip rectangle.
2718 Note that the clip rectangle is specified in logical (painter)
2721 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2723 void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2728 if ((!d->state->clipEnabled && op != Qt::NoClip))
2729 op = Qt::ReplaceClip;
2732 qWarning("QPainter::setClipRect: Painter not active");
2735 qreal right = rect.x() + rect.width();
2736 qreal bottom = rect.y() + rect.height();
2737 qreal pts[] = { rect.x(), rect.y(),
2741 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2742 d->state->clipEnabled = true;
2743 d->extended->clip(vp, op);
2744 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2745 d->state->clipInfo.clear();
2746 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2747 d->state->clipOperation = op;
2751 if (qreal(int(rect.top())) == rect.top()
2752 && qreal(int(rect.bottom())) == rect.bottom()
2753 && qreal(int(rect.left())) == rect.left()
2754 && qreal(int(rect.right())) == rect.right())
2756 setClipRect(rect.toRect(), op);
2760 if (rect.isEmpty()) {
2761 setClipRegion(QRegion(), op);
2767 setClipPath(path, op);
2771 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2774 Enables clipping, and sets the clip region to the given \a rectangle using the given
2777 void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2782 qWarning("QPainter::setClipRect: Painter not active");
2786 if ((!d->state->clipEnabled && op != Qt::NoClip))
2787 op = Qt::ReplaceClip;
2790 d->state->clipEnabled = true;
2791 d->extended->clip(rect, op);
2792 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2793 d->state->clipInfo.clear();
2794 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2795 d->state->clipOperation = op;
2799 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2800 op = Qt::ReplaceClip;
2802 d->state->clipRegion = rect;
2803 d->state->clipOperation = op;
2804 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2805 d->state->clipInfo.clear();
2806 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2807 d->state->clipEnabled = true;
2808 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2809 d->updateState(d->state);
2813 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2815 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2816 with the given \a width and \a height.
2820 \fn void QPainter::setClipRegion(const QRegion ®ion, Qt::ClipOperation operation)
2822 Sets the clip region to the given \a region using the specified clip
2823 \a operation. The default clip operation is to replace the current
2826 Note that the clip region is given in logical coordinates.
2828 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2830 void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2833 #ifdef QT_DEBUG_DRAW
2834 QRect rect = r.boundingRect();
2835 if (qt_show_painter_debug_output)
2836 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2837 r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2840 qWarning("QPainter::setClipRegion: Painter not active");
2844 if ((!d->state->clipEnabled && op != Qt::NoClip))
2845 op = Qt::ReplaceClip;
2848 d->state->clipEnabled = true;
2849 d->extended->clip(r, op);
2850 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2851 d->state->clipInfo.clear();
2852 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2853 d->state->clipOperation = op;
2857 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2858 op = Qt::ReplaceClip;
2860 d->state->clipRegion = r;
2861 d->state->clipOperation = op;
2862 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2863 d->state->clipInfo.clear();
2864 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2865 d->state->clipEnabled = true;
2866 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2867 d->updateState(d->state);
2874 Sets the transformation matrix to \a matrix and enables transformations.
2876 \note It is advisable to use setWorldTransform() instead of this function to
2877 preserve the properties of perspective transformations.
2879 If \a combine is true, then \a matrix is combined with the current
2880 transformation matrix; otherwise \a matrix replaces the current
2881 transformation matrix.
2883 If \a matrix is the identity matrix and \a combine is false, this
2884 function calls setWorldMatrixEnabled(false). (The identity matrix is the
2885 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2888 The following functions can transform the coordinate system without using
2897 They operate on the painter's worldMatrix() and are implemented like this:
2899 \snippet code/src_gui_painting_qpainter.cpp 4
2901 Note that when using setWorldMatrix() function you should always have
2902 \a combine be true when you are drawing into a QPicture. Otherwise
2903 it may not be possible to replay the picture with additional
2904 transformations; using the translate(), scale(), etc. convenience
2907 For more information about the coordinate system, transformations
2908 and window-viewport conversion, see \l {Coordinate System}.
2910 \sa setWorldTransform(), QTransform
2913 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2915 setWorldTransform(QTransform(matrix), combine);
2922 Returns the world transformation matrix.
2924 It is advisable to use worldTransform() because worldMatrix() does not
2925 preserve the properties of perspective transformations.
2927 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2931 const QMatrix &QPainter::worldMatrix() const
2933 Q_D(const QPainter);
2935 qWarning("QPainter::worldMatrix: Painter not active");
2936 return d->fakeState()->transform.toAffine();
2938 return d->state->worldMatrix.toAffine();
2944 Use setWorldTransform() instead.
2946 \sa setWorldTransform()
2949 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
2951 setWorldTransform(QTransform(matrix), combine);
2957 Use worldTransform() instead.
2959 \sa worldTransform()
2962 const QMatrix &QPainter::matrix() const
2964 return worldMatrix();
2972 Returns the transformation matrix combining the current
2973 window/viewport and world transformation.
2975 It is advisable to use combinedTransform() instead of this
2976 function to preserve the properties of perspective transformations.
2978 \sa setWorldTransform(), setWindow(), setViewport()
2980 QMatrix QPainter::combinedMatrix() const
2982 return combinedTransform().toAffine();
2989 Returns the matrix that transforms from logical coordinates to
2990 device coordinates of the platform dependent paint device.
2992 \note It is advisable to use deviceTransform() instead of this
2993 function to preserve the properties of perspective transformations.
2995 This function is \e only needed when using platform painting
2996 commands on the platform dependent handle (Qt::HANDLE), and the
2997 platform does not do transformations nativly.
2999 The QPaintEngine::PaintEngineFeature enum can be queried to
3000 determine whether the platform performs the transformations or
3003 \sa worldMatrix(), QPaintEngine::hasFeature(),
3005 const QMatrix &QPainter::deviceMatrix() const
3007 Q_D(const QPainter);
3009 qWarning("QPainter::deviceMatrix: Painter not active");
3010 return d->fakeState()->transform.toAffine();
3012 return d->state->matrix.toAffine();
3018 Resets any transformations that were made using translate(), scale(),
3019 shear(), rotate(), setWorldMatrix(), setViewport() and
3022 It is advisable to use resetTransform() instead of this function
3023 to preserve the properties of perspective transformations.
3025 \sa {QPainter#Coordinate Transformations}{Coordinate
3029 void QPainter::resetMatrix()
3038 Enables transformations if \a enable is true, or disables
3039 transformations if \a enable is false. The world transformation
3040 matrix is not changed.
3042 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3043 Transformations}{Coordinate Transformations}
3046 void QPainter::setWorldMatrixEnabled(bool enable)
3049 #ifdef QT_DEBUG_DRAW
3050 if (qt_show_painter_debug_output)
3051 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3055 qWarning("QPainter::setMatrixEnabled: Painter not active");
3058 if (enable == d->state->WxF)
3061 d->state->WxF = enable;
3068 Returns true if world transformation is enabled; otherwise returns
3071 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3074 bool QPainter::worldMatrixEnabled() const
3076 Q_D(const QPainter);
3078 qWarning("QPainter::worldMatrixEnabled: Painter not active");
3081 return d->state->WxF;
3087 Use setWorldMatrixEnabled() instead.
3089 \sa setWorldMatrixEnabled()
3092 void QPainter::setMatrixEnabled(bool enable)
3094 setWorldMatrixEnabled(enable);
3100 Use worldMatrixEnabled() instead
3102 \sa worldMatrixEnabled()
3105 bool QPainter::matrixEnabled() const
3107 return worldMatrixEnabled();
3111 Scales the coordinate system by (\a{sx}, \a{sy}).
3113 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3116 void QPainter::scale(qreal sx, qreal sy)
3118 #ifdef QT_DEBUG_DRAW
3119 if (qt_show_painter_debug_output)
3120 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3124 qWarning("QPainter::scale: Painter not active");
3128 d->state->worldMatrix.scale(sx,sy);
3129 d->state->WxF = true;
3134 Shears the coordinate system by (\a{sh}, \a{sv}).
3136 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3139 void QPainter::shear(qreal sh, qreal sv)
3141 #ifdef QT_DEBUG_DRAW
3142 if (qt_show_painter_debug_output)
3143 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3147 qWarning("QPainter::shear: Painter not active");
3151 d->state->worldMatrix.shear(sh, sv);
3152 d->state->WxF = true;
3157 \fn void QPainter::rotate(qreal angle)
3159 Rotates the coordinate system clockwise. The given \a angle parameter uses degree unit.
3161 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3164 void QPainter::rotate(qreal a)
3166 #ifdef QT_DEBUG_DRAW
3167 if (qt_show_painter_debug_output)
3168 printf("QPainter::rotate(), angle=%f\n", a);
3172 qWarning("QPainter::rotate: Painter not active");
3176 d->state->worldMatrix.rotate(a);
3177 d->state->WxF = true;
3182 Translates the coordinate system by the given \a offset; i.e. the
3183 given \a offset is added to points.
3185 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3187 void QPainter::translate(const QPointF &offset)
3189 qreal dx = offset.x();
3190 qreal dy = offset.y();
3191 #ifdef QT_DEBUG_DRAW
3192 if (qt_show_painter_debug_output)
3193 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3197 qWarning("QPainter::translate: Painter not active");
3201 d->state->worldMatrix.translate(dx, dy);
3202 d->state->WxF = true;
3207 \fn void QPainter::translate(const QPoint &offset)
3210 Translates the coordinate system by the given \a offset.
3214 \fn void QPainter::translate(qreal dx, qreal dy)
3217 Translates the coordinate system by the vector (\a dx, \a dy).
3221 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3223 Enables clipping, and sets the clip path for the painter to the
3224 given \a path, with the clip \a operation.
3226 Note that the clip path is specified in logical (painter)
3229 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3232 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3234 #ifdef QT_DEBUG_DRAW
3235 if (qt_show_painter_debug_output) {
3236 QRectF b = path.boundingRect();
3237 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3238 path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3244 qWarning("QPainter::setClipPath: Painter not active");
3248 if ((!d->state->clipEnabled && op != Qt::NoClip))
3249 op = Qt::ReplaceClip;
3252 d->state->clipEnabled = true;
3253 d->extended->clip(path, op);
3254 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3255 d->state->clipInfo.clear();
3256 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3257 d->state->clipOperation = op;
3261 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
3262 op = Qt::ReplaceClip;
3264 d->state->clipPath = path;
3265 d->state->clipOperation = op;
3266 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3267 d->state->clipInfo.clear();
3268 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3269 d->state->clipEnabled = true;
3270 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3271 d->updateState(d->state);
3275 Draws the outline (strokes) the path \a path with the pen specified
3278 \sa fillPath(), {QPainter#Drawing}{Drawing}
3280 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3285 qWarning("QPainter::strokePath: Painter not active");
3293 const QGradient *g = qpen_brush(pen).gradient();
3294 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3295 d->extended->stroke(qtVectorPathForPath(path), pen);
3300 QBrush oldBrush = d->state->brush;
3301 QPen oldPen = d->state->pen;
3304 setBrush(Qt::NoBrush);
3314 Fills the given \a path using the given \a brush. The outline is
3317 Alternatively, you can specify a QColor instead of a QBrush; the
3318 QBrush constructor (taking a QColor argument) will automatically
3319 create a solid pattern brush.
3323 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3328 qWarning("QPainter::fillPath: Painter not active");
3336 const QGradient *g = brush.gradient();
3337 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3338 d->extended->fill(qtVectorPathForPath(path), brush);
3343 QBrush oldBrush = d->state->brush;
3344 QPen oldPen = d->state->pen;
3357 Draws the given painter \a path using the current pen for outline
3358 and the current brush for filling.
3362 \li \inlineimage qpainter-path.png
3364 \snippet code/src_gui_painting_qpainter.cpp 5
3367 \sa {painting/painterpaths}{the Painter Paths
3368 example},{painting/deform}{the Vector Deformation example}
3370 void QPainter::drawPath(const QPainterPath &path)
3372 #ifdef QT_DEBUG_DRAW
3373 QRectF pathBounds = path.boundingRect();
3374 if (qt_show_painter_debug_output)
3375 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3376 path.elementCount(),
3377 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3383 qWarning("QPainter::drawPath: Painter not active");
3388 d->extended->drawPath(path);
3391 d->updateState(d->state);
3393 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3394 d->engine->drawPath(path);
3396 d->draw_helper(path);
3401 \fn void QPainter::drawLine(const QLineF &line)
3403 Draws a line defined by \a line.
3407 \li \inlineimage qpainter-line.png
3409 \snippet code/src_gui_painting_qpainter.cpp 6
3412 \sa drawLines(), drawPolyline(), {Coordinate System}
3416 \fn void QPainter::drawLine(const QLine &line)
3419 Draws a line defined by \a line.
3423 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3426 Draws a line from \a p1 to \a p2.
3430 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3433 Draws a line from \a p1 to \a p2.
3437 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3440 Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3441 current pen position to (\a x2, \a y2).
3445 \fn void QPainter::drawRect(const QRectF &rectangle)
3447 Draws the current \a rectangle with the current pen and brush.
3449 A filled rectangle has a size of \a{rectangle}.size(). A stroked
3450 rectangle has a size of \a{rectangle}.size() plus the pen width.
3454 \li \inlineimage qpainter-rectangle.png
3456 \snippet code/src_gui_painting_qpainter.cpp 7
3459 \sa drawRects(), drawPolygon(), {Coordinate System}
3463 \fn void QPainter::drawRect(const QRect &rectangle)
3467 Draws the current \a rectangle with the current pen and brush.
3471 \fn void QPainter::drawRect(int x, int y, int width, int height)
3475 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3476 with the given \a width and \a height.
3480 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3482 Draws the first \a rectCount of the given \a rectangles using the
3483 current pen and brush.
3487 void QPainter::drawRects(const QRectF *rects, int rectCount)
3489 #ifdef QT_DEBUG_DRAW
3490 if (qt_show_painter_debug_output)
3491 printf("QPainter::drawRects(), count=%d\n", rectCount);
3496 qWarning("QPainter::drawRects: Painter not active");
3504 d->extended->drawRects(rects, rectCount);
3508 d->updateState(d->state);
3510 if (!d->state->emulationSpecifier) {
3511 d->engine->drawRects(rects, rectCount);
3515 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3516 && d->state->matrix.type() == QTransform::TxTranslate) {
3517 for (int i=0; i<rectCount; ++i) {
3518 QRectF r(rects[i].x() + d->state->matrix.dx(),
3519 rects[i].y() + d->state->matrix.dy(),
3522 d->engine->drawRects(&r, 1);
3525 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3526 for (int i=0; i<rectCount; ++i) {
3527 QPainterPath rectPath;
3528 rectPath.addRect(rects[i]);
3529 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3532 QPainterPath rectPath;
3533 for (int i=0; i<rectCount; ++i)
3534 rectPath.addRect(rects[i]);
3535 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3541 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3544 Draws the first \a rectCount of the given \a rectangles using the
3545 current pen and brush.
3547 void QPainter::drawRects(const QRect *rects, int rectCount)
3549 #ifdef QT_DEBUG_DRAW
3550 if (qt_show_painter_debug_output)
3551 printf("QPainter::drawRects(), count=%d\n", rectCount);
3556 qWarning("QPainter::drawRects: Painter not active");
3564 d->extended->drawRects(rects, rectCount);
3568 d->updateState(d->state);
3570 if (!d->state->emulationSpecifier) {
3571 d->engine->drawRects(rects, rectCount);
3575 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3576 && d->state->matrix.type() == QTransform::TxTranslate) {
3577 for (int i=0; i<rectCount; ++i) {
3578 QRectF r(rects[i].x() + d->state->matrix.dx(),
3579 rects[i].y() + d->state->matrix.dy(),
3583 d->engine->drawRects(&r, 1);
3586 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3587 for (int i=0; i<rectCount; ++i) {
3588 QPainterPath rectPath;
3589 rectPath.addRect(rects[i]);
3590 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3593 QPainterPath rectPath;
3594 for (int i=0; i<rectCount; ++i)
3595 rectPath.addRect(rects[i]);
3597 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3603 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3606 Draws the given \a rectangles using the current pen and brush.
3610 \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3614 Draws the given \a rectangles using the current pen and brush.
3618 \fn void QPainter::drawPoint(const QPointF &position)
3620 Draws a single point at the given \a position using the current
3623 \sa {Coordinate System}
3627 \fn void QPainter::drawPoint(const QPoint &position)
3630 Draws a single point at the given \a position using the current
3634 /*! \fn void QPainter::drawPoint(int x, int y)
3638 Draws a single point at position (\a x, \a y).
3642 Draws the first \a pointCount points in the array \a points using
3643 the current pen's color.
3645 \sa {Coordinate System}
3647 void QPainter::drawPoints(const QPointF *points, int pointCount)
3649 #ifdef QT_DEBUG_DRAW
3650 if (qt_show_painter_debug_output)
3651 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3656 qWarning("QPainter::drawPoints: Painter not active");
3660 if (pointCount <= 0)
3664 d->extended->drawPoints(points, pointCount);
3668 d->updateState(d->state);
3670 if (!d->state->emulationSpecifier) {
3671 d->engine->drawPoints(points, pointCount);
3675 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3676 && d->state->matrix.type() == QTransform::TxTranslate) {
3677 // ### use drawPoints function
3678 for (int i=0; i<pointCount; ++i) {
3679 QPointF pt(points[i].x() + d->state->matrix.dx(),
3680 points[i].y() + d->state->matrix.dy());
3681 d->engine->drawPoints(&pt, 1);
3684 QPen pen = d->state->pen;
3685 bool flat_pen = pen.capStyle() == Qt::FlatCap;
3688 pen.setCapStyle(Qt::SquareCap);
3692 for (int i=0; i<pointCount; ++i) {
3693 path.moveTo(points[i].x(), points[i].y());
3694 path.lineTo(points[i].x() + 0.0001, points[i].y());
3696 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3705 Draws the first \a pointCount points in the array \a points using
3706 the current pen's color.
3709 void QPainter::drawPoints(const QPoint *points, int pointCount)
3711 #ifdef QT_DEBUG_DRAW
3712 if (qt_show_painter_debug_output)
3713 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3718 qWarning("QPainter::drawPoints: Painter not active");
3722 if (pointCount <= 0)
3726 d->extended->drawPoints(points, pointCount);
3730 d->updateState(d->state);
3732 if (!d->state->emulationSpecifier) {
3733 d->engine->drawPoints(points, pointCount);
3737 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3738 && d->state->matrix.type() == QTransform::TxTranslate) {
3739 // ### use drawPoints function
3740 for (int i=0; i<pointCount; ++i) {
3741 QPointF pt(points[i].x() + d->state->matrix.dx(),
3742 points[i].y() + d->state->matrix.dy());
3743 d->engine->drawPoints(&pt, 1);
3746 QPen pen = d->state->pen;
3747 bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3750 pen.setCapStyle(Qt::SquareCap);
3754 for (int i=0; i<pointCount; ++i) {
3755 path.moveTo(points[i].x(), points[i].y());
3756 path.lineTo(points[i].x() + 0.0001, points[i].y());
3758 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3765 \fn void QPainter::drawPoints(const QPolygonF &points)
3769 Draws the points in the vector \a points.
3773 \fn void QPainter::drawPoints(const QPolygon &points)
3777 Draws the points in the vector \a points.
3781 Sets the background mode of the painter to the given \a mode
3783 Qt::TransparentMode (the default) draws stippled lines and text
3784 without setting the background pixels. Qt::OpaqueMode fills these
3785 space with the current background color.
3787 Note that in order to draw a bitmap or pixmap transparently, you
3788 must use QPixmap::setMask().
3790 \sa backgroundMode(), setBackground(),
3791 {QPainter#Settings}{Settings}
3794 void QPainter::setBackgroundMode(Qt::BGMode mode)
3796 #ifdef QT_DEBUG_DRAW
3797 if (qt_show_painter_debug_output)
3798 printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3803 qWarning("QPainter::setBackgroundMode: Painter not active");
3806 if (d->state->bgMode == mode)
3809 d->state->bgMode = mode;
3811 d->checkEmulation();
3813 d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3818 Returns the current background mode.
3820 \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3822 Qt::BGMode QPainter::backgroundMode() const
3824 Q_D(const QPainter);
3826 qWarning("QPainter::backgroundMode: Painter not active");
3827 return Qt::TransparentMode;
3829 return d->state->bgMode;
3836 Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3840 void QPainter::setPen(const QColor &color)
3842 #ifdef QT_DEBUG_DRAW
3843 if (qt_show_painter_debug_output)
3844 printf("QPainter::setPen(), color=%04x\n", color.rgb());
3848 qWarning("QPainter::setPen: Painter not active");
3852 if (d->state->pen.style() == Qt::SolidLine
3853 && d->state->pen.widthF() == 0
3854 && d->state->pen.isSolid()
3855 && d->state->pen.color() == color)
3858 QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
3860 d->state->pen = pen;
3862 d->extended->penChanged();
3864 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3868 Sets the painter's pen to be the given \a pen.
3870 The \a pen defines how to draw lines and outlines, and it also
3871 defines the text color.
3873 \sa pen(), {QPainter#Settings}{Settings}
3876 void QPainter::setPen(const QPen &pen)
3879 #ifdef QT_DEBUG_DRAW
3880 if (qt_show_painter_debug_output)
3881 printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3882 pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3886 qWarning("QPainter::setPen: Painter not active");
3890 if (d->state->pen == pen)
3893 d->state->pen = pen;
3896 d->checkEmulation();
3897 d->extended->penChanged();
3901 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3907 Sets the painter's pen to have the given \a style, width 0 and
3911 void QPainter::setPen(Qt::PenStyle style)
3915 qWarning("QPainter::setPen: Painter not active");
3919 if (d->state->pen.style() == style
3920 && (style == Qt::NoPen || (d->state->pen.widthF() == 0
3921 && d->state->pen.isSolid()
3922 && d->state->pen.color() == QColor(Qt::black))))
3925 // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
3926 // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
3927 d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
3930 d->extended->penChanged();
3932 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3937 Returns the painter's current pen.
3939 \sa setPen(), {QPainter#Settings}{Settings}
3942 const QPen &QPainter::pen() const
3944 Q_D(const QPainter);
3946 qWarning("QPainter::pen: Painter not active");
3947 return d->fakeState()->pen;
3949 return d->state->pen;
3954 Sets the painter's brush to the given \a brush.
3956 The painter's brush defines how shapes are filled.
3958 \sa brush(), {QPainter#Settings}{Settings}
3961 void QPainter::setBrush(const QBrush &brush)
3963 #ifdef QT_DEBUG_DRAW
3964 if (qt_show_painter_debug_output)
3965 printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
3969 qWarning("QPainter::setBrush: Painter not active");
3973 if (d->state->brush.d == brush.d)
3977 d->state->brush = brush;
3978 d->checkEmulation();
3979 d->extended->brushChanged();
3983 d->state->brush = brush;
3984 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
3991 Sets the painter's brush to black color and the specified \a
3995 void QPainter::setBrush(Qt::BrushStyle style)
3999 qWarning("QPainter::setBrush: Painter not active");
4002 if (d->state->brush.style() == style &&
4003 (style == Qt::NoBrush
4004 || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
4006 d->state->brush = QBrush(Qt::black, style);
4008 d->extended->brushChanged();
4010 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4014 Returns the painter's current brush.
4016 \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
4019 const QBrush &QPainter::brush() const
4021 Q_D(const QPainter);
4023 qWarning("QPainter::brush: Painter not active");
4024 return d->fakeState()->brush;
4026 return d->state->brush;
4030 \fn void QPainter::setBackground(const QBrush &brush)
4032 Sets the background brush of the painter to the given \a brush.
4034 The background brush is the brush that is filled in when drawing
4035 opaque text, stippled lines and bitmaps. The background brush has
4036 no effect in transparent background mode (which is the default).
4038 \sa background(), setBackgroundMode(),
4039 {QPainter#Settings}{Settings}
4042 void QPainter::setBackground(const QBrush &bg)
4044 #ifdef QT_DEBUG_DRAW
4045 if (qt_show_painter_debug_output)
4046 printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4051 qWarning("QPainter::setBackground: Painter not active");
4054 d->state->bgBrush = bg;
4056 d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4060 Sets the painter's font to the given \a font.
4062 This font is used by subsequent drawText() functions. The text
4063 color is the same as the pen color.
4065 If you set a font that isn't available, Qt finds a close match.
4066 font() will return what you set using setFont() and fontInfo() returns the
4067 font actually being used (which may be the same).
4069 \sa font(), drawText(), {QPainter#Settings}{Settings}
4072 void QPainter::setFont(const QFont &font)
4076 #ifdef QT_DEBUG_DRAW
4077 if (qt_show_painter_debug_output)
4078 printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4082 qWarning("QPainter::setFont: Painter not active");
4086 d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4088 d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4092 Returns the currently set font used for drawing text.
4094 \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4096 const QFont &QPainter::font() const
4098 Q_D(const QPainter);
4100 qWarning("QPainter::font: Painter not active");
4101 return d->fakeState()->font;
4103 return d->state->font;
4109 Draws the given rectangle \a rect with rounded corners.
4111 The \a xRadius and \a yRadius arguments specify the radii
4112 of the ellipses defining the corners of the rounded rectangle.
4113 When \a mode is Qt::RelativeSize, \a xRadius and
4114 \a yRadius are specified in percentage of half the rectangle's
4115 width and height respectively, and should be in the range
4118 A filled rectangle has a size of rect.size(). A stroked rectangle
4119 has a size of rect.size() plus the pen width.
4123 \li \inlineimage qpainter-roundrect.png
4125 \snippet code/src_gui_painting_qpainter.cpp 8
4128 \sa drawRect(), QPen
4130 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4132 #ifdef QT_DEBUG_DRAW
4133 if (qt_show_painter_debug_output)
4134 printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4141 if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
4147 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4152 path.addRoundedRect(rect, xRadius, yRadius, mode);
4157 \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4158 Qt::SizeMode mode = Qt::AbsoluteSize);
4162 Draws the given rectangle \a rect with rounded corners.
4166 \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4167 Qt::SizeMode mode = Qt::AbsoluteSize);
4171 Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4177 Draws a rectangle \a r with rounded corners.
4179 The \a xRnd and \a yRnd arguments specify how rounded the corners
4180 should be. 0 is angled corners, 99 is maximum roundedness.
4182 A filled rectangle has a size of r.size(). A stroked rectangle
4183 has a size of r.size() plus the pen width.
4185 \sa drawRoundedRect()
4187 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4189 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4194 \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4199 Draws the rectangle \a r with rounded corners.
4205 \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4209 Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4213 \fn void QPainter::drawEllipse(const QRectF &rectangle)
4215 Draws the ellipse defined by the given \a rectangle.
4217 A filled ellipse has a size of \a{rectangle}.\l
4218 {QRect::size()}{size()}. A stroked ellipse has a size of
4219 \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4223 \li \inlineimage qpainter-ellipse.png
4225 \snippet code/src_gui_painting_qpainter.cpp 9
4228 \sa drawPie(), {Coordinate System}
4230 void QPainter::drawEllipse(const QRectF &r)
4232 #ifdef QT_DEBUG_DRAW
4233 if (qt_show_painter_debug_output)
4234 printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4241 QRectF rect(r.normalized());
4244 d->extended->drawEllipse(rect);
4248 d->updateState(d->state);
4249 if (d->state->emulationSpecifier) {
4250 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4251 && d->state->matrix.type() == QTransform::TxTranslate) {
4252 rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4255 path.addEllipse(rect);
4256 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4261 d->engine->drawEllipse(rect);
4265 \fn QPainter::drawEllipse(const QRect &rectangle)
4269 Draws the ellipse defined by the given \a rectangle.
4271 void QPainter::drawEllipse(const QRect &r)
4273 #ifdef QT_DEBUG_DRAW
4274 if (qt_show_painter_debug_output)
4275 printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4282 QRect rect(r.normalized());
4285 d->extended->drawEllipse(rect);
4289 d->updateState(d->state);
4291 if (d->state->emulationSpecifier) {
4292 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4293 && d->state->matrix.type() == QTransform::TxTranslate) {
4294 rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4297 path.addEllipse(rect);
4298 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4303 d->engine->drawEllipse(rect);
4307 \fn QPainter::drawEllipse(int x, int y, int width, int height)
4311 Draws the ellipse defined by the rectangle beginning at (\a{x},
4312 \a{y}) with the given \a width and \a height.
4318 \fn QPainter::drawEllipse(const QPointF ¢er, qreal rx, qreal ry)
4322 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4328 \fn QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)
4332 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4336 \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4338 Draws the arc defined by the given \a rectangle, \a startAngle and
4341 The \a startAngle and \a spanAngle must be specified in 1/16th of
4342 a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4343 values for the angles mean counter-clockwise while negative values
4344 mean the clockwise direction. Zero degrees is at the 3 o'clock
4349 \li \inlineimage qpainter-arc.png
4351 \snippet code/src_gui_painting_qpainter.cpp 10
4354 \sa drawPie(), drawChord(), {Coordinate System}
4357 void QPainter::drawArc(const QRectF &r, int a, int alen)
4359 #ifdef QT_DEBUG_DRAW
4360 if (qt_show_painter_debug_output)
4361 printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4362 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4369 QRectF rect = r.normalized();
4372 path.arcMoveTo(rect, a/16.0);
4373 path.arcTo(rect, a/16.0, alen/16.0);
4374 strokePath(path, d->state->pen);
4377 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4382 Draws the arc defined by the given \a rectangle, \a startAngle and
4387 \fn void QPainter::drawArc(int x, int y, int width, int height,
4388 int startAngle, int spanAngle)
4392 Draws the arc defined by the rectangle beginning at (\a x, \a y)
4393 with the specified \a width and \a height, and the given \a
4394 startAngle and \a spanAngle.
4398 \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4400 Draws a pie defined by the given \a rectangle, \a startAngle and \a spanAngle.
4402 The pie is filled with the current brush().
4404 The startAngle and spanAngle must be specified in 1/16th of a
4405 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4406 for the angles mean counter-clockwise while negative values mean
4407 the clockwise direction. Zero degrees is at the 3 o'clock
4412 \li \inlineimage qpainter-pie.png
4414 \snippet code/src_gui_painting_qpainter.cpp 11
4417 \sa drawEllipse(), drawChord(), {Coordinate System}
4419 void QPainter::drawPie(const QRectF &r, int a, int alen)
4421 #ifdef QT_DEBUG_DRAW
4422 if (qt_show_painter_debug_output)
4423 printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4424 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4435 if (a < 0) a += (360*16);
4438 QRectF rect = r.normalized();
4441 path.moveTo(rect.center());
4442 path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4443 path.closeSubpath();
4449 \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4452 Draws a pie defined by the given \a rectangle, \a startAngle and
4457 \fn void QPainter::drawPie(int x, int y, int width, int height, int
4458 startAngle, int spanAngle)
4462 Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4463 the specified \a width and \a height, and the given \a startAngle and
4468 \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4470 Draws the chord defined by the given \a rectangle, \a startAngle and
4471 \a spanAngle. The chord is filled with the current brush().
4473 The startAngle and spanAngle must be specified in 1/16th of a
4474 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4475 for the angles mean counter-clockwise while negative values mean
4476 the clockwise direction. Zero degrees is at the 3 o'clock
4481 \li \inlineimage qpainter-chord.png
4483 \snippet code/src_gui_painting_qpainter.cpp 12
4486 \sa drawArc(), drawPie(), {Coordinate System}
4488 void QPainter::drawChord(const QRectF &r, int a, int alen)
4490 #ifdef QT_DEBUG_DRAW
4491 if (qt_show_painter_debug_output)
4492 printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4493 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4500 QRectF rect = r.normalized();
4503 path.arcMoveTo(rect, a/16.0);
4504 path.arcTo(rect, a/16.0, alen/16.0);
4505 path.closeSubpath();
4509 \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4513 Draws the chord defined by the given \a rectangle, \a startAngle and
4518 \fn void QPainter::drawChord(int x, int y, int width, int height, int
4519 startAngle, int spanAngle)
4523 Draws the chord defined by the rectangle beginning at (\a x, \a y)
4524 with the specified \a width and \a height, and the given \a
4525 startAngle and \a spanAngle.
4530 Draws the first \a lineCount lines in the array \a lines
4531 using the current pen.
4533 \sa drawLine(), drawPolyline()
4535 void QPainter::drawLines(const QLineF *lines, int lineCount)
4537 #ifdef QT_DEBUG_DRAW
4538 if (qt_show_painter_debug_output)
4539 printf("QPainter::drawLines(), line count=%d\n", lineCount);
4544 if (!d->engine || lineCount < 1)
4548 d->extended->drawLines(lines, lineCount);
4552 d->updateState(d->state);
4554 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4556 if (lineEmulation) {
4557 if (lineEmulation == QPaintEngine::PrimitiveTransform
4558 && d->state->matrix.type() == QTransform::TxTranslate) {
4559 for (int i = 0; i < lineCount; ++i) {
4560 QLineF line = lines[i];
4561 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4562 d->engine->drawLines(&line, 1);
4565 QPainterPath linePath;
4566 for (int i = 0; i < lineCount; ++i) {
4567 linePath.moveTo(lines[i].p1());
4568 linePath.lineTo(lines[i].p2());
4570 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4574 d->engine->drawLines(lines, lineCount);
4578 \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4581 Draws the first \a lineCount lines in the array \a lines
4582 using the current pen.
4584 void QPainter::drawLines(const QLine *lines, int lineCount)
4586 #ifdef QT_DEBUG_DRAW
4587 if (qt_show_painter_debug_output)
4588 printf("QPainter::drawLine(), line count=%d\n", lineCount);
4593 if (!d->engine || lineCount < 1)
4597 d->extended->drawLines(lines, lineCount);
4601 d->updateState(d->state);
4603 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4605 if (lineEmulation) {
4606 if (lineEmulation == QPaintEngine::PrimitiveTransform
4607 && d->state->matrix.type() == QTransform::TxTranslate) {
4608 for (int i = 0; i < lineCount; ++i) {
4609 QLineF line = lines[i];
4610 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4611 d->engine->drawLines(&line, 1);
4614 QPainterPath linePath;
4615 for (int i = 0; i < lineCount; ++i) {
4616 linePath.moveTo(lines[i].p1());
4617 linePath.lineTo(lines[i].p2());
4619 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4623 d->engine->drawLines(lines, lineCount);
4629 Draws the first \a lineCount lines in the array \a pointPairs
4630 using the current pen. The lines are specified as pairs of points
4631 so the number of entries in \a pointPairs must be at least \a
4634 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4636 Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4638 drawLines((QLineF*)pointPairs, lineCount);
4644 Draws the first \a lineCount lines in the array \a pointPairs
4645 using the current pen.
4647 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4649 Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4651 drawLines((QLine*)pointPairs, lineCount);
4656 \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4659 Draws a line for each pair of points in the vector \a pointPairs
4660 using the current pen. If there is an odd number of points in the
4661 array, the last point will be ignored.
4665 \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4668 Draws a line for each pair of points in the vector \a pointPairs
4669 using the current pen.
4673 \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4676 Draws the set of lines defined by the list \a lines using the
4677 current pen and brush.
4681 \fn void QPainter::drawLines(const QVector<QLine> &lines)
4684 Draws the set of lines defined by the list \a lines using the
4685 current pen and brush.
4689 Draws the polyline defined by the first \a pointCount points in \a
4690 points using the current pen.
4692 Note that unlike the drawPolygon() function the last point is \e
4693 not connected to the first, neither is the polyline filled.
4698 \snippet code/src_gui_painting_qpainter.cpp 13
4701 \sa drawLines(), drawPolygon(), {Coordinate System}
4703 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4705 #ifdef QT_DEBUG_DRAW
4706 if (qt_show_painter_debug_output)
4707 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4711 if (!d->engine || pointCount < 2)
4715 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4719 d->updateState(d->state);
4721 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4723 if (lineEmulation) {
4725 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4726 // && d->state->matrix.type() == QTransform::TxTranslate) {
4728 QPainterPath polylinePath(points[0]);
4729 for (int i=1; i<pointCount; ++i)
4730 polylinePath.lineTo(points[i]);
4731 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4734 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4741 Draws the polyline defined by the first \a pointCount points in \a
4742 points using the current pen.
4744 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4746 #ifdef QT_DEBUG_DRAW
4747 if (qt_show_painter_debug_output)
4748 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4752 if (!d->engine || pointCount < 2)
4756 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4760 d->updateState(d->state);
4762 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4764 if (lineEmulation) {
4766 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4767 // && d->state->matrix.type() == QTransform::TxTranslate) {
4769 QPainterPath polylinePath(points[0]);
4770 for (int i=1; i<pointCount; ++i)
4771 polylinePath.lineTo(points[i]);
4772 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4775 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4780 \fn void QPainter::drawPolyline(const QPolygonF &points)
4784 Draws the polyline defined by the given \a points using the
4789 \fn void QPainter::drawPolyline(const QPolygon &points)
4793 Draws the polyline defined by the given \a points using the
4798 Draws the polygon defined by the first \a pointCount points in the
4799 array \a points using the current pen and brush.
4803 \li \inlineimage qpainter-polygon.png
4805 \snippet code/src_gui_painting_qpainter.cpp 14
4808 The first point is implicitly connected to the last point, and the
4809 polygon is filled with the current brush().
4811 If \a fillRule is Qt::WindingFill, the polygon is filled using the
4812 winding fill algorithm. If \a fillRule is Qt::OddEvenFill, the
4813 polygon is filled using the odd-even fill algorithm. See
4814 \l{Qt::FillRule} for a more detailed description of these fill
4817 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
4819 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
4821 #ifdef QT_DEBUG_DRAW
4822 if (qt_show_painter_debug_output)
4823 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4828 if (!d->engine || pointCount < 2)
4832 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4836 d->updateState(d->state);
4838 uint emulationSpecifier = d->state->emulationSpecifier;
4840 if (emulationSpecifier) {
4841 QPainterPath polygonPath(points[0]);
4842 for (int i=1; i<pointCount; ++i)
4843 polygonPath.lineTo(points[i]);
4844 polygonPath.closeSubpath();
4845 polygonPath.setFillRule(fillRule);
4846 d->draw_helper(polygonPath);
4850 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4855 Draws the polygon defined by the first \a pointCount points in the
4858 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
4860 #ifdef QT_DEBUG_DRAW
4861 if (qt_show_painter_debug_output)
4862 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4867 if (!d->engine || pointCount < 2)
4871 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4875 d->updateState(d->state);
4877 uint emulationSpecifier = d->state->emulationSpecifier;
4879 if (emulationSpecifier) {
4880 QPainterPath polygonPath(points[0]);
4881 for (int i=1; i<pointCount; ++i)
4882 polygonPath.lineTo(points[i]);
4883 polygonPath.closeSubpath();
4884 polygonPath.setFillRule(fillRule);
4885 d->draw_helper(polygonPath);
4889 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4892 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
4896 Draws the polygon defined by the given \a points using the fill
4900 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
4904 Draws the polygon defined by the given \a points using the fill
4909 \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4911 Draws the convex polygon defined by the first \a pointCount points
4912 in the array \a points using the current pen.
4916 \li \inlineimage qpainter-polygon.png
4918 \snippet code/src_gui_painting_qpainter.cpp 15
4921 The first point is implicitly connected to the last point, and the
4922 polygon is filled with the current brush(). If the supplied
4923 polygon is not convex, i.e. it contains at least one angle larger
4924 than 180 degrees, the results are undefined.
4926 On some platforms (e.g. X11), the drawConvexPolygon() function can
4927 be faster than the drawPolygon() function.
4929 \sa drawPolygon(), drawPolyline(), {Coordinate System}
4933 \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4936 Draws the convex polygon defined by the first \a pointCount points
4937 in the array \a points using the current pen.
4941 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
4945 Draws the convex polygon defined by \a polygon using the current
4950 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
4953 Draws the convex polygon defined by \a polygon using the current
4957 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4959 #ifdef QT_DEBUG_DRAW
4960 if (qt_show_painter_debug_output)
4961 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4966 if (!d->engine || pointCount < 2)
4970 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4974 d->updateState(d->state);
4976 uint emulationSpecifier = d->state->emulationSpecifier;
4978 if (emulationSpecifier) {
4979 QPainterPath polygonPath(points[0]);
4980 for (int i=1; i<pointCount; ++i)
4981 polygonPath.lineTo(points[i]);
4982 polygonPath.closeSubpath();
4983 polygonPath.setFillRule(Qt::WindingFill);
4984 d->draw_helper(polygonPath);
4988 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4991 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4993 #ifdef QT_DEBUG_DRAW
4994 if (qt_show_painter_debug_output)
4995 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5000 if (!d->engine || pointCount < 2)
5004 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5008 d->updateState(d->state);
5010 uint emulationSpecifier = d->state->emulationSpecifier;
5012 if (emulationSpecifier) {
5013 QPainterPath polygonPath(points[0]);
5014 for (int i=1; i<pointCount; ++i)
5015 polygonPath.lineTo(points[i]);
5016 polygonPath.closeSubpath();
5017 polygonPath.setFillRule(Qt::WindingFill);
5018 d->draw_helper(polygonPath);
5022 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5025 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5027 return m.inverted().map(QPointF(m.map(p).toPoint()));
5031 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5033 Draws the rectangular portion \a source of the given \a pixmap
5034 into the given \a target in the paint device.
5036 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5041 \snippet code/src_gui_painting_qpainter.cpp 16
5044 If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5045 using the pens color. If backgroundMode is Qt::OpaqueMode, the
5046 "unset" bits are drawn using the color of the background brush; if
5047 backgroundMode is Qt::TransparentMode, the "unset" bits are
5048 transparent. Drawing bitmaps with gradient or texture colors is
5053 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5055 #if defined QT_DEBUG_DRAW
5056 if (qt_show_painter_debug_output)
5057 printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5059 pm.width(), pm.height());
5064 if (!d->engine || pm.isNull())
5068 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5072 d->extended->drawPixmap(p, pm);
5080 int h = pm.height();
5085 // Emulate opaque background for bitmaps
5086 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5087 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5090 d->updateState(d->state);
5092 if ((d->state->matrix.type() > QTransform::TxTranslate
5093 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5094 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5095 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5098 // If there is no rotation involved we have to make sure we use the
5099 // antialiased and not the aliased coordinate system by rounding the coordinates.
5100 if (d->state->matrix.type() <= QTransform::TxScale) {
5101 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5106 setBackgroundMode(Qt::TransparentMode);
5107 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5108 QBrush brush(d->state->pen.color(), pm);
5111 setBrushOrigin(QPointF(0, 0));
5113 drawRect(pm.rect());
5116 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5117 x += d->state->matrix.dx();
5118 y += d->state->matrix.dy();
5120 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5124 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5126 #if defined QT_DEBUG_DRAW
5127 if (qt_show_painter_debug_output)
5128 printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5129 r.x(), r.y(), r.width(), r.height(),
5130 pm.width(), pm.height(),
5131 sr.x(), sr.y(), sr.width(), sr.height());
5135 if (!d->engine || pm.isNull())
5138 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5143 qreal w = r.width();
5144 qreal h = r.height();
5147 qreal sw = sr.width();
5148 qreal sh = sr.height();
5150 // Sanity-check clipping
5152 sw = pm.width() - sx;
5155 sh = pm.height() - sy;
5163 qreal w_ratio = sx * w/sw;
5171 qreal h_ratio = sy * h/sh;
5178 if (sw + sx > pm.width()) {
5179 qreal delta = sw - (pm.width() - sx);
5180 qreal w_ratio = delta * w/sw;
5185 if (sh + sy > pm.height()) {
5186 qreal delta = sh - (pm.height() - sy);
5187 qreal h_ratio = delta * h/sh;
5192 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5196 d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5200 // Emulate opaque background for bitmaps
5201 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5202 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5204 d->updateState(d->state);
5206 if ((d->state->matrix.type() > QTransform::TxTranslate
5207 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5208 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5209 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5210 || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5213 // If there is no rotation involved we have to make sure we use the
5214 // antialiased and not the aliased coordinate system by rounding the coordinates.
5215 if (d->state->matrix.type() <= QTransform::TxScale) {
5216 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5221 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5229 scale(w / sw, h / sh);
5230 setBackgroundMode(Qt::TransparentMode);
5231 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5234 if (sw == pm.width() && sh == pm.height())
5235 brush = QBrush(d->state->pen.color(), pm);
5237 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5242 drawRect(QRectF(0, 0, sw, sh));
5245 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5246 x += d->state->matrix.dx();
5247 y += d->state->matrix.dy();
5249 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5255 \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5256 const QRect &source)
5259 Draws the rectangular portion \a source of the given \a pixmap
5260 into the given \a target in the paint device.
5262 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5266 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5267 const QRectF &source)
5270 Draws the rectangular portion \a source of the given \a pixmap
5271 with its origin at the given \a point.
5275 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5276 const QRect &source)
5280 Draws the rectangular portion \a source of the given \a pixmap
5281 with its origin at the given \a point.
5285 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5288 Draws the given \a pixmap with its origin at the given \a point.
5292 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5295 Draws the given \a pixmap with its origin at the given \a point.
5299 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5303 Draws the given \a pixmap at position (\a{x}, \a{y}).
5307 \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5310 Draws the given \a pixmap into the given \a rectangle.
5312 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5316 \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5317 const QPixmap &pixmap)
5321 Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5322 with the given \a width and \a height.
5326 \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5327 int sx, int sy, int sw, int sh)
5331 Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5332 width \a sw and height \a sh, of the given \a pixmap , at the
5333 point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5334 If sw or sh are equal to zero the width/height of the pixmap
5335 is used and adjusted by the offset sx/sy;
5339 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5340 int sx, int sy, int sw, int sh)
5344 Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5345 pixmap into the paint device.
5347 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5348 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5349 pixmap that is to be drawn. The default is (0, 0).
5351 (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5352 The default, (0, 0) (and negative) means all the way to the
5353 bottom-right of the pixmap.
5356 void QPainter::drawImage(const QPointF &p, const QImage &image)
5360 if (!d->engine || image.isNull())
5364 d->extended->drawImage(p, image);
5371 int w = image.width();
5372 int h = image.height();
5374 d->updateState(d->state);
5376 if (((d->state->matrix.type() > QTransform::TxTranslate)
5377 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5378 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5379 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5382 // If there is no rotation involved we have to make sure we use the
5383 // antialiased and not the aliased coordinate system by rounding the coordinates.
5384 if (d->state->matrix.type() <= QTransform::TxScale) {
5385 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5390 setBackgroundMode(Qt::TransparentMode);
5391 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5392 QBrush brush(image);
5395 setBrushOrigin(QPointF(0, 0));
5397 drawRect(image.rect());
5402 if (d->state->matrix.type() == QTransform::TxTranslate
5403 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5404 x += d->state->matrix.dx();
5405 y += d->state->matrix.dy();
5408 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5411 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5412 Qt::ImageConversionFlags flags)
5416 if (!d->engine || image.isNull())
5419 qreal x = targetRect.x();
5420 qreal y = targetRect.y();
5421 qreal w = targetRect.width();
5422 qreal h = targetRect.height();
5423 qreal sx = sourceRect.x();
5424 qreal sy = sourceRect.y();
5425 qreal sw = sourceRect.width();
5426 qreal sh = sourceRect.height();
5428 // Sanity-check clipping
5430 sw = image.width() - sx;
5433 sh = image.height() - sy;
5441 qreal w_ratio = sx * w/sw;
5449 qreal h_ratio = sy * h/sh;
5456 if (sw + sx > image.width()) {
5457 qreal delta = sw - (image.width() - sx);
5458 qreal w_ratio = delta * w/sw;
5463 if (sh + sy > image.height()) {
5464 qreal delta = sh - (image.height() - sy);
5465 qreal h_ratio = delta * h/sh;
5470 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5474 d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5478 d->updateState(d->state);
5480 if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5481 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5482 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5483 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5486 // If there is no rotation involved we have to make sure we use the
5487 // antialiased and not the aliased coordinate system by rounding the coordinates.
5488 if (d->state->matrix.type() <= QTransform::TxScale) {
5489 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5494 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5501 scale(w / sw, h / sh);
5502 setBackgroundMode(Qt::TransparentMode);
5503 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5504 QBrush brush(image);
5507 setBrushOrigin(QPointF(-sx, -sy));
5509 drawRect(QRectF(0, 0, sw, sh));
5514 if (d->state->matrix.type() == QTransform::TxTranslate
5515 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5516 x += d->state->matrix.dx();
5517 y += d->state->matrix.dy();
5520 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5524 \fn void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphs)
5526 Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5527 edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5528 selected on \a glyphs and at offsets given by the positions in \a glyphs.
5532 \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes()
5534 #if !defined(QT_NO_RAWFONT)
5535 void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
5539 QRawFont font = glyphRun.rawFont();
5540 if (!font.isValid())
5543 QGlyphRunPrivate *glyphRun_d = QGlyphRunPrivate::get(glyphRun);
5545 const quint32 *glyphIndexes = glyphRun_d->glyphIndexData;
5546 const QPointF *glyphPositions = glyphRun_d->glyphPositionData;
5548 int count = qMin(glyphRun_d->glyphIndexDataSize, glyphRun_d->glyphPositionDataSize);
5549 QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5551 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5552 bool supportsTransformations = d->extended
5553 ? d->extended->supportsTransformations(fontD->fontEngine, d->state->matrix)
5554 : d->engine->type() == QPaintEngine::CoreGraphics || d->state->matrix.isAffine();
5556 for (int i=0; i<count; ++i) {
5557 QPointF processedPosition = position + glyphPositions[i];
5558 if (!supportsTransformations)
5559 processedPosition = d->state->transform().map(processedPosition);
5560 fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5563 d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, font, glyphRun.overline(),
5564 glyphRun.underline(), glyphRun.strikeOut());
5567 void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions,
5569 const QRawFont &font, bool overline, bool underline,
5576 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5577 QFontEngine *fontEngine = fontD->fontEngine;
5582 for (int i=0; i<glyphCount; ++i) {
5583 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5584 if (i == 0 || leftMost > positions[i].x)
5585 leftMost = positions[i].x;
5587 // We don't support glyphs that do not share a common baseline. If this turns out to
5588 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5589 // and do a drawTextItemDecorations call per cluster.
5590 if (i == 0 || baseLine < positions[i].y)
5591 baseLine = positions[i].y;
5593 // We use the advance rather than the actual bounds to match the algorithm in drawText()
5594 if (i == 0 || rightMost < positions[i].x + gm.xoff)
5595 rightMost = positions[i].x + gm.xoff;
5598 QFixed width = rightMost - leftMost;
5600 if (extended != 0 && state->matrix.isAffine()) {
5601 QStaticTextItem staticTextItem;
5602 staticTextItem.color = state->pen.color();
5603 staticTextItem.font = state->font;
5604 staticTextItem.setFontEngine(fontEngine);
5605 staticTextItem.numGlyphs = glyphCount;
5606 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5607 staticTextItem.glyphPositions = positions;
5609 extended->drawStaticTextItem(&staticTextItem);
5611 QTextItemInt textItem;
5612 textItem.fontEngine = fontEngine;
5614 QVarLengthArray<QFixed, 128> advances(glyphCount);
5615 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5616 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5617 memset(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5618 memset(advances.data(), 0, advances.size() * sizeof(QFixed));
5619 memset(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5621 textItem.glyphs.numGlyphs = glyphCount;
5622 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5623 textItem.glyphs.offsets = positions;
5624 textItem.glyphs.advances_x = advances.data();
5625 textItem.glyphs.advances_y = advances.data();
5626 textItem.glyphs.justifications = glyphJustifications.data();
5627 textItem.glyphs.attributes = glyphAttributes.data();
5629 engine->drawTextItem(QPointF(0, 0), textItem);
5632 QTextItemInt::RenderFlags flags;
5634 flags |= QTextItemInt::Underline;
5636 flags |= QTextItemInt::Overline;
5638 flags |= QTextItemInt::StrikeOut;
5640 drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5644 ? QTextCharFormat::SingleUnderline
5645 : QTextCharFormat::NoUnderline),
5646 flags, width.toReal(), QTextCharFormat());
5648 #endif // QT_NO_RAWFONT
5652 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5656 Draws the \a staticText at the \a topLeftPosition.
5658 \note The y-position is used as the top of the font.
5663 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5667 Draws the \a staticText at coordinates \a left and \a top.
5669 \note The y-position is used as the top of the font.
5673 \fn void QPainter::drawText(const QPointF &position, const QString &text)
5675 Draws the given \a text with the currently defined text direction,
5676 beginning at the given \a position.
5678 This function does not handle the newline character (\\n), as it cannot
5679 break text into multiple lines, and it cannot display the newline character.
5680 Use the QPainter::drawText() overload that takes a rectangle instead
5681 if you want to draw multiple lines of text with the newline character, or
5682 if you want the text to be wrapped.
5684 By default, QPainter draws text anti-aliased.
5686 \note The y-position is used as the baseline of the font.
5688 \sa setFont(), setPen()
5691 void QPainter::drawText(const QPointF &p, const QString &str)
5693 drawText(p, str, 0, 0);
5699 Draws the given \a staticText at the given \a topLeftPosition.
5701 The text will be drawn using the font and the transformation set on the painter. If the
5702 font and/or transformation set on the painter are different from the ones used to initialize
5703 the layout of the QStaticText, then the layout will have to be recalculated. Use
5704 QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5705 it will later be drawn.
5707 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5708 last drawn, then there will be a slight overhead when translating the text to its new position.
5710 \note If the painter's transformation is not affine, then \a staticText will be drawn using
5711 regular calls to drawText(), losing any potential for performance improvement.
5713 \note The y-position is used as the top of the font.
5717 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5720 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5723 QStaticTextPrivate *staticText_d =
5724 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5726 if (font() != staticText_d->font) {
5727 staticText_d->font = font();
5728 staticText_d->needsRelayout = true;
5731 // If we don't have an extended paint engine, or if the painter is projected,
5732 // we go through standard code path
5733 if (d->extended == 0 || !d->state->matrix.isAffine()) {
5734 staticText_d->paintText(topLeftPosition, this);
5738 QFontEngine *fe = staticText_d->font.d->engineForScript(QUnicodeTables::Common);
5739 if (fe->type() == QFontEngine::Multi)
5740 fe = static_cast<QFontEngineMulti *>(fe)->engine(0);
5741 bool supportsTransformations = d->extended->supportsTransformations(fe,
5743 if (supportsTransformations && !staticText_d->untransformedCoordinates) {
5744 staticText_d->untransformedCoordinates = true;
5745 staticText_d->needsRelayout = true;
5746 } else if (!supportsTransformations && staticText_d->untransformedCoordinates) {
5747 staticText_d->untransformedCoordinates = false;
5748 staticText_d->needsRelayout = true;
5751 // Don't recalculate entire layout because of translation, rather add the dx and dy
5752 // into the position to move each text item the correct distance.
5753 QPointF transformedPosition = topLeftPosition;
5754 if (!staticText_d->untransformedCoordinates)
5755 transformedPosition = transformedPosition * d->state->matrix;
5756 QTransform oldMatrix;
5758 // The translation has been applied to transformedPosition. Remove translation
5759 // component from matrix.
5760 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
5761 qreal m11 = d->state->matrix.m11();
5762 qreal m12 = d->state->matrix.m12();
5763 qreal m13 = d->state->matrix.m13();
5764 qreal m21 = d->state->matrix.m21();
5765 qreal m22 = d->state->matrix.m22();
5766 qreal m23 = d->state->matrix.m23();
5767 qreal m33 = d->state->matrix.m33();
5769 oldMatrix = d->state->matrix;
5770 d->state->matrix.setMatrix(m11, m12, m13,
5775 // If the transform is not identical to the text transform,
5776 // we have to relayout the text (for other transformations than plain translation)
5777 bool staticTextNeedsReinit = staticText_d->needsRelayout;
5778 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
5779 staticText_d->matrix = d->state->matrix;
5780 staticTextNeedsReinit = true;
5783 // Recreate the layout of the static text because the matrix or font has changed
5784 if (staticTextNeedsReinit)
5785 staticText_d->init();
5787 if (transformedPosition != staticText_d->position) { // Translate to actual position
5788 QFixed fx = QFixed::fromReal(transformedPosition.x());
5789 QFixed fy = QFixed::fromReal(transformedPosition.y());
5790 QFixed oldX = QFixed::fromReal(staticText_d->position.x());
5791 QFixed oldY = QFixed::fromReal(staticText_d->position.y());
5792 for (int item=0; item<staticText_d->itemCount;++item) {
5793 QStaticTextItem *textItem = staticText_d->items + item;
5794 for (int i=0; i<textItem->numGlyphs; ++i) {
5795 textItem->glyphPositions[i].x += fx - oldX;
5796 textItem->glyphPositions[i].y += fy - oldY;
5798 textItem->userDataNeedsUpdate = true;
5801 staticText_d->position = transformedPosition;
5804 QPen oldPen = d->state->pen;
5805 QColor currentColor = oldPen.color();
5806 for (int i=0; i<staticText_d->itemCount; ++i) {
5807 QStaticTextItem *item = staticText_d->items + i;
5808 if (item->color.isValid() && currentColor != item->color) {
5809 setPen(item->color);
5810 currentColor = item->color;
5812 d->extended->drawStaticTextItem(item);
5814 qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
5815 item->numGlyphs, item->fontEngine(), staticText_d->font,
5818 if (currentColor != oldPen.color())
5821 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
5822 d->state->matrix = oldMatrix;
5828 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
5830 #ifdef QT_DEBUG_DRAW
5831 if (qt_show_painter_debug_output)
5832 printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
5837 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
5840 if (tf & Qt::TextBypassShaping) {
5841 // Skip harfbuzz complex shaping, shape using glyph advances only
5842 int len = str.length();
5843 int numGlyphs = len;
5844 QVarLengthGlyphLayoutArray glyphs(len);
5845 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
5846 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
5847 glyphs.resize(numGlyphs);
5848 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
5849 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
5852 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
5853 drawTextItem(p, gf);
5857 QStackTextEngine engine(str, d->state->font);
5858 engine.option.setTextDirection(d->state->layoutDirection);
5859 if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
5860 engine.ignoreBidi = true;
5861 engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
5865 line.length = str.length();
5866 engine.shapeLine(line);
5868 int nItems = engine.layoutData->items.size();
5869 QVarLengthArray<int> visualOrder(nItems);
5870 QVarLengthArray<uchar> levels(nItems);
5871 for (int i = 0; i < nItems; ++i)
5872 levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
5873 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
5875 if (justificationPadding > 0) {
5876 engine.option.setAlignment(Qt::AlignJustify);
5877 engine.forceJustification = true;
5878 // this works because justify() is only interested in the difference between width and textWidth
5879 line.width = justificationPadding;
5880 engine.justify(line);
5882 QFixed x = QFixed::fromReal(p.x());
5884 for (int i = 0; i < nItems; ++i) {
5885 int item = visualOrder[i];
5886 const QScriptItem &si = engine.layoutData->items.at(item);
5887 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
5891 QFont f = engine.font(si);
5892 QTextItemInt gf(si, &f);
5893 gf.glyphs = engine.shapedGlyphs(&si);
5894 gf.chars = engine.layoutData->string.unicode() + si.position;
5895 gf.num_chars = engine.length(item);
5896 if (engine.forceJustification) {
5897 for (int j=0; j<gf.glyphs.numGlyphs; ++j)
5898 gf.width += gf.glyphs.effectiveAdvance(j);
5900 gf.width = si.width;
5902 gf.logClusters = engine.logClusters(&si);
5904 drawTextItem(QPointF(x.toReal(), p.y()), gf);
5910 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
5912 #ifdef QT_DEBUG_DRAW
5913 if (qt_show_painter_debug_output)
5914 printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
5915 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5920 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5924 d->updateState(d->state);
5927 qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
5929 *br = bounds.toAlignedRect();
5933 \fn void QPainter::drawText(const QPoint &position, const QString &text)
5937 Draws the given \a text with the currently defined text direction,
5938 beginning at the given \a position.
5940 By default, QPainter draws text anti-aliased.
5942 \note The y-position is used as the baseline of the font.
5944 \sa setFont(), setPen()
5948 \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
5951 Draws the given \a text within the provided \a rectangle.
5952 The \a rectangle along with alignment \a flags defines the anchors for the \a text.
5956 \li \inlineimage qpainter-text.png
5958 \snippet code/src_gui_painting_qpainter.cpp 17
5961 The \a boundingRect (if not null) is set to the what the bounding rectangle
5962 should be in order to enclose the whole text. The \a flags argument is a bitwise
5963 OR of the following flags:
5968 \li Qt::AlignHCenter
5969 \li Qt::AlignJustify
5972 \li Qt::AlignVCenter
5974 \li Qt::TextDontClip
5975 \li Qt::TextSingleLine
5976 \li Qt::TextExpandTabs
5977 \li Qt::TextShowMnemonic
5978 \li Qt::TextWordWrap
5979 \li Qt::TextIncludeTrailingSpaces
5982 \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
5984 By default, QPainter draws text anti-aliased.
5986 \note The y-coordinate of \a rectangle is used as the top of the font.
5988 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
5990 #ifdef QT_DEBUG_DRAW
5991 if (qt_show_painter_debug_output)
5992 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
5993 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5998 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6002 d->updateState(d->state);
6004 qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
6008 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
6011 Draws the given \a text within the provided \a rectangle according
6012 to the specified \a flags. The \a boundingRect (if not null) is set to
6013 the what the bounding rectangle should be in order to enclose the whole text.
6015 By default, QPainter draws text anti-aliased.
6017 \note The y-coordinate of \a rectangle is used as the top of the font.
6019 \sa setFont(), setPen()
6023 \fn void QPainter::drawText(int x, int y, const QString &text)
6027 Draws the given \a text at position (\a{x}, \a{y}), using the painter's
6028 currently defined text direction.
6030 By default, QPainter draws text anti-aliased.
6032 \note The y-position is used as the baseline of the font.
6034 \sa setFont(), setPen()
6038 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6039 const QString &text, QRect *boundingRect)
6043 Draws the given \a text within the rectangle with origin (\a{x},
6044 \a{y}), \a width and \a height.
6046 The \a boundingRect (if not null) is set to the actual bounding
6047 rectangle of the output. The \a flags argument is a bitwise OR of
6048 the following flags:
6053 \li Qt::AlignHCenter
6054 \li Qt::AlignJustify
6057 \li Qt::AlignVCenter
6059 \li Qt::TextSingleLine
6060 \li Qt::TextExpandTabs
6061 \li Qt::TextShowMnemonic
6062 \li Qt::TextWordWrap
6065 By default, QPainter draws text anti-aliased.
6067 \note The y-position is used as the top of the font.
6069 \sa Qt::AlignmentFlag, Qt::TextFlag, setFont(), setPen()
6073 \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6074 const QTextOption &option)
6077 Draws the given \a text in the \a rectangle specified using the \a option
6078 to control its positioning and orientation.
6080 By default, QPainter draws text anti-aliased.
6082 \note The y-coordinate of \a rectangle is used as the top of the font.
6084 \sa setFont(), setPen()
6086 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6088 #ifdef QT_DEBUG_DRAW
6089 if (qt_show_painter_debug_output)
6090 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6091 r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6096 if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6100 d->updateState(d->state);
6102 qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6106 \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6113 \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6118 Draws the text item \a ti at position \a p.
6122 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6127 Draws the text item \a ti at position \a p.
6129 This method ignores the painters background mode and
6130 color. drawText and qt_format_text have to do it themselves, as
6131 only they know the extents of the complete string.
6133 It ignores the font set on the painter as the text item has one of its own.
6135 The underline and strikeout parameters of the text items font are
6136 ignored aswell. You'll need to pass in the correct flags to get
6137 underlining and strikeout.
6140 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6142 const qreal radiusBase = qMax(qreal(1), maxRadius);
6144 QString key = QLatin1String("WaveUnderline-")
6145 % pen.color().name()
6146 % HexString<qreal>(radiusBase);
6149 if (QPixmapCache::find(key, pixmap))
6152 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6153 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6154 const int radius = qFloor(radiusBase);
6161 while (xs < width) {
6164 path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6167 pixmap = QPixmap(width, radius * 2);
6168 pixmap.fill(Qt::transparent);
6171 wavePen.setCapStyle(Qt::SquareCap);
6173 // This is to protect against making the line too fat, as happens on Mac OS X
6174 // due to it having a rather thick width for the regular underline.
6175 const qreal maxPenWidth = .8 * radius;
6176 if (wavePen.widthF() > maxPenWidth)
6177 wavePen.setWidth(maxPenWidth);
6179 QPainter imgPainter(&pixmap);
6180 imgPainter.setPen(wavePen);
6181 imgPainter.setRenderHint(QPainter::Antialiasing);
6182 imgPainter.translate(0, radius);
6183 imgPainter.drawPath(path);
6186 QPixmapCache::insert(key, pixmap);
6191 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
6192 QTextCharFormat::UnderlineStyle underlineStyle,
6193 QTextItem::RenderFlags flags, qreal width,
6194 const QTextCharFormat &charFormat)
6196 if (underlineStyle == QTextCharFormat::NoUnderline
6197 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6200 const QPen oldPen = painter->pen();
6201 const QBrush oldBrush = painter->brush();
6202 painter->setBrush(Qt::NoBrush);
6204 pen.setStyle(Qt::SolidLine);
6205 pen.setWidthF(fe->lineThickness().toReal());
6206 pen.setCapStyle(Qt::FlatCap);
6208 QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6210 const qreal underlineOffset = fe->underlinePosition().toReal();
6211 // deliberately ceil the offset to avoid the underline coming too close to
6212 // the text above it.
6213 const qreal underlinePos = pos.y() + qCeil(underlineOffset);
6215 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6216 QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
6218 underlineStyle = QTextCharFormat::UnderlineStyle(theme->themeHint(QPlatformTheme::SpellCheckUnderlineStyle).toInt());
6221 if (underlineStyle == QTextCharFormat::WaveUnderline) {
6223 painter->translate(0, pos.y() + 1);
6225 QColor uc = charFormat.underlineColor();
6229 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6230 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6231 const int descent = (int) fe->descent().toReal();
6233 painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6234 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6236 } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6237 QColor uc = charFormat.underlineColor();
6241 pen.setStyle((Qt::PenStyle)(underlineStyle));
6242 painter->setPen(pen);
6243 QLineF underline(line.x1(), underlinePos, line.x2(), underlinePos);
6245 textEngine->addUnderline(painter, underline);
6247 painter->drawLine(underline);
6250 pen.setStyle(Qt::SolidLine);
6251 pen.setColor(oldPen.color());
6253 if (flags & QTextItem::StrikeOut) {
6254 QLineF strikeOutLine = line;
6255 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6256 painter->setPen(pen);
6258 textEngine->addStrikeOut(painter, strikeOutLine);
6260 painter->drawLine(strikeOutLine);
6263 if (flags & QTextItem::Overline) {
6264 QLineF overline = line;
6265 overline.translate(0., - fe->ascent().toReal());
6266 painter->setPen(pen);
6268 textEngine->addOverline(painter, overline);
6270 painter->drawLine(overline);
6273 painter->setPen(oldPen);
6274 painter->setBrush(oldBrush);
6277 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6278 const QFixedPoint *positions, int glyphCount,
6279 QFontEngine *fontEngine, const QFont &font,
6280 const QTextCharFormat &charFormat)
6282 if (!(font.underline() || font.strikeOut() || font.overline()))
6288 for (int i=0; i<glyphCount; ++i) {
6289 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6290 if (i == 0 || leftMost > positions[i].x)
6291 leftMost = positions[i].x;
6293 // We don't support glyphs that do not share a common baseline. If this turns out to
6294 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6295 // and do a drawTextItemDecoration call per cluster.
6296 if (i == 0 || baseLine < positions[i].y)
6297 baseLine = positions[i].y;
6299 // We use the advance rather than the actual bounds to match the algorithm in drawText()
6300 if (i == 0 || rightMost < positions[i].x + gm.xoff)
6301 rightMost = positions[i].x + gm.xoff;
6304 QFixed width = rightMost - leftMost;
6305 QTextItem::RenderFlags flags = 0;
6307 if (font.underline())
6308 flags |= QTextItem::Underline;
6309 if (font.overline())
6310 flags |= QTextItem::Overline;
6311 if (font.strikeOut())
6312 flags |= QTextItem::StrikeOut;
6314 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6317 font.underline() ? QTextCharFormat::SingleUnderline
6318 : QTextCharFormat::NoUnderline, flags,
6319 width.toReal(), charFormat);
6322 void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6326 d->drawTextItem(p, ti, static_cast<QTextEngine *>(0));
6329 void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine)
6331 #ifdef QT_DEBUG_DRAW
6332 if (qt_show_painter_debug_output)
6333 printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6334 p.x(), p.y(), qPrintable(_ti.text()));
6343 qt_painter_thread_test(device->devType(),
6345 QFontDatabase::supportsThreadedFontRendering());
6348 QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6350 if (!extended && state->bgMode == Qt::OpaqueMode) {
6351 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6352 q->fillRect(rect, state->bgBrush);
6355 if (q->pen().style() == Qt::NoPen)
6358 const QPainter::RenderHints oldRenderHints = state->renderHints;
6359 if (!state->renderHints & QPainter::Antialiasing && state->matrix.type() >= QTransform::TxScale) {
6360 // draw antialias decoration (underline/overline/strikeout) with
6364 const QTransform &m = state->matrix;
6365 if (state->matrix.type() < QTransform::TxShear) {
6366 bool isPlain90DegreeRotation =
6367 (qFuzzyIsNull(m.m11())
6368 && qFuzzyIsNull(m.m12() - qreal(1))
6369 && qFuzzyIsNull(m.m21() + qreal(1))
6370 && qFuzzyIsNull(m.m22())
6373 (qFuzzyIsNull(m.m11() + qreal(1))
6374 && qFuzzyIsNull(m.m12())
6375 && qFuzzyIsNull(m.m21())
6376 && qFuzzyIsNull(m.m22() + qreal(1))
6379 (qFuzzyIsNull(m.m11())
6380 && qFuzzyIsNull(m.m12() + qreal(1))
6381 && qFuzzyIsNull(m.m21() - qreal(1))
6382 && qFuzzyIsNull(m.m22())
6385 aa = !isPlain90DegreeRotation;
6388 q->setRenderHint(QPainter::Antialiasing, true);
6394 if (!ti.glyphs.numGlyphs) {
6396 } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6397 QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6399 const QGlyphLayout &glyphs = ti.glyphs;
6400 int which = glyphs.glyphs[0] >> 24;
6405 bool rtl = ti.flags & QTextItem::RightToLeft;
6407 x += ti.width.toReal();
6411 for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6412 const int e = glyphs.glyphs[end] >> 24;
6417 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6419 // set the high byte to zero and calc the width
6420 for (i = start; i < end; ++i) {
6421 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6422 ti2.width += ti.glyphs.effectiveAdvance(i);
6426 x -= ti2.width.toReal();
6428 engine->drawTextItem(QPointF(x, y), ti2);
6431 x += ti2.width.toReal();
6433 // reset the high byte for all glyphs and advance to the next sub-string
6434 const int hi = which << 24;
6435 for (i = start; i < end; ++i) {
6436 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6444 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6446 // set the high byte to zero and calc the width
6447 for (i = start; i < end; ++i) {
6448 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6449 ti2.width += ti.glyphs.effectiveAdvance(i);
6453 x -= ti2.width.toReal();
6456 extended->drawTextItem(QPointF(x, y), ti2);
6458 engine->drawTextItem(QPointF(x,y), ti2);
6460 // reset the high byte for all glyphs
6461 const int hi = which << 24;
6462 for (i = start; i < end; ++i)
6463 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6467 extended->drawTextItem(p, ti);
6469 engine->drawTextItem(p, ti);
6471 drawTextItemDecoration(q, p, ti.fontEngine, textEngine, ti.underlineStyle,
6472 ti.flags, ti.width.toReal(), ti.charFormat);
6474 if (state->renderHints != oldRenderHints) {
6475 state->renderHints = oldRenderHints;
6477 extended->renderHintsChanged();
6479 state->dirtyFlags |= QPaintEngine::DirtyHints;
6484 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6486 Returns the bounding rectangle of the \a text as it will appear
6487 when drawn inside the given \a rectangle with the specified \a
6488 flags using the currently set font(); i.e the function tells you
6489 where the drawText() function will draw when given the same
6492 If the \a text does not fit within the given \a rectangle using
6493 the specified \a flags, the function returns the required
6496 The \a flags argument is a bitwise OR of the following flags:
6500 \li Qt::AlignHCenter
6503 \li Qt::AlignVCenter
6505 \li Qt::TextSingleLine
6506 \li Qt::TextExpandTabs
6507 \li Qt::TextShowMnemonic
6508 \li Qt::TextWordWrap
6509 \li Qt::TextIncludeTrailingSpaces
6511 If several of the horizontal or several of the vertical alignment
6512 flags are set, the resulting alignment is undefined.
6514 \sa drawText(), Qt::Alignment, Qt::TextFlag
6518 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6519 const QString &text)
6523 Returns the bounding rectangle of the \a text as it will appear
6524 when drawn inside the given \a rectangle with the specified \a
6525 flags using the currently set font().
6529 \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6530 const QString &text);
6534 Returns the bounding rectangle of the given \a text as it will
6535 appear when drawn inside the rectangle beginning at the point
6536 (\a{x}, \a{y}) with width \a w and height \a h.
6538 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6541 return QRect(rect.x(),rect.y(), 0,0);
6543 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6549 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6552 return QRectF(rect.x(),rect.y(), 0,0);
6554 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6559 \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6560 const QString &text, const QTextOption &option)
6564 Instead of specifying flags as a bitwise OR of the
6565 Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6566 an \a option argument. The QTextOption class provides a
6567 description of general rich text properties.
6571 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6575 if (!d->engine || text.length() == 0)
6576 return QRectF(r.x(),r.y(), 0,0);
6579 qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6584 \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6586 Draws a tiled \a pixmap, inside the given \a rectangle with its
6587 origin at the given \a position.
6589 Calling drawTiledPixmap() is similar to calling drawPixmap()
6590 several times to fill (tile) an area with a pixmap, but is
6591 potentially much more efficient depending on the underlying window
6596 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6598 #ifdef QT_DEBUG_DRAW
6599 if (qt_show_painter_debug_output)
6600 printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6601 r.x(), r.y(), r.width(), r.height(),
6602 pixmap.width(), pixmap.height(),
6607 if (!d->engine || pixmap.isNull() || r.isEmpty())
6611 qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6614 qreal sw = pixmap.width();
6615 qreal sh = pixmap.height();
6619 sx = qRound(sw) - qRound(-sx) % qRound(sw);
6621 sx = qRound(sx) % qRound(sw);
6623 sy = qRound(sh) - -qRound(sy) % qRound(sh);
6625 sy = qRound(sy) % qRound(sh);
6629 d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6633 if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6634 fillRect(r, d->state->bgBrush);
6636 d->updateState(d->state);
6637 if ((d->state->matrix.type() > QTransform::TxTranslate
6638 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6639 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6642 setBackgroundMode(Qt::TransparentMode);
6643 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6644 setBrush(QBrush(d->state->pen.color(), pixmap));
6647 // If there is no rotation involved we have to make sure we use the
6648 // antialiased and not the aliased coordinate system by rounding the coordinates.
6649 if (d->state->matrix.type() <= QTransform::TxScale) {
6650 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6652 if (d->state->matrix.type() <= QTransform::TxTranslate) {
6657 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6658 drawRect(QRectF(p, r.size()));
6660 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6669 if (d->state->matrix.type() == QTransform::TxTranslate
6670 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6671 x += d->state->matrix.dx();
6672 y += d->state->matrix.dy();
6675 d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6679 \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6680 const QPoint &position = QPoint())
6683 Draws a tiled \a pixmap, inside the given \a rectangle with its
6684 origin at the given \a position.
6688 \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6689 QPixmap &pixmap, int sx, int sy);
6692 Draws a tiled \a pixmap in the specified rectangle.
6694 (\a{x}, \a{y}) specifies the top-left point in the paint device
6695 that is to be drawn onto; with the given \a width and \a
6696 height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6697 pixmap that is to be drawn; this defaults to (0, 0).
6700 #ifndef QT_NO_PICTURE
6703 \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6705 Replays the given \a picture at the given \a point.
6707 The QPicture class is a paint device that records and replays
6708 QPainter commands. A picture serializes the painter commands to an
6709 IO device in a platform-independent format. Everything that can be
6710 painted on a widget or pixmap can also be stored in a picture.
6712 This function does exactly the same as QPicture::play() when
6713 called with \a point = QPoint(0, 0).
6718 \snippet code/src_gui_painting_qpainter.cpp 18
6721 \sa QPicture::play()
6724 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6732 d->updateState(d->state);
6736 const_cast<QPicture *>(&picture)->play(this);
6741 \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6744 Replays the given \a picture at the given \a point.
6748 \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6751 Draws the given \a picture at point (\a x, \a y).
6754 #endif // QT_NO_PICTURE
6757 \fn void QPainter::eraseRect(const QRectF &rectangle)
6759 Erases the area inside the given \a rectangle. Equivalent to
6761 \snippet code/src_gui_painting_qpainter.cpp 19
6765 void QPainter::eraseRect(const QRectF &r)
6769 fillRect(r, d->state->bgBrush);
6772 static inline bool needsResolving(const QBrush &brush)
6774 Qt::BrushStyle s = brush.style();
6775 return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
6776 s == Qt::ConicalGradientPattern) &&
6777 brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
6781 \fn void QPainter::eraseRect(const QRect &rectangle)
6784 Erases the area inside the given \a rectangle.
6788 \fn void QPainter::eraseRect(int x, int y, int width, int height)
6791 Erases the area inside the rectangle beginning at (\a x, \a y)
6792 with the given \a width and \a height.
6797 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
6800 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6801 width and \a height, using the brush \a style specified.
6807 \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
6810 Fills the given \a rectangle with the brush \a style specified.
6816 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
6819 Fills the given \a rectangle with the brush \a style specified.
6825 \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
6827 Fills the given \a rectangle with the \a brush specified.
6829 Alternatively, you can specify a QColor instead of a QBrush; the
6830 QBrush constructor (taking a QColor argument) will automatically
6831 create a solid pattern brush.
6835 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
6843 const QGradient *g = brush.gradient();
6844 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6845 d->extended->fillRect(r, brush);
6850 QPen oldPen = pen();
6851 QBrush oldBrush = this->brush();
6853 if (brush.style() == Qt::SolidPattern) {
6854 d->colorBrush.setStyle(Qt::SolidPattern);
6855 d->colorBrush.setColor(brush.color());
6856 setBrush(d->colorBrush);
6867 \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
6870 Fills the given \a rectangle with the specified \a brush.
6873 void QPainter::fillRect(const QRect &r, const QBrush &brush)
6881 const QGradient *g = brush.gradient();
6882 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6883 d->extended->fillRect(r, brush);
6888 QPen oldPen = pen();
6889 QBrush oldBrush = this->brush();
6891 if (brush.style() == Qt::SolidPattern) {
6892 d->colorBrush.setStyle(Qt::SolidPattern);
6893 d->colorBrush.setColor(brush.color());
6894 setBrush(d->colorBrush);
6907 \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
6910 Fills the given \a rectangle with the \a color specified.
6914 void QPainter::fillRect(const QRect &r, const QColor &color)
6922 d->extended->fillRect(r, color);
6926 fillRect(r, QBrush(color));
6931 \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
6934 Fills the given \a rectangle with the \a color specified.
6938 void QPainter::fillRect(const QRectF &r, const QColor &color)
6946 d->extended->fillRect(r, color);
6950 fillRect(r, QBrush(color));
6954 \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
6958 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6959 width and \a height, using the given \a brush.
6963 \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
6967 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6968 width and \a height, using the given \a color.
6974 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
6978 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6979 width and \a height, using the given \a color.
6985 \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
6989 Fills the given \a rectangle with the specified \a color.
6995 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
6999 Fills the given \a rectangle with the specified \a color.
7005 Sets the given render \a hint on the painter if \a on is true;
7006 otherwise clears the render hint.
7008 \sa setRenderHints(), renderHints(), {QPainter#Rendering
7009 Quality}{Rendering Quality}
7011 void QPainter::setRenderHint(RenderHint hint, bool on)
7013 #ifdef QT_DEBUG_DRAW
7014 if (qt_show_painter_debug_output)
7015 printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
7019 static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
7020 if (hint == QPainter::Antialiasing && antialiasingDisabled)
7024 setRenderHints(hint, on);
7030 Sets the given render \a hints on the painter if \a on is true;
7031 otherwise clears the render hints.
7033 \sa setRenderHint(), renderHints(), {QPainter#Rendering
7034 Quality}{Rendering Quality}
7037 void QPainter::setRenderHints(RenderHints hints, bool on)
7042 qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7047 d->state->renderHints |= hints;
7049 d->state->renderHints &= ~hints;
7052 d->extended->renderHintsChanged();
7054 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7058 Returns a flag that specifies the rendering hints that are set for
7061 \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7063 QPainter::RenderHints QPainter::renderHints() const
7065 Q_D(const QPainter);
7070 return d->state->renderHints;
7074 \fn bool QPainter::testRenderHint(RenderHint hint) const
7077 Returns true if \a hint is set; otherwise returns false.
7079 \sa renderHints(), setRenderHint()
7083 Returns true if view transformation is enabled; otherwise returns
7086 \sa setViewTransformEnabled(), worldTransform()
7089 bool QPainter::viewTransformEnabled() const
7091 Q_D(const QPainter);
7093 qWarning("QPainter::viewTransformEnabled: Painter not active");
7096 return d->state->VxF;
7100 \fn void QPainter::setWindow(const QRect &rectangle)
7102 Sets the painter's window to the given \a rectangle, and enables
7103 view transformations.
7105 The window rectangle is part of the view transformation. The
7106 window specifies the logical coordinate system. Its sister, the
7107 viewport(), specifies the device coordinate system.
7109 The default window rectangle is the same as the device's
7112 \sa window(), viewTransformEnabled(), {Coordinate
7113 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7117 \fn void QPainter::setWindow(int x, int y, int width, int height)
7120 Sets the painter's window to the rectangle beginning at (\a x, \a
7121 y) and the given \a width and \a height.
7124 void QPainter::setWindow(const QRect &r)
7126 #ifdef QT_DEBUG_DRAW
7127 if (qt_show_painter_debug_output)
7128 printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7134 qWarning("QPainter::setWindow: Painter not active");
7138 d->state->wx = r.x();
7139 d->state->wy = r.y();
7140 d->state->ww = r.width();
7141 d->state->wh = r.height();
7143 d->state->VxF = true;
7148 Returns the window rectangle.
7150 \sa setWindow(), setViewTransformEnabled()
7153 QRect QPainter::window() const
7155 Q_D(const QPainter);
7157 qWarning("QPainter::window: Painter not active");
7160 return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7164 \fn void QPainter::setViewport(const QRect &rectangle)
7166 Sets the painter's viewport rectangle to the given \a rectangle,
7167 and enables view transformations.
7169 The viewport rectangle is part of the view transformation. The
7170 viewport specifies the device coordinate system. Its sister, the
7171 window(), specifies the logical coordinate system.
7173 The default viewport rectangle is the same as the device's
7176 \sa viewport(), viewTransformEnabled(), {Coordinate
7177 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7181 \fn void QPainter::setViewport(int x, int y, int width, int height)
7184 Sets the painter's viewport rectangle to be the rectangle
7185 beginning at (\a x, \a y) with the given \a width and \a height.
7188 void QPainter::setViewport(const QRect &r)
7190 #ifdef QT_DEBUG_DRAW
7191 if (qt_show_painter_debug_output)
7192 printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7198 qWarning("QPainter::setViewport: Painter not active");
7202 d->state->vx = r.x();
7203 d->state->vy = r.y();
7204 d->state->vw = r.width();
7205 d->state->vh = r.height();
7207 d->state->VxF = true;
7212 Returns the viewport rectangle.
7214 \sa setViewport(), setViewTransformEnabled()
7217 QRect QPainter::viewport() const
7219 Q_D(const QPainter);
7221 qWarning("QPainter::viewport: Painter not active");
7224 return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7228 Enables view transformations if \a enable is true, or disables
7229 view transformations if \a enable is false.
7231 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7232 Conversion}{Window-Viewport Conversion}
7235 void QPainter::setViewTransformEnabled(bool enable)
7237 #ifdef QT_DEBUG_DRAW
7238 if (qt_show_painter_debug_output)
7239 printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7245 qWarning("QPainter::setViewTransformEnabled: Painter not active");
7249 if (enable == d->state->VxF)
7252 d->state->VxF = enable;
7261 Please use QWidget::render() instead.
7263 Redirects all paint commands for the given paint \a device, to the
7264 \a replacement device. The optional point \a offset defines an
7265 offset within the source device.
7267 The redirection will not be effective until the begin() function
7268 has been called; make sure to call end() for the given \a
7269 device's painter (if any) before redirecting. Call
7270 restoreRedirected() to restore the previous redirection.
7272 \warning Making use of redirections in the QPainter API implies
7273 that QPainter::begin() and QPaintDevice destructors need to hold
7274 a mutex for a short period. This can impact performance. Use of
7275 QWidget::render is strongly encouraged.
7277 \sa redirected(), restoreRedirected()
7279 void QPainter::setRedirected(const QPaintDevice *device,
7280 QPaintDevice *replacement,
7281 const QPoint &offset)
7283 Q_ASSERT(device != 0);
7285 Q_UNUSED(replacement)
7287 qWarning("QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7295 Using QWidget::render() obsoletes the use of this function.
7297 Restores the previous redirection for the given \a device after a
7298 call to setRedirected().
7300 \warning Making use of redirections in the QPainter API implies
7301 that QPainter::begin() and QPaintDevice destructors need to hold
7302 a mutex for a short period. This can impact performance. Use of
7303 QWidget::render is strongly encouraged.
7307 void QPainter::restoreRedirected(const QPaintDevice *device)
7310 qWarning("QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7318 Using QWidget::render() obsoletes the use of this function.
7320 Returns the replacement for given \a device. The optional out
7321 parameter \a offset returns the offset within the replaced device.
7323 \warning Making use of redirections in the QPainter API implies
7324 that QPainter::begin() and QPaintDevice destructors need to hold
7325 a mutex for a short period. This can impact performance. Use of
7326 QWidget::render is strongly encouraged.
7328 \sa setRedirected(), restoreRedirected()
7330 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7337 void qt_format_text(const QFont &fnt, const QRectF &_r,
7338 int tf, const QString& str, QRectF *brect,
7339 int tabstops, int *ta, int tabarraylen,
7342 qt_format_text(fnt, _r,
7344 tabstops, ta, tabarraylen,
7347 void qt_format_text(const QFont &fnt, const QRectF &_r,
7348 int tf, const QTextOption *option, const QString& str, QRectF *brect,
7349 int tabstops, int *ta, int tabarraylen,
7353 Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
7356 tf |= option->alignment();
7357 if (option->wrapMode() != QTextOption::NoWrap)
7358 tf |= Qt::TextWordWrap;
7360 if (option->flags() & QTextOption::IncludeTrailingSpaces)
7361 tf |= Qt::TextIncludeTrailingSpaces;
7363 if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
7364 tf |= Qt::TextExpandTabs;
7367 // we need to copy r here to protect against the case (&r == brect).
7370 bool dontclip = (tf & Qt::TextDontClip);
7371 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
7372 bool singleline = (tf & Qt::TextSingleLine);
7373 bool showmnemonic = (tf & Qt::TextShowMnemonic);
7374 bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
7376 Qt::LayoutDirection layout_direction;
7377 if (tf & Qt::TextForceLeftToRight)
7378 layout_direction = Qt::LeftToRight;
7379 else if (tf & Qt::TextForceRightToLeft)
7380 layout_direction = Qt::RightToLeft;
7382 layout_direction = option->textDirection();
7384 layout_direction = painter->layoutDirection();
7386 layout_direction = Qt::LeftToRight;
7388 tf = QGuiApplicationPrivate::visualAlignment(layout_direction, QFlag(tf));
7390 bool isRightToLeft = layout_direction == Qt::RightToLeft;
7391 bool expandtabs = ((tf & Qt::TextExpandTabs) &&
7392 (((tf & Qt::AlignLeft) && !isRightToLeft) ||
7393 ((tf & Qt::AlignRight) && isRightToLeft)));
7396 tf |= Qt::TextDontPrint;
7398 uint maxUnderlines = 0;
7399 int numUnderlines = 0;
7400 QVarLengthArray<int, 32> underlinePositions(1);
7402 QFontMetricsF fm(fnt);
7405 start_lengthVariant:
7406 bool hasMoreLengthVariants = false;
7407 // compatible behaviour to the old implementation. Replace
7409 int old_offset = offset;
7410 for (; offset < text.length(); offset++) {
7411 QChar chr = text.at(offset);
7412 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
7413 text[offset] = QLatin1Char(' ');
7414 } else if (chr == QLatin1Char('\n')) {
7415 text[offset] = QChar::LineSeparator;
7416 } else if (chr == QLatin1Char('&')) {
7418 } else if (chr == QLatin1Char('\t')) {
7420 text[offset] = QLatin1Char(' ');
7421 } else if (!tabarraylen && !tabstops) {
7422 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
7424 } else if (chr == QChar(ushort(0x9c))) {
7425 // string with multiple length variants
7426 hasMoreLengthVariants = true;
7431 int length = offset - old_offset;
7432 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
7433 underlinePositions.resize(maxUnderlines + 1);
7435 QChar *cout = text.data() + old_offset;
7439 if (*cin == QLatin1Char('&')) {
7445 if (*cin != QLatin1Char('&') && !hidemnmemonic)
7446 underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
7455 // no need to do extra work for underlines if we don't paint
7456 if (tf & Qt::TextDontPrint)
7459 underlinePositions[numUnderlines] = -1;
7463 QString finalText = text.mid(old_offset, length);
7464 QStackTextEngine engine(finalText, fnt);
7466 engine.option = *option;
7469 if (engine.option.tabStop() < 0 && tabstops > 0)
7470 engine.option.setTabStop(tabstops);
7472 if (engine.option.tabs().isEmpty() && ta) {
7474 for (int i = 0; i < tabarraylen; i++)
7475 tabs.append(qreal(ta[i]));
7476 engine.option.setTabArray(tabs);
7479 engine.option.setTextDirection(layout_direction);
7480 if (tf & Qt::AlignJustify)
7481 engine.option.setAlignment(Qt::AlignJustify);
7483 engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
7485 if (!option && (tf & Qt::TextWrapAnywhere))
7486 engine.option.setWrapMode(QTextOption::WrapAnywhere);
7488 if (tf & Qt::TextJustificationForced)
7489 engine.forceJustification = true;
7490 QTextLayout textLayout(&engine);
7491 textLayout.setCacheEnabled(true);
7492 textLayout.engine()->underlinePositions = underlinePositions.data();
7494 if (finalText.isEmpty()) {
7495 height = fm.height();
7497 tf |= Qt::TextDontPrint;
7499 qreal lineWidth = 0x01000000;
7500 if (wordwrap || (tf & Qt::TextJustificationForced))
7501 lineWidth = qMax<qreal>(0, r.width());
7503 tf |= Qt::TextIncludeTrailingSpaces;
7504 textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
7505 textLayout.beginLayout();
7507 qreal leading = fm.leading();
7511 QTextLine l = textLayout.createLine();
7515 l.setLineWidth(lineWidth);
7517 l.setPosition(QPointF(0., height));
7518 height += l.height();
7519 width = qMax(width, l.naturalTextWidth());
7520 if (!dontclip && !brect && height >= r.height())
7523 textLayout.endLayout();
7528 if (tf & Qt::AlignBottom) {
7529 yoff = r.height() - height;
7530 } else if (tf & Qt::AlignVCenter) {
7531 yoff = (r.height() - height)/2;
7533 QTransform::TransformationType type = painter->transform().type();
7534 if (type <= QTransform::TxScale) {
7535 // do the rounding manually to work around inconsistencies
7536 // in the paint engines when drawing on floating point offsets
7537 const qreal scale = painter->transform().m22();
7539 yoff = -qRound(-yoff * scale) / scale;
7543 if (tf & Qt::AlignRight) {
7544 xoff = r.width() - width;
7545 } else if (tf & Qt::AlignHCenter) {
7546 xoff = (r.width() - width)/2;
7548 QTransform::TransformationType type = painter->transform().type();
7549 if (type <= QTransform::TxScale) {
7550 // do the rounding manually to work around inconsistencies
7551 // in the paint engines when drawing on floating point offsets
7552 const qreal scale = painter->transform().m11();
7554 xoff = qRound(xoff * scale) / scale;
7558 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
7560 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
7562 goto start_lengthVariant;
7567 if (!(tf & Qt::TextDontPrint)) {
7568 bool restore = false;
7569 if (!dontclip && !r.contains(bounds)) {
7572 painter->setClipRect(r, Qt::IntersectClip);
7575 for (int i = 0; i < textLayout.lineCount(); i++) {
7576 QTextLine line = textLayout.lineAt(i);
7577 QTextEngine *eng = textLayout.engine();
7578 eng->enableDelayDecorations();
7580 qreal advance = line.horizontalAdvance();
7582 if (tf & Qt::AlignRight) {
7583 xoff = r.width() - advance -
7584 eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
7586 else if (tf & Qt::AlignHCenter)
7587 xoff = (r.width() - advance) / 2;
7589 line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
7590 eng->drawDecorations(painter);
7600 Sets the layout direction used by the painter when drawing text,
7601 to the specified \a direction.
7603 The default is Qt::LayoutDirectionAuto, which will implicitly determine the
7604 direction from the text drawn.
7606 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
7608 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
7612 d->state->layoutDirection = direction;
7616 Returns the layout direction used by the painter when drawing text.
7618 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
7620 Qt::LayoutDirection QPainter::layoutDirection() const
7622 Q_D(const QPainter);
7623 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
7626 QPainterState::QPainterState(const QPainterState *s)
7627 : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
7628 pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
7629 clipRegion(s->clipRegion), clipPath(s->clipPath),
7630 clipOperation(s->clipOperation),
7631 renderHints(s->renderHints), clipInfo(s->clipInfo),
7632 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
7633 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
7634 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
7635 opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
7636 clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
7637 layoutDirection(s->layoutDirection),
7638 composition_mode(s->composition_mode),
7639 emulationSpecifier(s->emulationSpecifier), changeFlags(0)
7641 dirtyFlags = s->dirtyFlags;
7644 QPainterState::QPainterState()
7645 : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
7647 wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
7648 opacity(1), WxF(false), VxF(false), clipEnabled(true),
7649 bgMode(Qt::TransparentMode), painter(0),
7650 layoutDirection(QGuiApplication::layoutDirection()),
7651 composition_mode(QPainter::CompositionMode_SourceOver),
7652 emulationSpecifier(0), changeFlags(0)
7657 QPainterState::~QPainterState()
7661 void QPainterState::init(QPainter *p) {
7662 bgBrush = Qt::white;
7663 bgMode = Qt::TransparentMode;
7667 wx = wy = ww = wh = 0;
7668 vx = vy = vw = vh = 0;
7671 brushOrigin = QPointF(0, 0);
7673 font = deviceFont = QFont();
7674 clipRegion = QRegion();
7675 clipPath = QPainterPath();
7676 clipOperation = Qt::NoClip;
7678 worldMatrix.reset();
7680 layoutDirection = QGuiApplication::layoutDirection();
7681 composition_mode = QPainter::CompositionMode_SourceOver;
7682 emulationSpecifier = 0;
7690 \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
7691 Qt::ImageConversionFlags flags)
7693 Draws the rectangular portion \a source of the given \a image
7694 into the \a target rectangle in the paint device.
7696 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7698 If the image needs to be modified to fit in a lower-resolution
7699 result (e.g. converting from 32-bit to 8-bit), use the \a flags to
7700 specify how you would prefer this to happen.
7705 \snippet code/src_gui_painting_qpainter.cpp 20
7712 \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
7713 Qt::ImageConversionFlags flags)
7716 Draws the rectangular portion \a source of the given \a image
7717 into the \a target rectangle in the paint device.
7719 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7723 \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
7727 Draws the given \a image at the given \a point.
7731 \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
7735 Draws the given \a image at the given \a point.
7739 \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
7740 Qt::ImageConversionFlags flags = 0)
7744 Draws the rectangular portion \a source of the given \a image with
7745 its origin at the given \a point.
7749 \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
7750 Qt::ImageConversionFlags flags = 0)
7753 Draws the rectangular portion \a source of the given \a image with
7754 its origin at the given \a point.
7758 \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
7762 Draws the given \a image into the given \a rectangle.
7764 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7768 \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
7772 Draws the given \a image into the given \a rectangle.
7774 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7778 \fn void QPainter::drawImage(int x, int y, const QImage &image,
7779 int sx, int sy, int sw, int sh,
7780 Qt::ImageConversionFlags flags)
7783 Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
7786 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
7787 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
7788 image that is to be drawn. The default is (0, 0).
7790 (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
7791 The default, (0, 0) (and negative) means all the way to the
7792 bottom-right of the image.
7796 \class QPaintEngineState
7800 \brief The QPaintEngineState class provides information about the
7801 active paint engine's current state.
7804 QPaintEngineState records which properties that have changed since
7805 the last time the paint engine was updated, as well as their
7808 Which properties that have changed can at any time be retrieved
7809 using the state() function. This function returns an instance of
7810 the QPaintEngine::DirtyFlags type which stores an OR combination
7811 of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
7812 enum defines whether a property has changed since the last update
7815 If a property is marked with a dirty flag, its current value can
7816 be retrieved using the corresponding get function:
7821 \header \li Property Flag \li Current Property Value
7822 \row \li QPaintEngine::DirtyBackground \li backgroundBrush()
7823 \row \li QPaintEngine::DirtyBackgroundMode \li backgroundMode()
7824 \row \li QPaintEngine::DirtyBrush \li brush()
7825 \row \li QPaintEngine::DirtyBrushOrigin \li brushOrigin()
7826 \row \li QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
7828 \row \li QPaintEngine::DirtyClipPath \li clipPath()
7829 \row \li QPaintEngine::DirtyClipRegion \li clipRegion()
7830 \row \li QPaintEngine::DirtyCompositionMode \li compositionMode()
7831 \row \li QPaintEngine::DirtyFont \li font()
7832 \row \li QPaintEngine::DirtyTransform \li transform()
7833 \row \li QPaintEngine::DirtyClipEnabled \li isClipEnabled()
7834 \row \li QPaintEngine::DirtyPen \li pen()
7835 \row \li QPaintEngine::DirtyHints \li renderHints()
7838 The QPaintEngineState class also provide the painter() function
7839 which returns a pointer to the painter that is currently updating
7842 An instance of this class, representing the current state of the
7843 active paint engine, is passed as argument to the
7844 QPaintEngine::updateState() function. The only situation in which
7845 you will have to use this class directly is when implementing your
7853 \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
7855 Returns a combination of flags identifying the set of properties
7856 that need to be updated when updating the paint engine's state
7857 (i.e. during a call to the QPaintEngine::updateState() function).
7859 \sa QPaintEngine::updateState()
7864 Returns the pen in the current paint engine state.
7866 This variable should only be used when the state() returns a
7867 combination which includes the QPaintEngine::DirtyPen flag.
7869 \sa state(), QPaintEngine::updateState()
7872 QPen QPaintEngineState::pen() const
7874 return static_cast<const QPainterState *>(this)->pen;
7878 Returns the brush in the current paint engine state.
7880 This variable should only be used when the state() returns a
7881 combination which includes the QPaintEngine::DirtyBrush flag.
7883 \sa state(), QPaintEngine::updateState()
7886 QBrush QPaintEngineState::brush() const
7888 return static_cast<const QPainterState *>(this)->brush;
7892 Returns the brush origin in the current paint engine state.
7894 This variable should only be used when the state() returns a
7895 combination which includes the QPaintEngine::DirtyBrushOrigin flag.
7897 \sa state(), QPaintEngine::updateState()
7900 QPointF QPaintEngineState::brushOrigin() const
7902 return static_cast<const QPainterState *>(this)->brushOrigin;
7906 Returns the background brush in the current paint engine state.
7908 This variable should only be used when the state() returns a
7909 combination which includes the QPaintEngine::DirtyBackground flag.
7911 \sa state(), QPaintEngine::updateState()
7914 QBrush QPaintEngineState::backgroundBrush() const
7916 return static_cast<const QPainterState *>(this)->bgBrush;
7920 Returns the background mode in the current paint engine
7923 This variable should only be used when the state() returns a
7924 combination which includes the QPaintEngine::DirtyBackgroundMode flag.
7926 \sa state(), QPaintEngine::updateState()
7929 Qt::BGMode QPaintEngineState::backgroundMode() const
7931 return static_cast<const QPainterState *>(this)->bgMode;
7935 Returns the font in the current paint engine
7938 This variable should only be used when the state() returns a
7939 combination which includes the QPaintEngine::DirtyFont flag.
7941 \sa state(), QPaintEngine::updateState()
7944 QFont QPaintEngineState::font() const
7946 return static_cast<const QPainterState *>(this)->font;
7953 Returns the matrix in the current paint engine
7956 \note It is advisable to use transform() instead of this function to
7957 preserve the properties of perspective transformations.
7959 This variable should only be used when the state() returns a
7960 combination which includes the QPaintEngine::DirtyTransform flag.
7962 \sa state(), QPaintEngine::updateState()
7965 QMatrix QPaintEngineState::matrix() const
7967 const QPainterState *st = static_cast<const QPainterState *>(this);
7969 return st->matrix.toAffine();
7975 Returns the matrix in the current paint engine state.
7977 This variable should only be used when the state() returns a
7978 combination which includes the QPaintEngine::DirtyTransform flag.
7980 \sa state(), QPaintEngine::updateState()
7984 QTransform QPaintEngineState::transform() const
7986 const QPainterState *st = static_cast<const QPainterState *>(this);
7993 Returns the clip operation in the current paint engine
7996 This variable should only be used when the state() returns a
7997 combination which includes either the QPaintEngine::DirtyClipPath
7998 or the QPaintEngine::DirtyClipRegion flag.
8000 \sa state(), QPaintEngine::updateState()
8003 Qt::ClipOperation QPaintEngineState::clipOperation() const
8005 return static_cast<const QPainterState *>(this)->clipOperation;
8011 Returns whether the coordinate of the fill have been specified
8012 as bounded by the current rendering operation and have to be
8013 resolved (about the currently rendered primitive).
8015 bool QPaintEngineState::brushNeedsResolving() const
8017 const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
8018 return needsResolving(brush);
8025 Returns whether the coordinate of the stroke have been specified
8026 as bounded by the current rendering operation and have to be
8027 resolved (about the currently rendered primitive).
8029 bool QPaintEngineState::penNeedsResolving() const
8031 const QPen &pen = static_cast<const QPainterState *>(this)->pen;
8032 return needsResolving(pen.brush());
8036 Returns the clip region in the current paint engine state.
8038 This variable should only be used when the state() returns a
8039 combination which includes the QPaintEngine::DirtyClipRegion flag.
8041 \sa state(), QPaintEngine::updateState()
8044 QRegion QPaintEngineState::clipRegion() const
8046 return static_cast<const QPainterState *>(this)->clipRegion;
8050 Returns the clip path in the current paint engine state.
8052 This variable should only be used when the state() returns a
8053 combination which includes the QPaintEngine::DirtyClipPath flag.
8055 \sa state(), QPaintEngine::updateState()
8058 QPainterPath QPaintEngineState::clipPath() const
8060 return static_cast<const QPainterState *>(this)->clipPath;
8064 Returns whether clipping is enabled or not in the current paint
8067 This variable should only be used when the state() returns a
8068 combination which includes the QPaintEngine::DirtyClipEnabled
8071 \sa state(), QPaintEngine::updateState()
8074 bool QPaintEngineState::isClipEnabled() const
8076 return static_cast<const QPainterState *>(this)->clipEnabled;
8080 Returns the render hints in the current paint engine state.
8082 This variable should only be used when the state() returns a
8083 combination which includes the QPaintEngine::DirtyHints
8086 \sa state(), QPaintEngine::updateState()
8089 QPainter::RenderHints QPaintEngineState::renderHints() const
8091 return static_cast<const QPainterState *>(this)->renderHints;
8095 Returns the composition mode in the current paint engine state.
8097 This variable should only be used when the state() returns a
8098 combination which includes the QPaintEngine::DirtyCompositionMode
8101 \sa state(), QPaintEngine::updateState()
8104 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8106 return static_cast<const QPainterState *>(this)->composition_mode;
8111 Returns a pointer to the painter currently updating the paint
8115 QPainter *QPaintEngineState::painter() const
8117 return static_cast<const QPainterState *>(this)->painter;
8124 Returns the opacity in the current paint engine state.
8127 qreal QPaintEngineState::opacity() const
8129 return static_cast<const QPainterState *>(this)->opacity;
8135 Sets the world transformation matrix.
8136 If \a combine is true, the specified \a transform is combined with
8137 the current matrix; otherwise it replaces the current matrix.
8139 \sa transform(), setWorldTransform()
8142 void QPainter::setTransform(const QTransform &transform, bool combine )
8144 setWorldTransform(transform, combine);
8148 Returns the world transformation matrix.
8150 \sa worldTransform()
8153 const QTransform & QPainter::transform() const
8155 return worldTransform();
8160 Returns the matrix that transforms from logical coordinates to
8161 device coordinates of the platform dependent paint device.
8163 This function is \e only needed when using platform painting
8164 commands on the platform dependent handle (Qt::HANDLE), and the
8165 platform does not do transformations nativly.
8167 The QPaintEngine::PaintEngineFeature enum can be queried to
8168 determine whether the platform performs the transformations or
8171 \sa worldTransform(), QPaintEngine::hasFeature(),
8174 const QTransform & QPainter::deviceTransform() const
8176 Q_D(const QPainter);
8178 qWarning("QPainter::deviceTransform: Painter not active");
8179 return d->fakeState()->transform;
8181 return d->state->matrix;
8186 Resets any transformations that were made using translate(),
8187 scale(), shear(), rotate(), setWorldTransform(), setViewport()
8190 \sa {Coordinate Transformations}
8193 void QPainter::resetTransform()
8196 #ifdef QT_DEBUG_DRAW
8197 if (qt_show_painter_debug_output)
8198 printf("QPainter::resetMatrix()\n");
8201 qWarning("QPainter::resetMatrix: Painter not active");
8205 d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins
8206 d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
8207 d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
8208 d->state->worldMatrix = QTransform();
8209 setMatrixEnabled(false);
8210 setViewTransformEnabled(false);
8212 d->extended->transformChanged();
8214 d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
8218 Sets the world transformation matrix.
8219 If \a combine is true, the specified \a matrix is combined with the current matrix;
8220 otherwise it replaces the current matrix.
8222 \sa transform(), setTransform()
8225 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
8230 qWarning("QPainter::setWorldTransform: Painter not active");
8235 d->state->worldMatrix = matrix * d->state->worldMatrix; // combines
8237 d->state->worldMatrix = matrix; // set new matrix
8239 d->state->WxF = true;
8244 Returns the world transformation matrix.
8247 const QTransform & QPainter::worldTransform() const
8249 Q_D(const QPainter);
8251 qWarning("QPainter::worldTransform: Painter not active");
8252 return d->fakeState()->transform;
8254 return d->state->worldMatrix;
8258 Returns the transformation matrix combining the current
8259 window/viewport and world transformation.
8261 \sa setWorldTransform(), setWindow(), setViewport()
8264 QTransform QPainter::combinedTransform() const
8266 Q_D(const QPainter);
8268 qWarning("QPainter::combinedTransform: Painter not active");
8269 return QTransform();
8271 return d->state->worldMatrix * d->viewTransform();
8277 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
8278 at multiple positions with different scale, rotation and opacity. \a
8279 fragments is an array of \a fragmentCount elements specifying the
8280 parameters used to draw each pixmap fragment. The \a hints
8281 parameter can be used to pass in drawing hints.
8283 This function is potentially faster than multiple calls to drawPixmap(),
8284 since the backend can optimize state changes.
8286 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
8289 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
8290 const QPixmap &pixmap, PixmapFragmentHints hints)
8294 if (!d->engine || pixmap.isNull())
8298 for (int i = 0; i < fragmentCount; ++i) {
8299 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8300 fragments[i].width, fragments[i].height);
8301 if (!(QRectF(pixmap.rect()).contains(sourceRect)))
8302 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
8306 if (d->engine->isExtended()) {
8307 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
8309 qreal oldOpacity = opacity();
8310 QTransform oldTransform = transform();
8312 for (int i = 0; i < fragmentCount; ++i) {
8313 QTransform transform = oldTransform;
8316 if (fragments[i].rotation == 0) {
8317 xOffset = fragments[i].x;
8318 yOffset = fragments[i].y;
8320 transform.translate(fragments[i].x, fragments[i].y);
8321 transform.rotate(fragments[i].rotation);
8323 setOpacity(oldOpacity * fragments[i].opacity);
8324 setTransform(transform);
8326 qreal w = fragments[i].scaleX * fragments[i].width;
8327 qreal h = fragments[i].scaleY * fragments[i].height;
8328 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8329 fragments[i].width, fragments[i].height);
8330 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
8333 setOpacity(oldOpacity);
8334 setTransform(oldTransform);
8340 \class QPainter::PixmapFragment
8343 \brief This class is used in conjunction with the
8344 QPainter::drawPixmapFragments() function to specify how a pixmap, or
8345 sub-rect of a pixmap, is drawn.
8347 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
8348 as a source rectangle within the pixmap passed into the
8349 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
8350 width and \a height are used to calculate the target rectangle that is
8351 drawn. \a x and \a y denotes the center of the target rectangle. The \a
8352 width and \a height in the target rectangle is scaled by the \a scaleX and
8353 \a scaleY values. The resulting target rectangle is then rotated \a
8354 rotation degrees around the \a x, \a y center point.
8356 \sa QPainter::drawPixmapFragments()
8362 This is a convenience function that returns a QPainter::PixmapFragment that is
8363 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
8364 rotation, \a opacity parameters.
8367 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
8368 qreal scaleX, qreal scaleY, qreal rotation,
8371 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
8372 sourceRect.height(), scaleX, scaleY, rotation, opacity};
8377 \variable QPainter::PixmapFragment::x
8378 \brief the x coordinate of center point in the target rectangle.
8382 \variable QPainter::PixmapFragment::y
8383 \brief the y coordinate of the center point in the target rectangle.
8387 \variable QPainter::PixmapFragment::sourceLeft
8388 \brief the left coordinate of the source rectangle.
8392 \variable QPainter::PixmapFragment::sourceTop
8393 \brief the top coordinate of the source rectangle.
8397 \variable QPainter::PixmapFragment::width
8399 \brief the width of the source rectangle and is used to calculate the width
8400 of the target rectangle.
8404 \variable QPainter::PixmapFragment::height
8406 \brief the height of the source rectangle and is used to calculate the
8407 height of the target rectangle.
8411 \variable QPainter::PixmapFragment::scaleX
8412 \brief the horizontal scale of the target rectangle.
8416 \variable QPainter::PixmapFragment::scaleY
8417 \brief the vertical scale of the target rectangle.
8421 \variable QPainter::PixmapFragment::rotation
8423 \brief the rotation of the target rectangle in degrees. The target
8424 rectangle is rotated after it has been scaled.
8428 \variable QPainter::PixmapFragment::opacity
8430 \brief the opacity of the target rectangle, where 0.0 is fully transparent
8431 and 1.0 is fully opaque.
8437 \enum QPainter::PixmapFragmentHint
8439 \value OpaqueHint Indicates that the pixmap fragments to be drawn are
8440 opaque. Opaque fragments are potentially faster to draw.
8442 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
8445 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
8447 p->draw_helper(path, operation);