1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
50 #include "qpaintdevice.h"
51 #include "qpaintengine.h"
53 #include "qpainter_p.h"
54 #include "qpainterpath.h"
56 #include "qpixmapcache.h"
58 #include "qtextlayout.h"
60 #include "qvarlengtharray.h"
61 #include "qstatictext.h"
62 #include "qglyphrun.h"
64 #include <private/qfontengine_p.h>
65 #include <private/qpaintengine_p.h>
66 #include <private/qemulationpaintengine_p.h>
67 #include <private/qpainterpath_p.h>
68 #include <private/qtextengine_p.h>
69 #include <private/qpaintengine_raster_p.h>
70 #include <private/qmath_p.h>
71 #include <private/qstatictext_p.h>
72 #include <private/qglyphrun_p.h>
73 #include <private/qhexstring_p.h>
74 #include <private/qguiapplication_p.h>
75 #include <private/qrawfont_p.h>
79 #define QGradient_StretchToDevice 0x10000000
80 #define QPaintEngine_OpaqueBackground 0x40000000
82 // #define QT_DEBUG_DRAW
84 bool qt_show_painter_debug_output = true;
87 extern QPixmap qt_pixmapForBrush(int style, bool invert);
89 void qt_format_text(const QFont &font,
90 const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
91 int tabstops, int* tabarray, int tabarraylen,
93 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
94 QTextCharFormat::UnderlineStyle underlineStyle,
95 QTextItem::RenderFlags flags, qreal width,
96 const QTextCharFormat &charFormat);
97 // Helper function to calculate left most position, width and flags for decoration drawing
98 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
99 const QFixedPoint *positions, int glyphCount,
100 QFontEngine *fontEngine, const QFont &font,
101 const QTextCharFormat &charFormat);
103 static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush)
105 switch (brush.style()) {
106 case Qt::LinearGradientPattern:
107 case Qt::RadialGradientPattern:
108 case Qt::ConicalGradientPattern:
109 return brush.gradient()->coordinateMode();
113 return QGradient::LogicalMode;
116 /* Returns true if the gradient requires stretch to device...*/
117 static inline bool check_gradient(const QBrush &brush)
119 return coordinateMode(brush) == QGradient::StretchToDeviceMode;
122 extern bool qHasPixmapTexture(const QBrush &);
124 static inline bool is_brush_transparent(const QBrush &brush) {
125 Qt::BrushStyle s = brush.style();
126 bool brushBitmap = qHasPixmapTexture(brush)
127 ? brush.texture().isQBitmap()
128 : (brush.textureImage().depth() == 1);
129 return ((s >= Qt::Dense1Pattern && s <= Qt::DiagCrossPattern)
130 || (s == Qt::TexturePattern && brushBitmap));
133 static inline bool is_pen_transparent(const QPen &pen) {
134 return pen.style() > Qt::SolidLine || is_brush_transparent(pen.brush());
137 /* Discards the emulation flags that are not relevant for line drawing
138 and returns the result
140 static inline uint line_emulation(uint emulation)
142 return emulation & (QPaintEngine::PrimitiveTransform
143 | QPaintEngine::AlphaBlend
144 | QPaintEngine::Antialiasing
145 | QPaintEngine::BrushStroke
146 | QPaintEngine::ConstantOpacity
147 | QGradient_StretchToDevice
148 | QPaintEngine::ObjectBoundingModeGradients
149 | QPaintEngine_OpaqueBackground);
153 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
156 case QInternal::Image:
157 case QInternal::Printer:
158 case QInternal::Picture:
159 // can be drawn onto these devices safely from any thread
163 if (!extraCondition && QThread::currentThread() != qApp->thread()) {
164 qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
173 void QPainterPrivate::checkEmulation()
176 if (extended->flags() & QPaintEngineEx::DoNotEmulate)
179 bool doEmulation = false;
180 if (state->bgMode == Qt::OpaqueMode)
183 const QGradient *bg = state->brush.gradient();
184 if (bg && bg->coordinateMode() > QGradient::LogicalMode)
187 const QGradient *pg = qpen_brush(state->pen).gradient();
188 if (pg && pg->coordinateMode() > QGradient::LogicalMode)
192 if (extended != emulationEngine) {
193 if (!emulationEngine)
194 emulationEngine = new QEmulationPaintEngine(extended);
195 extended = emulationEngine;
196 extended->setState(state);
198 } else if (emulationEngine == extended) {
199 extended = emulationEngine->real_engine;
204 QPainterPrivate::~QPainterPrivate()
206 delete emulationEngine;
207 for (int i=0; i<states.size(); ++i)
215 QTransform QPainterPrivate::viewTransform() const
218 qreal scaleW = qreal(state->vw)/qreal(state->ww);
219 qreal scaleH = qreal(state->vh)/qreal(state->wh);
220 return QTransform(scaleW, 0, 0, scaleH,
221 state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
229 Returns true if using a shared painter; otherwise false.
231 bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
236 QPainter *sp = pdev->sharedPainter();
240 // Save the current state of the shared painter and assign
241 // the current d_ptr to the shared painter's d_ptr.
243 if (!sp->d_ptr->d_ptrs) {
244 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
245 // redirections within the same paintEvent(), which should be enough
246 // in 99% of all cases). E.g: A renders B which renders C which renders D.
247 sp->d_ptr->d_ptrs_size = 4;
248 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
249 Q_CHECK_PTR(sp->d_ptr->d_ptrs);
250 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
251 // However, to support corner cases we grow the array dynamically if needed.
252 sp->d_ptr->d_ptrs_size <<= 1;
253 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
254 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
256 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
258 q->d_ptr.reset(sp->d_ptr.data());
260 Q_ASSERT(q->d_ptr->state);
262 // Now initialize the painter with correct widget properties.
265 pdev->redirected(&offset);
266 offset += q->d_ptr->engine->coordinateOffset();
268 // Update system rect.
269 q->d_ptr->state->ww = q->d_ptr->state->vw = pdev->width();
270 q->d_ptr->state->wh = q->d_ptr->state->vh = pdev->height();
273 if (q->d_ptr->state->WxF) {
274 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix;
275 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
276 q->d_ptr->state->worldMatrix = QTransform();
277 q->d_ptr->state->WxF = false;
279 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
281 q->d_ptr->updateMatrix();
283 QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
284 if (enginePrivate->currentClipDevice == pdev) {
285 enginePrivate->systemStateChanged();
289 // Update system transform and clip.
290 enginePrivate->currentClipDevice = pdev;
291 enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
295 void QPainterPrivate::detachPainterPrivate(QPainter *q)
297 Q_ASSERT(refcount > 1);
300 QPainterPrivate *original = d_ptrs[--refcount - 1];
302 inDestructor = false;
304 original->inDestructor = true;
305 } else if (!original) {
306 original = new QPainterPrivate(q);
309 d_ptrs[refcount - 1] = 0;
312 q->d_ptr.reset(original);
314 if (emulationEngine) {
315 extended = emulationEngine->real_engine;
316 delete emulationEngine;
322 void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op)
325 if (qt_show_painter_debug_output) {
326 printf("QPainter::drawHelper\n");
330 if (originalPath.isEmpty())
333 QPaintEngine::PaintEngineFeatures gradientStretch =
334 QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
335 | QPaintEngine::ObjectBoundingModeGradients);
337 const bool mustEmulateObjectBoundingModeGradients = extended
338 || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients)
339 && !engine->hasFeature(QPaintEngine::PatternTransform));
341 if (!(state->emulationSpecifier & ~gradientStretch)
342 && !mustEmulateObjectBoundingModeGradients) {
343 drawStretchedGradient(originalPath, op);
345 } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {
346 drawOpaqueBackground(originalPath, op);
352 qreal strokeOffsetX = 0, strokeOffsetY = 0;
354 QPainterPath path = originalPath * state->matrix;
355 QRectF pathBounds = path.boundingRect();
357 bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
359 qreal penWidth = state->pen.widthF();
364 // In case of complex xform
365 if (state->matrix.type() > QTransform::TxScale) {
366 QPainterPathStroker stroker;
367 stroker.setWidth(penWidth);
368 stroker.setJoinStyle(state->pen.joinStyle());
369 stroker.setCapStyle(state->pen.capStyle());
370 QPainterPath stroke = stroker.createStroke(originalPath);
371 strokeBounds = (stroke * state->matrix).boundingRect();
373 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);
374 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);
380 if (!strokeBounds.isEmpty()) {
381 absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
383 absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
384 .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
387 if (q->hasClipping()) {
388 bool hasPerspectiveTransform = false;
389 for (int i = 0; i < state->clipInfo.size(); ++i) {
390 const QPainterClipInfo &info = state->clipInfo.at(i);
391 if (info.matrix.type() == QTransform::TxProject) {
392 hasPerspectiveTransform = true;
396 // avoid mapping QRegions with perspective transforms
397 if (!hasPerspectiveTransform) {
398 // The trick with txinv and invMatrix is done in order to
399 // avoid transforming the clip to logical coordinates, and
400 // then back to device coordinates. This is a problem with
401 // QRegion/QRect based clips, since they use integer
402 // coordinates and converting to/from logical coordinates will
404 bool old_txinv = txinv;
405 QTransform old_invMatrix = invMatrix;
407 invMatrix = QTransform();
408 QPainterPath clipPath = q->clipPath();
409 QRectF r = clipPath.boundingRect().intersected(absPathRect);
410 absPathRect = r.toAlignedRect();
412 invMatrix = old_invMatrix;
416 // qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
417 // devMinX, devMinY, device->width(), device->height());
418 // qDebug() << " - matrix" << state->matrix;
419 // qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
420 // qDebug() << " - path.bounds" << path.boundingRect();
422 if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
425 QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
430 p.d_ptr->helper_device = helper_device;
432 p.setOpacity(state->opacity);
433 p.translate(-absPathRect.x(), -absPathRect.y());
434 p.setTransform(state->matrix, true);
435 p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
436 p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
437 p.setBackground(state->bgBrush);
438 p.setBackgroundMode(state->bgMode);
439 p.setBrushOrigin(state->brushOrigin);
441 p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);
442 p.setRenderHint(QPainter::SmoothPixmapTransform,
443 state->renderHints & QPainter::SmoothPixmapTransform);
445 p.drawPath(originalPath);
448 static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0;
449 if (do_fallback_overlay) {
450 QImage block(8, 8, QImage::Format_ARGB32_Premultiplied);
452 pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
453 pt.drawLine(0, 0, 8, 8);
456 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
458 p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
465 state->matrix = QTransform();
467 extended->transformChanged();
469 state->dirtyFlags |= QPaintEngine::DirtyTransform;
472 engine->drawImage(absPathRect,
474 QRectF(0, 0, absPathRect.width(), absPathRect.height()),
475 Qt::OrderedDither | Qt::OrderedAlphaDither);
479 void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op)
483 q->setBackgroundMode(Qt::TransparentMode);
485 if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
486 q->fillPath(path, state->bgBrush.color());
487 q->fillPath(path, state->brush);
490 if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
491 q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
492 q->strokePath(path, state->pen);
495 q->setBackgroundMode(Qt::OpaqueMode);
498 static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
500 Q_ASSERT(brush.style() >= Qt::LinearGradientPattern
501 && brush.style() <= Qt::ConicalGradientPattern);
503 QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
504 boundingRect.x(), boundingRect.y());
506 QGradient g = *brush.gradient();
507 g.setCoordinateMode(QGradient::LogicalMode);
510 b.setTransform(gradientToUser * b.transform());
514 void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op)
518 const qreal sw = helper_device->width();
519 const qreal sh = helper_device->height();
521 bool changedPen = false;
522 bool changedBrush = false;
523 bool needsFill = false;
525 const QPen pen = state->pen;
526 const QBrush brush = state->brush;
528 const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
529 const QGradient::CoordinateMode brushMode = coordinateMode(brush);
533 // Draw the xformed fill if the brush is a stretch gradient.
534 if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
535 if (brushMode == QGradient::StretchToDeviceMode) {
536 q->setPen(Qt::NoPen);
537 changedPen = pen.style() != Qt::NoPen;
541 const qreal isw = 1.0 / sw;
542 const qreal ish = 1.0 / sh;
543 QTransform inv(isw, 0, 0, ish, 0, 0);
544 engine->drawPath(path * inv);
549 if (brushMode == QGradient::ObjectBoundingMode) {
550 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
551 boundingRect = path.boundingRect();
552 q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
558 if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
559 // Draw the xformed outline if the pen is a stretch gradient.
560 if (penMode == QGradient::StretchToDeviceMode) {
561 q->setPen(Qt::NoPen);
566 engine->drawPath(path);
570 q->setBrush(pen.brush());
574 QPainterPathStroker stroker;
575 stroker.setDashPattern(pen.style());
576 stroker.setWidth(pen.widthF());
577 stroker.setJoinStyle(pen.joinStyle());
578 stroker.setCapStyle(pen.capStyle());
579 stroker.setMiterLimit(pen.miterLimit());
580 QPainterPath stroke = stroker.createStroke(path);
582 const qreal isw = 1.0 / sw;
583 const qreal ish = 1.0 / sh;
584 QTransform inv(isw, 0, 0, ish, 0, 0);
585 engine->drawPath(stroke * inv);
588 if (!needsFill && brush.style() != Qt::NoBrush) {
589 q->setBrush(Qt::NoBrush);
593 if (penMode == QGradient::ObjectBoundingMode) {
594 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
596 // avoid computing the bounding rect twice
597 if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
598 boundingRect = path.boundingRect();
601 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect));
604 } else if (changedPen) {
610 engine->drawPath(path);
612 } else if (needsFill) {
613 if (pen.style() != Qt::NoPen) {
614 q->setPen(Qt::NoPen);
619 engine->drawPath(path);
629 void QPainterPrivate::updateMatrix()
631 state->matrix = state->WxF ? state->worldMatrix : QTransform();
633 state->matrix *= viewTransform();
635 txinv = false; // no inverted matrix
636 state->matrix *= state->redirectionMatrix;
638 extended->transformChanged();
640 state->dirtyFlags |= QPaintEngine::DirtyTransform;
642 // printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
643 // qDebug() << " --- using matrix" << state->matrix << redirection_offset;
647 void QPainterPrivate::updateInvMatrix()
649 Q_ASSERT(txinv == false);
650 txinv = true; // creating inverted matrix
651 invMatrix = state->matrix.inverted();
654 extern bool qt_isExtendedRadialGradient(const QBrush &brush);
656 void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
659 bool linearGradient = false;
660 bool radialGradient = false;
661 bool extendedRadialGradient = false;
662 bool conicalGradient = false;
663 bool patternBrush = false;
665 bool complexXform = false;
669 // Pen and brush properties (we have to check both if one changes because the
670 // one that's unchanged can still be in a state which requires emulation)
671 if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) {
672 // Check Brush stroke emulation
673 if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke))
674 s->emulationSpecifier |= QPaintEngine::BrushStroke;
676 s->emulationSpecifier &= ~QPaintEngine::BrushStroke;
680 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
681 Qt::BrushStyle brushStyle = qbrush_style(s->brush);
682 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
683 alpha = (penBrushStyle != Qt::NoBrush
684 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
685 && !penBrush.isOpaque())
686 || (brushStyle != Qt::NoBrush
687 && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
688 && !s->brush.isOpaque());
689 linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
690 (brushStyle == Qt::LinearGradientPattern));
691 radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
692 (brushStyle == Qt::RadialGradientPattern));
693 extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
694 conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
695 (brushStyle == Qt::ConicalGradientPattern));
696 patternBrush = (((penBrushStyle > Qt::SolidPattern
697 && penBrushStyle < Qt::LinearGradientPattern)
698 || penBrushStyle == Qt::TexturePattern) ||
699 ((brushStyle > Qt::SolidPattern
700 && brushStyle < Qt::LinearGradientPattern)
701 || brushStyle == Qt::TexturePattern));
703 bool penTextureAlpha = false;
704 if (penBrush.style() == Qt::TexturePattern)
705 penTextureAlpha = qHasPixmapTexture(penBrush)
706 ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
707 : penBrush.textureImage().hasAlphaChannel();
708 bool brushTextureAlpha = false;
709 if (s->brush.style() == Qt::TexturePattern) {
710 brushTextureAlpha = qHasPixmapTexture(s->brush)
711 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
712 : s->brush.textureImage().hasAlphaChannel();
714 if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
715 || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
716 && !engine->hasFeature(QPaintEngine::MaskedBrush))
717 s->emulationSpecifier |= QPaintEngine::MaskedBrush;
719 s->emulationSpecifier &= ~QPaintEngine::MaskedBrush;
722 if (s->state() & (QPaintEngine::DirtyHints
723 | QPaintEngine::DirtyOpacity
724 | QPaintEngine::DirtyBackgroundMode)) {
732 qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
734 " - linearGradient: %d\n"
735 " - radialGradient: %d\n"
736 " - conicalGradient: %d\n"
737 " - patternBrush: %d\n"
746 uint(s->renderHints),
751 if (s->state() & QPaintEngine::DirtyTransform) {
752 xform = !s->matrix.isIdentity();
753 complexXform = !s->matrix.isAffine();
754 } else if (s->matrix.type() >= QTransform::TxTranslate) {
756 complexXform = !s->matrix.isAffine();
759 const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone);
760 const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone);
762 const bool patternXform = patternBrush && (xform || brushXform || penXform);
764 // Check alphablending
765 if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend))
766 s->emulationSpecifier |= QPaintEngine::AlphaBlend;
768 s->emulationSpecifier &= ~QPaintEngine::AlphaBlend;
770 // Linear gradient emulation
771 if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill))
772 s->emulationSpecifier |= QPaintEngine::LinearGradientFill;
774 s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
776 // Radial gradient emulation
777 if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
778 s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
780 s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
782 // Conical gradient emulation
783 if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
784 s->emulationSpecifier |= QPaintEngine::ConicalGradientFill;
786 s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill;
789 if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
790 s->emulationSpecifier |= QPaintEngine::PatternBrush;
792 s->emulationSpecifier &= ~QPaintEngine::PatternBrush;
795 if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform))
796 s->emulationSpecifier |= QPaintEngine::PatternTransform;
798 s->emulationSpecifier &= ~QPaintEngine::PatternTransform;
801 if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform))
802 s->emulationSpecifier |= QPaintEngine::PrimitiveTransform;
804 s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform;
806 // Perspective XForms
807 if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform))
808 s->emulationSpecifier |= QPaintEngine::PerspectiveTransform;
810 s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform;
813 if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity))
814 s->emulationSpecifier |= QPaintEngine::ConstantOpacity;
816 s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity;
818 bool gradientStretch = false;
819 bool objectBoundingMode = false;
820 if (linearGradient || conicalGradient || radialGradient) {
821 QGradient::CoordinateMode brushMode = coordinateMode(s->brush);
822 QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush());
824 gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
825 gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
827 objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
828 objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
831 s->emulationSpecifier |= QGradient_StretchToDevice;
833 s->emulationSpecifier &= ~QGradient_StretchToDevice;
835 if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
836 s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients;
838 s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients;
840 // Opaque backgrounds...
841 if (s->bgMode == Qt::OpaqueMode &&
842 (is_pen_transparent(s->pen) || is_brush_transparent(s->brush)))
843 s->emulationSpecifier |= QPaintEngine_OpaqueBackground;
845 s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground;
848 //won't be correct either way because the device can already have
849 // something rendered to it in which case subsequent emulation
850 // on a fully transparent qimage and then blitting the results
851 // won't produce correct results
853 if (state->composition_mode > QPainter::CompositionMode_Xor &&
854 !engine->hasFeature(QPaintEngine::BlendModes))
855 s->emulationSpecifier |= QPaintEngine::BlendModes;
857 s->emulationSpecifier &= ~QPaintEngine::BlendModes;
861 void QPainterPrivate::updateStateImpl(QPainterState *newState)
863 // ### we might have to call QPainter::begin() here...
864 if (!engine->state) {
865 engine->state = newState;
866 engine->setDirty(QPaintEngine::AllDirty);
869 if (engine->state->painter() != newState->painter)
870 // ### this could break with clip regions vs paths.
871 engine->setDirty(QPaintEngine::AllDirty);
873 // Upon restore, revert all changes since last save
874 else if (engine->state != newState)
875 newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
877 // We need to store all changes made so that restore can deal with them
879 newState->changeFlags |= newState->dirtyFlags;
881 updateEmulationSpecifier(newState);
883 // Unset potential dirty background mode
884 newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode
885 | QPaintEngine::DirtyBackground);
887 engine->state = newState;
888 engine->updateState(*newState);
889 engine->clearDirty(QPaintEngine::AllDirty);
893 void QPainterPrivate::updateState(QPainterState *newState)
897 engine->state = newState;
899 } else if (newState->state() || engine->state!=newState) {
900 bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
901 && newState->pen.widthF() == 0;
902 if (setNonCosmeticPen) {
903 // Override the default pen's cosmetic state if the
904 // NonCosmeticDefaultPen render hint is used.
905 QPen oldPen = newState->pen;
906 newState->pen.setWidth(1);
907 newState->pen.setCosmetic(false);
908 newState->dirtyFlags |= QPaintEngine::DirtyPen;
910 updateStateImpl(newState);
912 // Restore the state pen back to its default to preserve visible
914 newState->pen = oldPen;
916 updateStateImpl(newState);
924 \brief The QPainter class performs low-level painting on widgets and
931 QPainter provides highly optimized functions to do most of the
932 drawing GUI programs require. It can draw everything from simple
933 lines to complex shapes like pies and chords. It can also draw
934 aligned text and pixmaps. Normally, it draws in a "natural"
935 coordinate system, but it can also do view and world
936 transformation. QPainter can operate on any object that inherits
937 the QPaintDevice class.
939 The common use of QPainter is inside a widget's paint event:
940 Construct and customize (e.g. set the pen or the brush) the
941 painter. Then draw. Remember to destroy the QPainter object after
942 drawing. For example:
944 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 0
946 The core functionality of QPainter is drawing, but the class also
947 provide several functions that allows you to customize QPainter's
948 settings and its rendering quality, and others that enable
949 clipping. In addition you can control how different shapes are
950 merged together by specifying the painter's composition mode.
952 The isActive() function indicates whether the painter is active. A
953 painter is activated by the begin() function and the constructor
954 that takes a QPaintDevice argument. The end() function, and the
955 destructor, deactivates it.
957 Together with the QPaintDevice and QPaintEngine classes, QPainter
958 form the basis for Qt's paint system. QPainter is the class used
959 to perform drawing operations. QPaintDevice represents a device
960 that can be painted on using a QPainter. QPaintEngine provides the
961 interface that the painter uses to draw onto different types of
962 devices. If the painter is active, device() returns the paint
963 device on which the painter paints, and paintEngine() returns the
964 paint engine that the painter is currently operating on. For more
965 information, see the \l {Paint System}.
967 Sometimes it is desirable to make someone else paint on an unusual
968 QPaintDevice. QPainter supports a static function to do this,
971 \warning When the paintdevice is a widget, QPainter can only be
972 used inside a paintEvent() function or in a function called by
979 There are several settings that you can customize to make QPainter
980 draw according to your preferences:
984 \li font() is the font used for drawing text. If the painter
985 isActive(), you can retrieve information about the currently set
986 font, and its metrics, using the fontInfo() and fontMetrics()
987 functions respectively.
989 \li brush() defines the color or pattern that is used for filling
992 \li pen() defines the color or stipple that is used for drawing
995 \li backgroundMode() defines whether there is a background() or
996 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
998 \li background() only applies when backgroundMode() is \l
999 Qt::OpaqueMode and pen() is a stipple. In that case, it
1000 describes the color of the background pixels in the stipple.
1002 \li brushOrigin() defines the origin of the tiled brushes, normally
1003 the origin of widget's background.
1005 \li viewport(), window(), worldTransform() make up the painter's coordinate
1006 transformation system. For more information, see the \l
1007 {Coordinate Transformations} section and the \l {Coordinate
1008 System} documentation.
1010 \li hasClipping() tells whether the painter clips at all. (The paint
1011 device clips, too.) If the painter clips, it clips to clipRegion().
1013 \li layoutDirection() defines the layout direction used by the
1014 painter when drawing text.
1016 \li worldMatrixEnabled() tells whether world transformation is enabled.
1018 \li viewTransformEnabled() tells whether view transformation is
1023 Note that some of these settings mirror settings in some paint
1024 devices, e.g. QWidget::font(). The QPainter::begin() function (or
1025 equivalently the QPainter constructor) copies these attributes
1026 from the paint device.
1028 You can at any time save the QPainter's state by calling the
1029 save() function which saves all the available settings on an
1030 internal stack. The restore() function pops them back.
1034 QPainter provides functions to draw most primitives: drawPoint(),
1035 drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1036 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1037 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
1038 convenience functions, drawRects() and drawLines(), draw the given
1039 number of rectangles or lines in the given array of \l
1040 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1043 The QPainter class also provides the fillRect() function which
1044 fills the given QRect, with the given QBrush, and the eraseRect()
1045 function that erases the area inside the given rectangle.
1047 All of these functions have both integer and floating point
1052 \li \inlineimage qpainter-basicdrawing.png
1054 \b {Basic Drawing Example}
1056 The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1057 display basic graphics primitives in a variety of styles using the
1062 If you need to draw a complex shape, especially if you need to do
1063 so repeatedly, consider creating a QPainterPath and drawing it
1069 \b {Painter Paths example}
1071 The QPainterPath class provides a container for painting
1072 operations, enabling graphical shapes to be constructed and
1075 The \l {painting/painterpaths}{Painter Paths} example shows how
1076 painter paths can be used to build complex shapes for rendering.
1078 \li \inlineimage qpainter-painterpaths.png
1081 QPainter also provides the fillPath() function which fills the
1082 given QPainterPath with the given QBrush, and the strokePath()
1083 function that draws the outline of the given path (i.e. strokes
1086 See also the \l {painting/deform}{Vector Deformation} example which
1087 shows how to use advanced vector techniques to draw text using a
1088 QPainterPath, the \l {painting/gradients}{Gradients} example which shows
1089 the different types of gradients that are available in Qt, and the \l
1090 {painting/pathstroke}{Path Stroking} example which shows Qt's built-in
1091 dash patterns and shows how custom patterns can be used to extend
1092 the range of available patterns.
1096 \li \l {painting/deform}{Vector Deformation}
1097 \li \l {painting/gradients}{Gradients}
1098 \li \l {painting/pathstroke}{Path Stroking}
1100 \li \inlineimage qpainter-vectordeformation.png
1101 \li \inlineimage qpainter-gradients.png
1102 \li \inlineimage qpainter-pathstroking.png
1106 There are functions to draw pixmaps/images, namely drawPixmap(),
1107 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1108 produce the same result, except that drawPixmap() is faster
1109 on-screen while drawImage() may be faster on a QPrinter or other
1112 Text drawing is done using drawText(). When you need
1113 fine-grained positioning, boundingRect() tells you where a given
1114 drawText() command will draw.
1116 There is a drawPicture() function that draws the contents of an
1117 entire QPicture. The drawPicture() function is the only function
1118 that disregards all the painter's settings as QPicture has its own
1121 \section1 Rendering Quality
1123 To get the optimal rendering result using QPainter, you should use
1124 the platform independent QImage as paint device; i.e. using QImage
1125 will ensure that the result has an identical pixel representation
1128 The QPainter class also provides a means of controlling the
1129 rendering quality through its RenderHint enum and the support for
1130 floating point precision: All the functions for drawing primitives
1131 has a floating point version. These are often used in combination
1132 with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1136 \li \inlineimage qpainter-concentriccircles.png
1138 \b {Concentric Circles Example}
1140 The \l {painting/concentriccircles}{Concentric Circles} example
1141 shows the improved rendering quality that can be obtained using
1142 floating point precision and anti-aliasing when drawing custom
1145 The application's main window displays several widgets which are
1146 drawn using the various combinations of precision and
1151 The RenderHint enum specifies flags to QPainter that may or may
1152 not be respected by any given engine. \l
1153 {RenderHint}{QPainter::Antialiasing} indicates that the engine
1154 should antialias edges of primitives if possible, \l
1155 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1156 should antialias text if possible, and the \l
1157 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1158 engine should use a smooth pixmap transformation algorithm.
1159 \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
1160 indicating that the engine should use fragment programs and offscreen
1161 rendering for antialiasing.
1163 The renderHints() function returns a flag that specifies the
1164 rendering hints that are set for this painter. Use the
1165 setRenderHint() function to set or clear the currently set
1168 \section1 Coordinate Transformations
1170 Normally, the QPainter operates on the device's own coordinate
1171 system (usually pixels), but QPainter has good support for
1172 coordinate transformations.
1176 \li nop \li rotate() \li scale() \li translate()
1178 \li \inlineimage qpainter-clock.png
1179 \li \inlineimage qpainter-rotation.png
1180 \li \inlineimage qpainter-scale.png
1181 \li \inlineimage qpainter-translation.png
1184 The most commonly used transformations are scaling, rotation,
1185 translation and shearing. Use the scale() function to scale the
1186 coordinate system by a given offset, the rotate() function to
1187 rotate it clockwise and translate() to translate it (i.e. adding a
1188 given offset to the points). You can also twist the coordinate
1189 system around the origin using the shear() function. See the \l
1190 {painting/affine}{Affine Transformations} example for a visualization of
1191 a sheared coordinate system.
1193 See also the \l {painting/transformations}{Transformations}
1194 example which shows how transformations influence the way that
1195 QPainter renders graphics primitives. In particular it shows how
1196 the order of transformations affects the result.
1201 \b {Affine Transformations Example}
1203 The \l {painting/affine}{Affine Transformations} example shows Qt's
1204 ability to perform affine transformations on painting
1205 operations. The demo also allows the user to experiment with the
1206 transformation operations and see the results immediately.
1208 \li \inlineimage qpainter-affinetransformations.png
1211 All the tranformation operations operate on the transformation
1212 worldTransform(). A matrix transforms a point in the plane to another
1213 point. For more information about the transformation matrix, see
1214 the \l {Coordinate System} and QTransform documentation.
1216 The setWorldTransform() function can replace or add to the currently
1217 set worldTransform(). The resetTransform() function resets any
1218 transformations that were made using translate(), scale(),
1219 shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1220 functions. The deviceTransform() returns the matrix that transforms
1221 from logical coordinates to device coordinates of the platform
1222 dependent paint device. The latter function is only needed when
1223 using platform painting commands on the platform dependent handle,
1224 and the platform does not do transformations nativly.
1226 When drawing with QPainter, we specify points using logical
1227 coordinates which then are converted into the physical coordinates
1228 of the paint device. The mapping of the logical coordinates to the
1229 physical coordinates are handled by QPainter's combinedTransform(), a
1230 combination of viewport() and window() and worldTransform(). The
1231 viewport() represents the physical coordinates specifying an
1232 arbitrary rectangle, the window() describes the same rectangle in
1233 logical coordinates, and the worldTransform() is identical with the
1234 transformation matrix.
1236 See also \l {Coordinate System}
1240 QPainter can clip any drawing operation to a rectangle, a region,
1241 or a vector path. The current clip is available using the
1242 functions clipRegion() and clipPath(). Whether paths or regions are
1243 preferred (faster) depends on the underlying paintEngine(). For
1244 example, the QImage paint engine prefers paths while the X11 paint
1245 engine prefers regions. Setting a clip is done in the painters
1246 logical coordinates.
1248 After QPainter's clipping, the paint device may also clip. For
1249 example, most widgets clip away the pixels used by child widgets,
1250 and most printers clip away an area near the edges of the paper.
1251 This additional clipping is not reflected by the return value of
1252 clipRegion() or hasClipping().
1254 \section1 Composition Modes
1255 \target Composition Modes
1257 QPainter provides the CompositionMode enum which defines the
1258 Porter-Duff rules for digital image compositing; it describes a
1259 model for combining the pixels in one image, the source, with the
1260 pixels in another image, the destination.
1262 The two most common forms of composition are \l
1263 {QPainter::CompositionMode}{Source} and \l
1264 {QPainter::CompositionMode}{SourceOver}. \l
1265 {QPainter::CompositionMode}{Source} is used to draw opaque objects
1266 onto a paint device. In this mode, each pixel in the source
1267 replaces the corresponding pixel in the destination. In \l
1268 {QPainter::CompositionMode}{SourceOver} composition mode, the
1269 source object is transparent and is drawn on top of the
1272 Note that composition transformation operates pixelwise. For that
1273 reason, there is a difference between using the graphic primitive
1274 itself and its bounding rectangle: The bounding rect contains
1275 pixels with alpha == 0 (i.e the pixels surrounding the
1276 primitive). These pixels will overwrite the other image's pixels,
1277 affectively clearing those, while the primitive only overwrites
1282 \li \inlineimage qpainter-compositiondemo.png
1285 \b {Composition Modes Example}
1287 The \l {painting/composition}{Composition Modes} example, available in
1288 Qt's examples directory, allows you to experiment with the various
1289 composition modes and see the results immediately.
1293 \section1 Limitations
1296 If you are using coordinates with Qt's raster-based paint engine, it is
1297 important to note that, while coordinates greater than +/- 2\sup 15 can
1298 be used, any painting performed with coordinates outside this range is not
1299 guaranteed to be shown; the drawing may be clipped. This is due to the
1300 use of \c{short int} in the implementation.
1302 The outlines generated by Qt's stroker are only an approximation when dealing
1303 with curved shapes. It is in most cases impossible to represent the outline of
1304 a bezier curve segment using another bezier curve segment, and so Qt approximates
1305 the curve outlines by using several smaller curves. For performance reasons there
1306 is a limit to how many curves Qt uses for these outlines, and thus when using
1307 large pen widths or scales the outline error increases. To generate outlines with
1308 smaller errors it is possible to use the QPainterPathStroker class, which has the
1309 setCurveThreshold member function which let's the user specify the error tolerance.
1310 Another workaround is to convert the paths to polygons first and then draw the
1313 \section1 Performance
1315 QPainter is a rich framework that allows developers to do a great
1316 variety of graphical operations, such as gradients, composition
1317 modes and vector graphics. And QPainter can do this across a
1318 variety of different hardware and software stacks. Naturally the
1319 underlying combination of hardware and software has some
1320 implications for performance, and ensuring that every single
1321 operation is fast in combination with all the various combinations
1322 of composition modes, brushes, clipping, transformation, etc, is
1323 close to an impossible task because of the number of
1324 permutations. As a compromise we have selected a subset of the
1325 QPainter API and backends, where performance is guaranteed to be as
1326 good as we can sensibly get it for the given combination of
1327 hardware and software.
1329 The backends we focus on as high-performance engines are:
1333 \li Raster - This backend implements all rendering in pure software
1334 and is always used to render into QImages. For optimal performance
1335 only use the format types QImage::Format_ARGB32_Premultiplied,
1336 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1337 including QImage::Format_ARGB32, has significantly worse
1338 performance. This engine is used by default for QWidget and QPixmap.
1340 \li OpenGL 2.0 (ES) - This backend is the primary backend for
1341 hardware accelerated graphics. It can be run on desktop machines
1342 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1343 specification. This includes most graphics chips produced in the
1344 last couple of years. The engine can be enabled by using QPainter
1345 onto a QOpenGLWidget or by passing \c {-graphicssystem opengl} on the
1346 command line when the underlying system supports it.
1348 \li OpenVG - This backend implements the Khronos standard for 2D
1349 and Vector Graphics. It is primarily for embedded devices with
1350 hardware support for OpenVG. The engine can be enabled by
1351 passing \c {-graphicssystem openvg} on the command line when
1352 the underlying system supports it.
1356 These operations are:
1360 \li Simple transformations, meaning translation and scaling, pluss
1361 0, 90, 180, 270 degree rotations.
1363 \li \c drawPixmap() in combination with simple transformations and
1364 opacity with non-smooth transformation mode
1365 (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1367 \li Rectangle fills with solid color, two-color linear gradients
1368 and simple transforms.
1370 \li Rectangular clipping with simple transformations and intersect
1373 \li Composition Modes \c QPainter::CompositionMode_Source and
1374 QPainter::CompositionMode_SourceOver
1376 \li Rounded rectangle filling using solid color and two-color
1377 linear gradients fills.
1379 \li 3x3 patched pixmaps, via qDrawBorderPixmap.
1383 This list gives an indication of which features to safely use in
1384 an application where performance is critical. For certain setups,
1385 other operations may be fast too, but before making extensive use
1386 of them, it is recommended to benchmark and verify them on the
1387 system where the software will run in the end. There are also
1388 cases where expensive operations are ok to use, for instance when
1389 the result is cached in a QPixmap.
1391 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
1392 {Drawing Utility Functions}
1396 \enum QPainter::RenderHint
1398 Renderhints are used to specify flags to QPainter that may or
1399 may not be respected by any given engine.
1401 \value Antialiasing Indicates that the engine should antialias
1402 edges of primitives if possible.
1404 \value TextAntialiasing Indicates that the engine should antialias
1405 text if possible. To forcibly disable antialiasing for text, do not
1406 use this hint. Instead, set QFont::NoAntialias on your font's style
1409 \value SmoothPixmapTransform Indicates that the engine should use
1410 a smooth pixmap transformation algorithm (such as bilinear) rather
1411 than nearest neighbor.
1413 \value HighQualityAntialiasing An OpenGL-specific rendering hint
1414 indicating that the engine should use fragment programs and offscreen
1415 rendering for antialiasing.
1417 \value NonCosmeticDefaultPen The engine should interpret pens with a width
1418 of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
1419 pen with a width of 1.
1421 \sa renderHints(), setRenderHint(), {QPainter#Rendering
1422 Quality}{Rendering Quality}, {Concentric Circles Example}
1427 Constructs a painter.
1432 QPainter::QPainter()
1433 : d_ptr(new QPainterPrivate(this))
1438 \fn QPainter::QPainter(QPaintDevice *device)
1440 Constructs a painter that begins painting the paint \a device
1443 This constructor is convenient for short-lived painters, e.g. in a
1444 QWidget::paintEvent() and should be used only once. The
1445 constructor calls begin() for you and the QPainter destructor
1446 automatically calls end().
1448 Here's an example using begin() and end():
1449 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 1
1451 The same example using this constructor:
1452 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 2
1454 Since the constructor cannot provide feedback when the initialization
1455 of the painter failed you should rather use begin() and end() to paint
1456 on external devices, e.g. printers.
1461 QPainter::QPainter(QPaintDevice *pd)
1465 if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1466 d_ptr.reset(new QPainterPrivate(this));
1473 Destroys the painter.
1475 QPainter::~QPainter()
1477 d_ptr->inDestructor = true;
1481 else if (d_ptr->refcount > 1)
1482 d_ptr->detachPainterPrivate(this);
1484 // don't throw anything in the destructor.
1487 // Make sure we haven't messed things up.
1488 Q_ASSERT(d_ptr->inDestructor);
1489 d_ptr->inDestructor = false;
1490 Q_ASSERT(d_ptr->refcount == 1);
1492 free(d_ptr->d_ptrs);
1497 Returns the paint device on which this painter is currently
1498 painting, or 0 if the painter is not active.
1503 QPaintDevice *QPainter::device() const
1505 Q_D(const QPainter);
1506 if (isActive() && d->engine->d_func()->currentClipDevice)
1507 return d->engine->d_func()->currentClipDevice;
1508 return d->original_device;
1512 Returns true if begin() has been called and end() has not yet been
1513 called; otherwise returns false.
1515 \sa begin(), QPaintDevice::paintingActive()
1518 bool QPainter::isActive() const
1520 Q_D(const QPainter);
1525 Initializes the painters pen, background and font to the same as
1526 the given \a paint device.
1530 \sa begin(), {QPainter#Settings}{Settings}
1532 void QPainter::initFrom(const QPaintDevice *device)
1534 Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0");
1537 qWarning("QPainter::initFrom: Painter not active, aborted");
1544 d->extended->penChanged();
1545 } else if (d->engine) {
1546 d->engine->setDirty(QPaintEngine::DirtyPen);
1547 d->engine->setDirty(QPaintEngine::DirtyBrush);
1548 d->engine->setDirty(QPaintEngine::DirtyFont);
1554 Saves the current painter state (pushes the state onto a stack). A
1555 save() must be followed by a corresponding restore(); the end()
1556 function unwinds the stack.
1561 void QPainter::save()
1563 #ifdef QT_DEBUG_DRAW
1564 if (qt_show_painter_debug_output)
1565 printf("QPainter::save()\n");
1569 qWarning("QPainter::save: Painter not active");
1574 d->state = d->extended->createState(d->states.back());
1575 d->extended->setState(d->state);
1577 d->updateState(d->state);
1578 d->state = new QPainterState(d->states.back());
1579 d->engine->state = d->state;
1581 d->states.push_back(d->state);
1585 Restores the current painter state (pops a saved state off the
1591 void QPainter::restore()
1593 #ifdef QT_DEBUG_DRAW
1594 if (qt_show_painter_debug_output)
1595 printf("QPainter::restore()\n");
1598 if (d->states.size()<=1) {
1599 qWarning("QPainter::restore: Unbalanced save/restore");
1601 } else if (!d->engine) {
1602 qWarning("QPainter::restore: Painter not active");
1606 QPainterState *tmp = d->state;
1607 d->states.pop_back();
1608 d->state = d->states.back();
1612 d->checkEmulation();
1613 d->extended->setState(d->state);
1618 // trigger clip update if the clip path/region has changed since
1620 if (!d->state->clipInfo.isEmpty()
1621 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1622 // reuse the tmp state to avoid any extra allocs...
1623 tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1624 tmp->clipOperation = Qt::NoClip;
1625 tmp->clipPath = QPainterPath();
1626 d->engine->updateState(*tmp);
1627 // replay the list of clip states,
1628 for (int i=0; i<d->state->clipInfo.size(); ++i) {
1629 const QPainterClipInfo &info = d->state->clipInfo.at(i);
1630 tmp->matrix = info.matrix;
1631 tmp->matrix *= d->state->redirectionMatrix;
1632 tmp->clipOperation = info.operation;
1633 if (info.clipType == QPainterClipInfo::RectClip) {
1634 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1635 tmp->clipRegion = info.rect;
1636 } else if (info.clipType == QPainterClipInfo::RegionClip) {
1637 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1638 tmp->clipRegion = info.region;
1639 } else { // clipType == QPainterClipInfo::PathClip
1640 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1641 tmp->clipPath = info.path;
1643 d->engine->updateState(*tmp);
1647 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1648 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1649 tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1650 tmp->changeFlags |= QPaintEngine::DirtyTransform;
1653 d->updateState(d->state);
1660 \fn bool QPainter::begin(QPaintDevice *device)
1662 Begins painting the paint \a device and returns true if
1663 successful; otherwise returns false.
1665 Notice that all painter settings (setPen(), setBrush() etc.) are reset
1666 to default values when begin() is called.
1668 The errors that can occur are serious problems, such as these:
1670 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 3
1672 Note that most of the time, you can use one of the constructors
1673 instead of begin(), and that end() is automatically done at
1676 \warning A paint device can only be painted by one painter at a
1679 \warning Painting on a QImage with the format
1680 QImage::Format_Indexed8 is not supported.
1682 \sa end(), QPainter()
1685 static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1694 bool QPainter::begin(QPaintDevice *pd)
1698 if (pd->painters > 0) {
1699 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1703 if (d_ptr->engine) {
1704 qWarning("QPainter::begin: Painter already active");
1708 if (QPainterPrivate::attachPainterPrivate(this, pd))
1713 d->helper_device = pd;
1714 d->original_device = pd;
1716 QPoint redirectionOffset;
1717 QPaintDevice *rpd = pd->redirected(&redirectionOffset);
1721 #ifdef QT_DEBUG_DRAW
1722 if (qt_show_painter_debug_output)
1723 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1726 if (pd->devType() == QInternal::Pixmap)
1727 static_cast<QPixmap *>(pd)->detach();
1728 else if (pd->devType() == QInternal::Image)
1729 static_cast<QImage *>(pd)->detach();
1731 d->engine = pd->paintEngine();
1734 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1740 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1741 if (d->emulationEngine)
1742 d->emulationEngine->real_engine = d->extended;
1744 // Setup new state...
1745 Q_ASSERT(!d->state);
1746 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1747 d->state->painter = this;
1748 d->states.push_back(d->state);
1750 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1751 d->state->brushOrigin = QPointF();
1753 // Slip a painter state into the engine before we do any other operations
1755 d->extended->setState(d->state);
1757 d->engine->state = d->state;
1759 switch (pd->devType()) {
1760 case QInternal::Pixmap:
1762 QPixmap *pm = static_cast<QPixmap *>(pd);
1765 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1766 qt_cleanup_painter_state(d);
1770 if (pm->depth() == 1) {
1771 d->state->pen = QPen(Qt::color1);
1772 d->state->brush = QBrush(Qt::color0);
1776 case QInternal::Image:
1778 QImage *img = static_cast<QImage *>(pd);
1780 if (img->isNull()) {
1781 qWarning("QPainter::begin: Cannot paint on a null image");
1782 qt_cleanup_painter_state(d);
1784 } else if (img->format() == QImage::Format_Indexed8) {
1785 // Painting on indexed8 images is not supported.
1786 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1787 qt_cleanup_painter_state(d);
1790 if (img->depth() == 1) {
1791 d->state->pen = QPen(Qt::color1);
1792 d->state->brush = QBrush(Qt::color0);
1799 if (d->state->ww == 0) // For compat with 3.x painter defaults
1800 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1802 d->engine->setPaintDevice(pd);
1804 bool begun = d->engine->begin(pd);
1806 qWarning("QPainter::begin(): Returned false");
1807 if (d->engine->isActive()) {
1810 qt_cleanup_painter_state(d);
1814 d->engine->setActive(begun);
1817 // Copy painter properties from original paint device,
1818 // required for QPixmap::grabWidget()
1819 if (d->original_device->devType() == QInternal::Widget) {
1820 initFrom(d->original_device);
1822 d->state->layoutDirection = Qt::LayoutDirectionAuto;
1823 // make sure we have a font compatible with the paintdevice
1824 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1827 QRect systemRect = d->engine->systemRect();
1828 if (!systemRect.isEmpty()) {
1829 d->state->ww = d->state->vw = systemRect.width();
1830 d->state->wh = d->state->vh = systemRect.height();
1832 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1833 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1836 const QPoint coordinateOffset = d->engine->coordinateOffset();
1837 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1839 Q_ASSERT(d->engine->isActive());
1841 if (!d->state->redirectionMatrix.isIdentity())
1844 Q_ASSERT(d->engine->isActive());
1845 d->state->renderHints = QPainter::TextAntialiasing;
1846 ++d->device->painters;
1848 d->state->emulationSpecifier = 0;
1854 Ends painting. Any resources used while painting are released. You
1855 don't normally need to call this since it is called by the
1858 Returns true if the painter is no longer active; otherwise returns false.
1860 \sa begin(), isActive()
1863 bool QPainter::end()
1865 #ifdef QT_DEBUG_DRAW
1866 if (qt_show_painter_debug_output)
1867 printf("QPainter::end()\n");
1872 qWarning("QPainter::end: Painter not active, aborted");
1873 qt_cleanup_painter_state(d);
1877 if (d->refcount > 1) {
1878 d->detachPainterPrivate(this);
1884 if (d->engine->isActive()) {
1885 ended = d->engine->end();
1888 --d->device->painters;
1889 if (d->device->painters == 0) {
1890 d->engine->setPaintDevice(0);
1891 d->engine->setActive(false);
1895 if (d->states.size() > 1) {
1896 qWarning("QPainter::end: Painter ended with %d saved states",
1900 if (d->engine->autoDestruct()) {
1904 if (d->emulationEngine) {
1905 delete d->emulationEngine;
1906 d->emulationEngine = 0;
1913 qt_cleanup_painter_state(d);
1920 Returns the paint engine that the painter is currently operating
1921 on if the painter is active; otherwise 0.
1925 QPaintEngine *QPainter::paintEngine() const
1927 Q_D(const QPainter);
1934 Flushes the painting pipeline and prepares for the user issuing commands
1935 directly to the underlying graphics context. Must be followed by a call to
1936 endNativePainting().
1938 Note that only the states the underlying paint engine changes will be reset
1939 to their respective default states. The states we reset may change from
1940 release to release. The following states are currently reset in the OpenGL
1944 \li blending is disabled
1945 \li the depth, stencil and scissor tests are disabled
1946 \li the active texture unit is reset to 0
1947 \li the depth mask, depth function and the clear depth are reset to their
1949 \li the stencil mask, stencil operation and stencil function are reset to
1950 their default values
1951 \li the current color is reset to solid white
1954 If, for example, the OpenGL polygon mode is changed by the user inside a
1955 beginNativePaint()/endNativePainting() block, it will not be reset to the
1956 default state by endNativePainting(). Here is an example that shows
1957 intermixing of painter commands and raw OpenGL commands:
1959 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
1961 \sa endNativePainting()
1963 void QPainter::beginNativePainting()
1967 qWarning("QPainter::beginNativePainting: Painter not active");
1972 d->extended->beginNativePainting();
1978 Restores the painter after manually issuing native painting commands. Lets
1979 the painter restore any native state that it relies on before calling any
1980 other painter commands.
1982 \sa beginNativePainting()
1984 void QPainter::endNativePainting()
1986 Q_D(const QPainter);
1988 qWarning("QPainter::beginNativePainting: Painter not active");
1993 d->extended->endNativePainting();
1995 d->engine->syncState();
1999 Returns the font metrics for the painter if the painter is
2000 active. Otherwise, the return value is undefined.
2002 \sa font(), isActive(), {QPainter#Settings}{Settings}
2005 QFontMetrics QPainter::fontMetrics() const
2007 Q_D(const QPainter);
2009 qWarning("QPainter::fontMetrics: Painter not active");
2010 return QFontMetrics(QFont());
2012 return QFontMetrics(d->state->font);
2017 Returns the font info for the painter if the painter is
2018 active. Otherwise, the return value is undefined.
2020 \sa font(), isActive(), {QPainter#Settings}{Settings}
2023 QFontInfo QPainter::fontInfo() const
2025 Q_D(const QPainter);
2027 qWarning("QPainter::fontInfo: Painter not active");
2028 return QFontInfo(QFont());
2030 return QFontInfo(d->state->font);
2036 Returns the opacity of the painter. The default value is
2040 qreal QPainter::opacity() const
2042 Q_D(const QPainter);
2044 qWarning("QPainter::opacity: Painter not active");
2047 return d->state->opacity;
2053 Sets the opacity of the painter to \a opacity. The value should
2054 be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2055 1.0 is fully opaque.
2057 Opacity set on the painter will apply to all drawing operations
2061 void QPainter::setOpacity(qreal opacity)
2066 qWarning("QPainter::setOpacity: Painter not active");
2070 opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2072 if (opacity == d->state->opacity)
2075 d->state->opacity = opacity;
2078 d->extended->opacityChanged();
2080 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2085 Returns the currently set brush origin.
2087 \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2090 QPoint QPainter::brushOrigin() const
2092 Q_D(const QPainter);
2094 qWarning("QPainter::brushOrigin: Painter not active");
2097 return QPointF(d->state->brushOrigin).toPoint();
2101 \fn void QPainter::setBrushOrigin(const QPointF &position)
2103 Sets the brush origin to \a position.
2105 The brush origin specifies the (0, 0) coordinate of the painter's
2108 Note that while the brushOrigin() was necessary to adopt the
2109 parent's background for a widget in Qt 3, this is no longer the
2110 case since the Qt 4 painter doesn't paint the background unless
2111 you explicitly tell it to do so by setting the widget's \l
2112 {QWidget::autoFillBackground}{autoFillBackground} property to
2115 \sa brushOrigin(), {QPainter#Settings}{Settings}
2118 void QPainter::setBrushOrigin(const QPointF &p)
2121 #ifdef QT_DEBUG_DRAW
2122 if (qt_show_painter_debug_output)
2123 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2127 qWarning("QPainter::setBrushOrigin: Painter not active");
2131 d->state->brushOrigin = p;
2134 d->extended->brushOriginChanged();
2138 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2142 \fn void QPainter::setBrushOrigin(const QPoint &position)
2145 Sets the brush's origin to the given \a position.
2149 \fn void QPainter::setBrushOrigin(int x, int y)
2153 Sets the brush's origin to point (\a x, \a y).
2157 \enum QPainter::CompositionMode
2159 Defines the modes supported for digital image compositing.
2160 Composition modes are used to specify how the pixels in one image,
2161 the source, are merged with the pixel in another image, the
2164 Please note that the bitwise raster operation modes, denoted with
2165 a RasterOp prefix, are only natively supported in the X11 and
2166 raster paint engines. This means that the only way to utilize
2167 these modes on the Mac is via a QImage. The RasterOp denoted blend
2168 modes are \e not supported for pens and brushes with alpha
2169 components. Also, turning on the QPainter::Antialiasing render
2170 hint will effectively disable the RasterOp modes.
2173 \image qpainter-compositionmode1.png
2174 \image qpainter-compositionmode2.png
2176 The most common type is SourceOver (often referred to as just
2177 alpha blending) where the source pixel is blended on top of the
2178 destination pixel in such a way that the alpha component of the
2179 source defines the translucency of the pixel.
2181 When the paint device is a QImage, the image format must be set to
2182 \l {QImage::Format}{Format_ARGB32_Premultiplied} or
2183 \l {QImage::Format}{Format_ARGB32} for the composition modes to have
2184 any effect. For performance the premultiplied version is the preferred
2187 When a composition mode is set it applies to all painting
2188 operator, pens, brushes, gradients and pixmap/image drawing.
2190 \value CompositionMode_SourceOver This is the default mode. The
2191 alpha of the source is used to blend the pixel on top of the
2194 \value CompositionMode_DestinationOver The alpha of the
2195 destination is used to blend it on top of the source pixels. This
2196 mode is the inverse of CompositionMode_SourceOver.
2198 \value CompositionMode_Clear The pixels in the destination are
2199 cleared (set to fully transparent) independent of the source.
2201 \value CompositionMode_Source The output is the source
2202 pixel. (This means a basic copy operation and is identical to
2203 SourceOver when the source pixel is opaque).
2205 \value CompositionMode_Destination The output is the destination
2206 pixel. This means that the blending has no effect. This mode is
2207 the inverse of CompositionMode_Source.
2209 \value CompositionMode_SourceIn The output is the source, where
2210 the alpha is reduced by that of the destination.
2212 \value CompositionMode_DestinationIn The output is the
2213 destination, where the alpha is reduced by that of the
2214 source. This mode is the inverse of CompositionMode_SourceIn.
2216 \value CompositionMode_SourceOut The output is the source, where
2217 the alpha is reduced by the inverse of destination.
2219 \value CompositionMode_DestinationOut The output is the
2220 destination, where the alpha is reduced by the inverse of the
2221 source. This mode is the inverse of CompositionMode_SourceOut.
2223 \value CompositionMode_SourceAtop The source pixel is blended on
2224 top of the destination, with the alpha of the source pixel reduced
2225 by the alpha of the destination pixel.
2227 \value CompositionMode_DestinationAtop The destination pixel is
2228 blended on top of the source, with the alpha of the destination
2229 pixel is reduced by the alpha of the destination pixel. This mode
2230 is the inverse of CompositionMode_SourceAtop.
2232 \value CompositionMode_Xor The source, whose alpha is reduced with
2233 the inverse of the destination alpha, is merged with the
2234 destination, whose alpha is reduced by the inverse of the source
2235 alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2237 \value CompositionMode_Plus Both the alpha and color of the source
2238 and destination pixels are added together.
2240 \value CompositionMode_Multiply The output is the source color
2241 multiplied by the destination. Multiplying a color with white
2242 leaves the color unchanged, while multiplying a color
2243 with black produces black.
2245 \value CompositionMode_Screen The source and destination colors
2246 are inverted and then multiplied. Screening a color with white
2247 produces white, whereas screening a color with black leaves the
2250 \value CompositionMode_Overlay Multiplies or screens the colors
2251 depending on the destination color. The destination color is mixed
2252 with the source color to reflect the lightness or darkness of the
2255 \value CompositionMode_Darken The darker of the source and
2256 destination colors is selected.
2258 \value CompositionMode_Lighten The lighter of the source and
2259 destination colors is selected.
2261 \value CompositionMode_ColorDodge The destination color is
2262 brightened to reflect the source color. A black source color
2263 leaves the destination color unchanged.
2265 \value CompositionMode_ColorBurn The destination color is darkened
2266 to reflect the source color. A white source color leaves the
2267 destination color unchanged.
2269 \value CompositionMode_HardLight Multiplies or screens the colors
2270 depending on the source color. A light source color will lighten
2271 the destination color, whereas a dark source color will darken the
2274 \value CompositionMode_SoftLight Darkens or lightens the colors
2275 depending on the source color. Similar to
2276 CompositionMode_HardLight.
2278 \value CompositionMode_Difference Subtracts the darker of the
2279 colors from the lighter. Painting with white inverts the
2280 destination color, whereas painting with black leaves the
2281 destination color unchanged.
2283 \value CompositionMode_Exclusion Similar to
2284 CompositionMode_Difference, but with a lower contrast. Painting
2285 with white inverts the destination color, whereas painting with
2286 black leaves the destination color unchanged.
2288 \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2289 the source and destination pixels (src OR dst).
2291 \value RasterOp_SourceAndDestination Does a bitwise AND operation
2292 on the source and destination pixels (src AND dst).
2294 \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2295 on the source and destination pixels (src XOR dst).
2297 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2298 operation on the source and destination pixels ((NOT src) AND (NOT
2301 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2302 operation on the source and destination pixels ((NOT src) OR (NOT
2305 \value RasterOp_NotSourceXorDestination Does a bitwise operation
2306 where the source pixels are inverted and then XOR'ed with the
2307 destination ((NOT src) XOR dst).
2309 \value RasterOp_NotSource Does a bitwise operation where the
2310 source pixels are inverted (NOT src).
2312 \value RasterOp_NotSourceAndDestination Does a bitwise operation
2313 where the source is inverted and then AND'ed with the destination
2314 ((NOT src) AND dst).
2316 \value RasterOp_SourceAndNotDestination Does a bitwise operation
2317 where the source is AND'ed with the inverted destination pixels
2318 (src AND (NOT dst)).
2320 \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2321 Modes}{Composition Modes}, {Image Composition Example}
2325 Sets the composition mode to the given \a mode.
2327 \warning Only a QPainter operating on a QImage fully supports all
2328 composition modes. The RasterOp modes are supported for X11 as
2329 described in compositionMode().
2331 \sa compositionMode()
2333 void QPainter::setCompositionMode(CompositionMode mode)
2337 qWarning("QPainter::setCompositionMode: Painter not active");
2340 if (d->state->composition_mode == mode)
2343 d->state->composition_mode = mode;
2344 d->extended->compositionModeChanged();
2348 if (mode >= QPainter::RasterOp_SourceOrDestination) {
2349 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2350 qWarning("QPainter::setCompositionMode: "
2351 "Raster operation modes not supported on device");
2354 } else if (mode >= QPainter::CompositionMode_Plus) {
2355 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2356 qWarning("QPainter::setCompositionMode: "
2357 "Blend modes not supported on device");
2360 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2361 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2362 qWarning("QPainter::setCompositionMode: "
2363 "PorterDuff modes not supported on device");
2368 d->state->composition_mode = mode;
2369 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2373 Returns the current composition mode.
2375 \sa CompositionMode, setCompositionMode()
2377 QPainter::CompositionMode QPainter::compositionMode() const
2379 Q_D(const QPainter);
2381 qWarning("QPainter::compositionMode: Painter not active");
2382 return QPainter::CompositionMode_SourceOver;
2384 return d->state->composition_mode;
2388 Returns the current background brush.
2390 \sa setBackground(), {QPainter#Settings}{Settings}
2393 const QBrush &QPainter::background() const
2395 Q_D(const QPainter);
2397 qWarning("QPainter::background: Painter not active");
2398 return d->fakeState()->brush;
2400 return d->state->bgBrush;
2405 Returns true if clipping has been set; otherwise returns false.
2407 \sa setClipping(), {QPainter#Clipping}{Clipping}
2410 bool QPainter::hasClipping() const
2412 Q_D(const QPainter);
2414 qWarning("QPainter::hasClipping: Painter not active");
2417 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2422 Enables clipping if \a enable is true, or disables clipping if \a
2425 \sa hasClipping(), {QPainter#Clipping}{Clipping}
2428 void QPainter::setClipping(bool enable)
2431 #ifdef QT_DEBUG_DRAW
2432 if (qt_show_painter_debug_output)
2433 printf("QPainter::setClipping(), enable=%s, was=%s\n",
2434 enable ? "on" : "off",
2435 hasClipping() ? "on" : "off");
2438 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2442 if (hasClipping() == enable)
2445 // we can't enable clipping if we don't have a clip
2447 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2449 d->state->clipEnabled = enable;
2452 d->extended->clipEnabledChanged();
2456 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2457 d->updateState(d->state);
2462 Returns the currently set clip region. Note that the clip region
2463 is given in logical coordinates.
2465 \warning QPainter does not store the combined clip explicitly as
2466 this is handled by the underlying QPaintEngine, so the path is
2467 recreated on demand and transformed to the current logical
2468 coordinate system. This is potentially an expensive operation.
2470 \sa setClipRegion(), clipPath(), setClipping()
2473 QRegion QPainter::clipRegion() const
2475 Q_D(const QPainter);
2477 qWarning("QPainter::clipRegion: Painter not active");
2482 bool lastWasNothing = true;
2485 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2487 // ### Falcon: Use QPainterPath
2488 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2489 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2490 switch (info.clipType) {
2492 case QPainterClipInfo::RegionClip: {
2493 QTransform matrix = (info.matrix * d->invMatrix);
2494 if (lastWasNothing) {
2495 region = info.region * matrix;
2496 lastWasNothing = false;
2499 if (info.operation == Qt::IntersectClip)
2500 region &= info.region * matrix;
2501 else if (info.operation == Qt::NoClip) {
2502 lastWasNothing = true;
2505 region = info.region * matrix;
2509 case QPainterClipInfo::PathClip: {
2510 QTransform matrix = (info.matrix * d->invMatrix);
2511 if (lastWasNothing) {
2512 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2513 info.path.fillRule());
2514 lastWasNothing = false;
2517 if (info.operation == Qt::IntersectClip) {
2518 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2519 info.path.fillRule());
2520 } else if (info.operation == Qt::NoClip) {
2521 lastWasNothing = true;
2524 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2525 info.path.fillRule());
2530 case QPainterClipInfo::RectClip: {
2531 QTransform matrix = (info.matrix * d->invMatrix);
2532 if (lastWasNothing) {
2533 region = QRegion(info.rect) * matrix;
2534 lastWasNothing = false;
2537 if (info.operation == Qt::IntersectClip) {
2538 // Use rect intersection if possible.
2539 if (matrix.type() <= QTransform::TxScale)
2540 region &= matrix.mapRect(info.rect);
2542 region &= matrix.map(QRegion(info.rect));
2543 } else if (info.operation == Qt::NoClip) {
2544 lastWasNothing = true;
2547 region = QRegion(info.rect) * matrix;
2552 case QPainterClipInfo::RectFClip: {
2553 QTransform matrix = (info.matrix * d->invMatrix);
2554 if (lastWasNothing) {
2555 region = QRegion(info.rectf.toRect()) * matrix;
2556 lastWasNothing = false;
2559 if (info.operation == Qt::IntersectClip) {
2560 // Use rect intersection if possible.
2561 if (matrix.type() <= QTransform::TxScale)
2562 region &= matrix.mapRect(info.rectf.toRect());
2564 region &= matrix.map(QRegion(info.rectf.toRect()));
2565 } else if (info.operation == Qt::NoClip) {
2566 lastWasNothing = true;
2569 region = QRegion(info.rectf.toRect()) * matrix;
2579 extern QPainterPath qt_regionToPath(const QRegion ®ion);
2582 Returns the currently clip as a path. Note that the clip path is
2583 given in logical coordinates.
2585 \warning QPainter does not store the combined clip explicitly as
2586 this is handled by the underlying QPaintEngine, so the path is
2587 recreated on demand and transformed to the current logical
2588 coordinate system. This is potentially an expensive operation.
2590 \sa setClipPath(), clipRegion(), setClipping()
2592 QPainterPath QPainter::clipPath() const
2594 Q_D(const QPainter);
2596 // ### Since we do not support path intersections and path unions yet,
2597 // we just use clipRegion() here...
2599 qWarning("QPainter::clipPath: Painter not active");
2600 return QPainterPath();
2603 // No clip, return empty
2604 if (d->state->clipInfo.size() == 0) {
2605 return QPainterPath();
2608 // Update inverse matrix, used below.
2610 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2612 // For the simple case avoid conversion.
2613 if (d->state->clipInfo.size() == 1
2614 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2615 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2616 return d->state->clipInfo.at(0).path * matrix;
2618 } else if (d->state->clipInfo.size() == 1
2619 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2620 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2622 path.addRect(d->state->clipInfo.at(0).rect);
2623 return path * matrix;
2625 // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2626 return qt_regionToPath(clipRegion());
2632 Returns the bounding rectangle of the current clip if there is a clip;
2633 otherwise returns an empty rectangle. Note that the clip region is
2634 given in logical coordinates.
2636 The bounding rectangle is not guaranteed to be tight.
2638 \sa setClipRect(), setClipPath(), setClipRegion()
2643 QRectF QPainter::clipBoundingRect() const
2645 Q_D(const QPainter);
2648 qWarning("QPainter::clipBoundingRect: Painter not active");
2652 // Accumulate the bounding box in device space. This is not 100%
2653 // precise, but it fits within the guarantee and it is reasonably
2656 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2658 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2660 if (info.clipType == QPainterClipInfo::RectClip)
2662 else if (info.clipType == QPainterClipInfo::RectFClip)
2664 else if (info.clipType == QPainterClipInfo::RegionClip)
2665 r = info.region.boundingRect();
2667 r = info.path.boundingRect();
2669 r = info.matrix.mapRect(r);
2673 else if (info.operation == Qt::IntersectClip)
2678 // Map the rectangle back into logical space using the inverse
2681 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2683 return d->invMatrix.mapRect(bounds);
2687 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2689 Enables clipping, and sets the clip region to the given \a
2690 rectangle using the given clip \a operation. The default operation
2691 is to replace the current clip rectangle.
2693 Note that the clip rectangle is specified in logical (painter)
2696 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2698 void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2703 if ((!d->state->clipEnabled && op != Qt::NoClip))
2704 op = Qt::ReplaceClip;
2707 qWarning("QPainter::setClipRect: Painter not active");
2710 qreal right = rect.x() + rect.width();
2711 qreal bottom = rect.y() + rect.height();
2712 qreal pts[] = { rect.x(), rect.y(),
2716 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2717 d->state->clipEnabled = true;
2718 d->extended->clip(vp, op);
2719 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2720 d->state->clipInfo.clear();
2721 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2722 d->state->clipOperation = op;
2726 if (qreal(int(rect.top())) == rect.top()
2727 && qreal(int(rect.bottom())) == rect.bottom()
2728 && qreal(int(rect.left())) == rect.left()
2729 && qreal(int(rect.right())) == rect.right())
2731 setClipRect(rect.toRect(), op);
2735 if (rect.isEmpty()) {
2736 setClipRegion(QRegion(), op);
2742 setClipPath(path, op);
2746 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2749 Enables clipping, and sets the clip region to the given \a rectangle using the given
2752 void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2757 qWarning("QPainter::setClipRect: Painter not active");
2761 if ((!d->state->clipEnabled && op != Qt::NoClip))
2762 op = Qt::ReplaceClip;
2765 d->state->clipEnabled = true;
2766 d->extended->clip(rect, op);
2767 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2768 d->state->clipInfo.clear();
2769 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2770 d->state->clipOperation = op;
2774 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2775 op = Qt::ReplaceClip;
2777 d->state->clipRegion = rect;
2778 d->state->clipOperation = op;
2779 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2780 d->state->clipInfo.clear();
2781 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2782 d->state->clipEnabled = true;
2783 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2784 d->updateState(d->state);
2788 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2790 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2791 with the given \a width and \a height.
2795 \fn void QPainter::setClipRegion(const QRegion ®ion, Qt::ClipOperation operation)
2797 Sets the clip region to the given \a region using the specified clip
2798 \a operation. The default clip operation is to replace the current
2801 Note that the clip region is given in logical coordinates.
2803 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2805 void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2808 #ifdef QT_DEBUG_DRAW
2809 QRect rect = r.boundingRect();
2810 if (qt_show_painter_debug_output)
2811 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2812 r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2815 qWarning("QPainter::setClipRegion: Painter not active");
2819 if ((!d->state->clipEnabled && op != Qt::NoClip))
2820 op = Qt::ReplaceClip;
2823 d->state->clipEnabled = true;
2824 d->extended->clip(r, op);
2825 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2826 d->state->clipInfo.clear();
2827 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2828 d->state->clipOperation = op;
2832 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2833 op = Qt::ReplaceClip;
2835 d->state->clipRegion = r;
2836 d->state->clipOperation = op;
2837 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2838 d->state->clipInfo.clear();
2839 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2840 d->state->clipEnabled = true;
2841 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2842 d->updateState(d->state);
2849 Sets the transformation matrix to \a matrix and enables transformations.
2851 \note It is advisable to use setWorldTransform() instead of this function to
2852 preserve the properties of perspective transformations.
2854 If \a combine is true, then \a matrix is combined with the current
2855 transformation matrix; otherwise \a matrix replaces the current
2856 transformation matrix.
2858 If \a matrix is the identity matrix and \a combine is false, this
2859 function calls setWorldMatrixEnabled(false). (The identity matrix is the
2860 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2863 The following functions can transform the coordinate system without using
2872 They operate on the painter's worldMatrix() and are implemented like this:
2874 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 4
2876 Note that when using setWorldMatrix() function you should always have
2877 \a combine be true when you are drawing into a QPicture. Otherwise
2878 it may not be possible to replay the picture with additional
2879 transformations; using the translate(), scale(), etc. convenience
2882 For more information about the coordinate system, transformations
2883 and window-viewport conversion, see \l {Coordinate System}.
2885 \sa setWorldTransform(), QTransform
2888 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2890 setWorldTransform(QTransform(matrix), combine);
2897 Returns the world transformation matrix.
2899 It is advisable to use worldTransform() because worldMatrix() does not
2900 preserve the properties of perspective transformations.
2902 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2906 const QMatrix &QPainter::worldMatrix() const
2908 Q_D(const QPainter);
2910 qWarning("QPainter::worldMatrix: Painter not active");
2911 return d->fakeState()->transform.toAffine();
2913 return d->state->worldMatrix.toAffine();
2919 Use setWorldTransform() instead.
2921 \sa setWorldTransform()
2924 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
2926 setWorldTransform(QTransform(matrix), combine);
2932 Use worldTransform() instead.
2934 \sa worldTransform()
2937 const QMatrix &QPainter::matrix() const
2939 return worldMatrix();
2947 Returns the transformation matrix combining the current
2948 window/viewport and world transformation.
2950 It is advisable to use combinedTransform() instead of this
2951 function to preserve the properties of perspective transformations.
2953 \sa setWorldTransform(), setWindow(), setViewport()
2955 QMatrix QPainter::combinedMatrix() const
2957 return combinedTransform().toAffine();
2964 Returns the matrix that transforms from logical coordinates to
2965 device coordinates of the platform dependent paint device.
2967 \note It is advisable to use deviceTransform() instead of this
2968 function to preserve the properties of perspective transformations.
2970 This function is \e only needed when using platform painting
2971 commands on the platform dependent handle (Qt::HANDLE), and the
2972 platform does not do transformations nativly.
2974 The QPaintEngine::PaintEngineFeature enum can be queried to
2975 determine whether the platform performs the transformations or
2978 \sa worldMatrix(), QPaintEngine::hasFeature(),
2980 const QMatrix &QPainter::deviceMatrix() const
2982 Q_D(const QPainter);
2984 qWarning("QPainter::deviceMatrix: Painter not active");
2985 return d->fakeState()->transform.toAffine();
2987 return d->state->matrix.toAffine();
2993 Resets any transformations that were made using translate(), scale(),
2994 shear(), rotate(), setWorldMatrix(), setViewport() and
2997 It is advisable to use resetTransform() instead of this function
2998 to preserve the properties of perspective transformations.
3000 \sa {QPainter#Coordinate Transformations}{Coordinate
3004 void QPainter::resetMatrix()
3013 Enables transformations if \a enable is true, or disables
3014 transformations if \a enable is false. The world transformation
3015 matrix is not changed.
3017 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3018 Transformations}{Coordinate Transformations}
3021 void QPainter::setWorldMatrixEnabled(bool enable)
3024 #ifdef QT_DEBUG_DRAW
3025 if (qt_show_painter_debug_output)
3026 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3030 qWarning("QPainter::setMatrixEnabled: Painter not active");
3033 if (enable == d->state->WxF)
3036 d->state->WxF = enable;
3043 Returns true if world transformation is enabled; otherwise returns
3046 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3049 bool QPainter::worldMatrixEnabled() const
3051 Q_D(const QPainter);
3053 qWarning("QPainter::worldMatrixEnabled: Painter not active");
3056 return d->state->WxF;
3062 Use setWorldMatrixEnabled() instead.
3064 \sa setWorldMatrixEnabled()
3067 void QPainter::setMatrixEnabled(bool enable)
3069 setWorldMatrixEnabled(enable);
3075 Use worldMatrixEnabled() instead
3077 \sa worldMatrixEnabled()
3080 bool QPainter::matrixEnabled() const
3082 return worldMatrixEnabled();
3086 Scales the coordinate system by (\a{sx}, \a{sy}).
3088 \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate
3092 void QPainter::scale(qreal sx, qreal sy)
3094 #ifdef QT_DEBUG_DRAW
3095 if (qt_show_painter_debug_output)
3096 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3100 qWarning("QPainter::scale: Painter not active");
3104 d->state->worldMatrix.scale(sx,sy);
3105 d->state->WxF = true;
3110 Shears the coordinate system by (\a{sh}, \a{sv}).
3112 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3116 void QPainter::shear(qreal sh, qreal sv)
3118 #ifdef QT_DEBUG_DRAW
3119 if (qt_show_painter_debug_output)
3120 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3124 qWarning("QPainter::shear: Painter not active");
3128 d->state->worldMatrix.shear(sh, sv);
3129 d->state->WxF = true;
3134 \fn void QPainter::rotate(qreal angle)
3136 Rotates the coordinate system the given \a angle clockwise.
3138 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3142 void QPainter::rotate(qreal a)
3144 #ifdef QT_DEBUG_DRAW
3145 if (qt_show_painter_debug_output)
3146 printf("QPainter::rotate(), angle=%f\n", a);
3150 qWarning("QPainter::rotate: Painter not active");
3154 d->state->worldMatrix.rotate(a);
3155 d->state->WxF = true;
3160 Translates the coordinate system by the given \a offset; i.e. the
3161 given \a offset is added to points.
3163 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3166 void QPainter::translate(const QPointF &offset)
3168 qreal dx = offset.x();
3169 qreal dy = offset.y();
3170 #ifdef QT_DEBUG_DRAW
3171 if (qt_show_painter_debug_output)
3172 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3176 qWarning("QPainter::translate: Painter not active");
3180 d->state->worldMatrix.translate(dx, dy);
3181 d->state->WxF = true;
3186 \fn void QPainter::translate(const QPoint &offset)
3189 Translates the coordinate system by the given \a offset.
3193 \fn void QPainter::translate(qreal dx, qreal dy)
3196 Translates the coordinate system by the vector (\a dx, \a dy).
3200 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3202 Enables clipping, and sets the clip path for the painter to the
3203 given \a path, with the clip \a operation.
3205 Note that the clip path is specified in logical (painter)
3208 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3211 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3213 #ifdef QT_DEBUG_DRAW
3214 if (qt_show_painter_debug_output) {
3215 QRectF b = path.boundingRect();
3216 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3217 path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3223 qWarning("QPainter::setClipPath: Painter not active");
3227 if ((!d->state->clipEnabled && op != Qt::NoClip))
3228 op = Qt::ReplaceClip;
3231 d->state->clipEnabled = true;
3232 d->extended->clip(path, op);
3233 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3234 d->state->clipInfo.clear();
3235 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3236 d->state->clipOperation = op;
3240 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
3241 op = Qt::ReplaceClip;
3243 d->state->clipPath = path;
3244 d->state->clipOperation = op;
3245 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3246 d->state->clipInfo.clear();
3247 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3248 d->state->clipEnabled = true;
3249 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3250 d->updateState(d->state);
3254 Draws the outline (strokes) the path \a path with the pen specified
3257 \sa fillPath(), {QPainter#Drawing}{Drawing}
3259 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3264 qWarning("QPainter::strokePath: Painter not active");
3272 const QGradient *g = qpen_brush(pen).gradient();
3273 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3274 d->extended->stroke(qtVectorPathForPath(path), pen);
3279 QBrush oldBrush = d->state->brush;
3280 QPen oldPen = d->state->pen;
3283 setBrush(Qt::NoBrush);
3293 Fills the given \a path using the given \a brush. The outline is
3296 Alternatively, you can specify a QColor instead of a QBrush; the
3297 QBrush constructor (taking a QColor argument) will automatically
3298 create a solid pattern brush.
3302 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3307 qWarning("QPainter::fillPath: Painter not active");
3315 const QGradient *g = brush.gradient();
3316 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3317 d->extended->fill(qtVectorPathForPath(path), brush);
3322 QBrush oldBrush = d->state->brush;
3323 QPen oldPen = d->state->pen;
3336 Draws the given painter \a path using the current pen for outline
3337 and the current brush for filling.
3341 \li \inlineimage qpainter-path.png
3343 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 5
3346 \sa {painting/painterpaths}{the Painter Paths
3347 example},{painting/deform}{the Vector Deformation example}
3349 void QPainter::drawPath(const QPainterPath &path)
3351 #ifdef QT_DEBUG_DRAW
3352 QRectF pathBounds = path.boundingRect();
3353 if (qt_show_painter_debug_output)
3354 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3355 path.elementCount(),
3356 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3362 qWarning("QPainter::drawPath: Painter not active");
3367 d->extended->drawPath(path);
3370 d->updateState(d->state);
3372 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3373 d->engine->drawPath(path);
3375 d->draw_helper(path);
3380 \fn void QPainter::drawLine(const QLineF &line)
3382 Draws a line defined by \a line.
3386 \li \inlineimage qpainter-line.png
3388 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 6
3391 \sa drawLines(), drawPolyline(), {Coordinate System}
3395 \fn void QPainter::drawLine(const QLine &line)
3398 Draws a line defined by \a line.
3402 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3405 Draws a line from \a p1 to \a p2.
3409 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3412 Draws a line from \a p1 to \a p2.
3416 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3419 Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3420 current pen position to (\a x2, \a y2).
3424 \fn void QPainter::drawRect(const QRectF &rectangle)
3426 Draws the current \a rectangle with the current pen and brush.
3428 A filled rectangle has a size of \a{rectangle}.size(). A stroked
3429 rectangle has a size of \a{rectangle}.size() plus the pen width.
3433 \li \inlineimage qpainter-rectangle.png
3435 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 7
3438 \sa drawRects(), drawPolygon(), {Coordinate System}
3442 \fn void QPainter::drawRect(const QRect &rectangle)
3446 Draws the current \a rectangle with the current pen and brush.
3450 \fn void QPainter::drawRect(int x, int y, int width, int height)
3454 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3455 with the given \a width and \a height.
3459 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3461 Draws the first \a rectCount of the given \a rectangles using the
3462 current pen and brush.
3466 void QPainter::drawRects(const QRectF *rects, int rectCount)
3468 #ifdef QT_DEBUG_DRAW
3469 if (qt_show_painter_debug_output)
3470 printf("QPainter::drawRects(), count=%d\n", rectCount);
3475 qWarning("QPainter::drawRects: Painter not active");
3483 d->extended->drawRects(rects, rectCount);
3487 d->updateState(d->state);
3489 if (!d->state->emulationSpecifier) {
3490 d->engine->drawRects(rects, rectCount);
3494 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3495 && d->state->matrix.type() == QTransform::TxTranslate) {
3496 for (int i=0; i<rectCount; ++i) {
3497 QRectF r(rects[i].x() + d->state->matrix.dx(),
3498 rects[i].y() + d->state->matrix.dy(),
3501 d->engine->drawRects(&r, 1);
3504 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3505 for (int i=0; i<rectCount; ++i) {
3506 QPainterPath rectPath;
3507 rectPath.addRect(rects[i]);
3508 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3511 QPainterPath rectPath;
3512 for (int i=0; i<rectCount; ++i)
3513 rectPath.addRect(rects[i]);
3514 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3520 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3523 Draws the first \a rectCount of the given \a rectangles using the
3524 current pen and brush.
3526 void QPainter::drawRects(const QRect *rects, int rectCount)
3528 #ifdef QT_DEBUG_DRAW
3529 if (qt_show_painter_debug_output)
3530 printf("QPainter::drawRects(), count=%d\n", rectCount);
3535 qWarning("QPainter::drawRects: Painter not active");
3543 d->extended->drawRects(rects, rectCount);
3547 d->updateState(d->state);
3549 if (!d->state->emulationSpecifier) {
3550 d->engine->drawRects(rects, rectCount);
3554 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3555 && d->state->matrix.type() == QTransform::TxTranslate) {
3556 for (int i=0; i<rectCount; ++i) {
3557 QRectF r(rects[i].x() + d->state->matrix.dx(),
3558 rects[i].y() + d->state->matrix.dy(),
3562 d->engine->drawRects(&r, 1);
3565 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3566 for (int i=0; i<rectCount; ++i) {
3567 QPainterPath rectPath;
3568 rectPath.addRect(rects[i]);
3569 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3572 QPainterPath rectPath;
3573 for (int i=0; i<rectCount; ++i)
3574 rectPath.addRect(rects[i]);
3576 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3582 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3585 Draws the given \a rectangles using the current pen and brush.
3589 \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3593 Draws the given \a rectangles using the current pen and brush.
3597 \fn void QPainter::drawPoint(const QPointF &position)
3599 Draws a single point at the given \a position using the current
3602 \sa {Coordinate System}
3606 \fn void QPainter::drawPoint(const QPoint &position)
3609 Draws a single point at the given \a position using the current
3613 /*! \fn void QPainter::drawPoint(int x, int y)
3617 Draws a single point at position (\a x, \a y).
3621 Draws the first \a pointCount points in the array \a points using
3622 the current pen's color.
3624 \sa {Coordinate System}
3626 void QPainter::drawPoints(const QPointF *points, int pointCount)
3628 #ifdef QT_DEBUG_DRAW
3629 if (qt_show_painter_debug_output)
3630 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3635 qWarning("QPainter::drawPoints: Painter not active");
3639 if (pointCount <= 0)
3643 d->extended->drawPoints(points, pointCount);
3647 d->updateState(d->state);
3649 if (!d->state->emulationSpecifier) {
3650 d->engine->drawPoints(points, pointCount);
3654 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3655 && d->state->matrix.type() == QTransform::TxTranslate) {
3656 // ### use drawPoints function
3657 for (int i=0; i<pointCount; ++i) {
3658 QPointF pt(points[i].x() + d->state->matrix.dx(),
3659 points[i].y() + d->state->matrix.dy());
3660 d->engine->drawPoints(&pt, 1);
3663 QPen pen = d->state->pen;
3664 bool flat_pen = pen.capStyle() == Qt::FlatCap;
3667 pen.setCapStyle(Qt::SquareCap);
3671 for (int i=0; i<pointCount; ++i) {
3672 path.moveTo(points[i].x(), points[i].y());
3673 path.lineTo(points[i].x() + 0.0001, points[i].y());
3675 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3684 Draws the first \a pointCount points in the array \a points using
3685 the current pen's color.
3688 void QPainter::drawPoints(const QPoint *points, int pointCount)
3690 #ifdef QT_DEBUG_DRAW
3691 if (qt_show_painter_debug_output)
3692 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3697 qWarning("QPainter::drawPoints: Painter not active");
3701 if (pointCount <= 0)
3705 d->extended->drawPoints(points, pointCount);
3709 d->updateState(d->state);
3711 if (!d->state->emulationSpecifier) {
3712 d->engine->drawPoints(points, pointCount);
3716 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3717 && d->state->matrix.type() == QTransform::TxTranslate) {
3718 // ### use drawPoints function
3719 for (int i=0; i<pointCount; ++i) {
3720 QPointF pt(points[i].x() + d->state->matrix.dx(),
3721 points[i].y() + d->state->matrix.dy());
3722 d->engine->drawPoints(&pt, 1);
3725 QPen pen = d->state->pen;
3726 bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3729 pen.setCapStyle(Qt::SquareCap);
3733 for (int i=0; i<pointCount; ++i) {
3734 path.moveTo(points[i].x(), points[i].y());
3735 path.lineTo(points[i].x() + 0.0001, points[i].y());
3737 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3744 \fn void QPainter::drawPoints(const QPolygonF &points)
3748 Draws the points in the vector \a points.
3752 \fn void QPainter::drawPoints(const QPolygon &points)
3756 Draws the points in the vector \a points.
3760 Sets the background mode of the painter to the given \a mode
3762 Qt::TransparentMode (the default) draws stippled lines and text
3763 without setting the background pixels. Qt::OpaqueMode fills these
3764 space with the current background color.
3766 Note that in order to draw a bitmap or pixmap transparently, you
3767 must use QPixmap::setMask().
3769 \sa backgroundMode(), setBackground(),
3770 {QPainter#Settings}{Settings}
3773 void QPainter::setBackgroundMode(Qt::BGMode mode)
3775 #ifdef QT_DEBUG_DRAW
3776 if (qt_show_painter_debug_output)
3777 printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3782 qWarning("QPainter::setBackgroundMode: Painter not active");
3785 if (d->state->bgMode == mode)
3788 d->state->bgMode = mode;
3790 d->checkEmulation();
3792 d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3797 Returns the current background mode.
3799 \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3801 Qt::BGMode QPainter::backgroundMode() const
3803 Q_D(const QPainter);
3805 qWarning("QPainter::backgroundMode: Painter not active");
3806 return Qt::TransparentMode;
3808 return d->state->bgMode;
3815 Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3819 void QPainter::setPen(const QColor &color)
3821 #ifdef QT_DEBUG_DRAW
3822 if (qt_show_painter_debug_output)
3823 printf("QPainter::setPen(), color=%04x\n", color.rgb());
3827 qWarning("QPainter::setPen: Painter not active");
3831 if (d->state->pen.style() == Qt::SolidLine
3832 && d->state->pen.widthF() == 0
3833 && d->state->pen.isSolid()
3834 && d->state->pen.color() == color)
3837 QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
3839 d->state->pen = pen;
3841 d->extended->penChanged();
3843 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3847 Sets the painter's pen to be the given \a pen.
3849 The \a pen defines how to draw lines and outlines, and it also
3850 defines the text color.
3852 \sa pen(), {QPainter#Settings}{Settings}
3855 void QPainter::setPen(const QPen &pen)
3858 #ifdef QT_DEBUG_DRAW
3859 if (qt_show_painter_debug_output)
3860 printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3861 pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3865 qWarning("QPainter::setPen: Painter not active");
3869 if (d->state->pen == pen)
3872 d->state->pen = pen;
3875 d->checkEmulation();
3876 d->extended->penChanged();
3880 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3886 Sets the painter's pen to have the given \a style, width 0 and
3890 void QPainter::setPen(Qt::PenStyle style)
3894 qWarning("QPainter::setPen: Painter not active");
3898 if (d->state->pen.style() == style
3899 && (style == Qt::NoPen || (d->state->pen.widthF() == 0
3900 && d->state->pen.isSolid()
3901 && d->state->pen.color() == QColor(Qt::black))))
3904 // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
3905 // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
3906 d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
3909 d->extended->penChanged();
3911 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3916 Returns the painter's current pen.
3918 \sa setPen(), {QPainter#Settings}{Settings}
3921 const QPen &QPainter::pen() const
3923 Q_D(const QPainter);
3925 qWarning("QPainter::pen: Painter not active");
3926 return d->fakeState()->pen;
3928 return d->state->pen;
3933 Sets the painter's brush to the given \a brush.
3935 The painter's brush defines how shapes are filled.
3937 \sa brush(), {QPainter#Settings}{Settings}
3940 void QPainter::setBrush(const QBrush &brush)
3942 #ifdef QT_DEBUG_DRAW
3943 if (qt_show_painter_debug_output)
3944 printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
3948 qWarning("QPainter::setBrush: Painter not active");
3952 if (d->state->brush.d == brush.d)
3956 d->state->brush = brush;
3957 d->checkEmulation();
3958 d->extended->brushChanged();
3962 d->state->brush = brush;
3963 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
3970 Sets the painter's brush to black color and the specified \a
3974 void QPainter::setBrush(Qt::BrushStyle style)
3978 qWarning("QPainter::setBrush: Painter not active");
3981 if (d->state->brush.style() == style &&
3982 (style == Qt::NoBrush
3983 || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
3985 d->state->brush = QBrush(Qt::black, style);
3987 d->extended->brushChanged();
3989 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
3993 Returns the painter's current brush.
3995 \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
3998 const QBrush &QPainter::brush() const
4000 Q_D(const QPainter);
4002 qWarning("QPainter::brush: Painter not active");
4003 return d->fakeState()->brush;
4005 return d->state->brush;
4009 \fn void QPainter::setBackground(const QBrush &brush)
4011 Sets the background brush of the painter to the given \a brush.
4013 The background brush is the brush that is filled in when drawing
4014 opaque text, stippled lines and bitmaps. The background brush has
4015 no effect in transparent background mode (which is the default).
4017 \sa background(), setBackgroundMode(),
4018 {QPainter#Settings}{Settings}
4021 void QPainter::setBackground(const QBrush &bg)
4023 #ifdef QT_DEBUG_DRAW
4024 if (qt_show_painter_debug_output)
4025 printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4030 qWarning("QPainter::setBackground: Painter not active");
4033 d->state->bgBrush = bg;
4035 d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4039 Sets the painter's font to the given \a font.
4041 This font is used by subsequent drawText() functions. The text
4042 color is the same as the pen color.
4044 If you set a font that isn't available, Qt finds a close match.
4045 font() will return what you set using setFont() and fontInfo() returns the
4046 font actually being used (which may be the same).
4048 \sa font(), drawText(), {QPainter#Settings}{Settings}
4051 void QPainter::setFont(const QFont &font)
4055 #ifdef QT_DEBUG_DRAW
4056 if (qt_show_painter_debug_output)
4057 printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4061 qWarning("QPainter::setFont: Painter not active");
4065 d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4067 d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4071 Returns the currently set font used for drawing text.
4073 \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4075 const QFont &QPainter::font() const
4077 Q_D(const QPainter);
4079 qWarning("QPainter::font: Painter not active");
4080 return d->fakeState()->font;
4082 return d->state->font;
4088 Draws the given rectangle \a rect with rounded corners.
4090 The \a xRadius and \a yRadius arguments specify the radii
4091 of the ellipses defining the corners of the rounded rectangle.
4092 When \a mode is Qt::RelativeSize, \a xRadius and
4093 \a yRadius are specified in percentage of half the rectangle's
4094 width and height respectively, and should be in the range
4097 A filled rectangle has a size of rect.size(). A stroked rectangle
4098 has a size of rect.size() plus the pen width.
4102 \li \inlineimage qpainter-roundrect.png
4104 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 8
4107 \sa drawRect(), QPen
4109 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4111 #ifdef QT_DEBUG_DRAW
4112 if (qt_show_painter_debug_output)
4113 printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4120 if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
4126 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4131 path.addRoundedRect(rect, xRadius, yRadius, mode);
4136 \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4137 Qt::SizeMode mode = Qt::AbsoluteSize);
4141 Draws the given rectangle \a rect with rounded corners.
4145 \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4146 Qt::SizeMode mode = Qt::AbsoluteSize);
4150 Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4156 Draws a rectangle \a r with rounded corners.
4158 The \a xRnd and \a yRnd arguments specify how rounded the corners
4159 should be. 0 is angled corners, 99 is maximum roundedness.
4161 A filled rectangle has a size of r.size(). A stroked rectangle
4162 has a size of r.size() plus the pen width.
4164 \sa drawRoundedRect()
4166 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4168 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4173 \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4178 Draws the rectangle \a r with rounded corners.
4184 \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4188 Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4192 \fn void QPainter::drawEllipse(const QRectF &rectangle)
4194 Draws the ellipse defined by the given \a rectangle.
4196 A filled ellipse has a size of \a{rectangle}.\l
4197 {QRect::size()}{size()}. A stroked ellipse has a size of
4198 \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4202 \li \inlineimage qpainter-ellipse.png
4204 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 9
4207 \sa drawPie(), {Coordinate System}
4209 void QPainter::drawEllipse(const QRectF &r)
4211 #ifdef QT_DEBUG_DRAW
4212 if (qt_show_painter_debug_output)
4213 printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4220 QRectF rect(r.normalized());
4223 d->extended->drawEllipse(rect);
4227 d->updateState(d->state);
4228 if (d->state->emulationSpecifier) {
4229 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4230 && d->state->matrix.type() == QTransform::TxTranslate) {
4231 rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4234 path.addEllipse(rect);
4235 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4240 d->engine->drawEllipse(rect);
4244 \fn QPainter::drawEllipse(const QRect &rectangle)
4248 Draws the ellipse defined by the given \a rectangle.
4250 void QPainter::drawEllipse(const QRect &r)
4252 #ifdef QT_DEBUG_DRAW
4253 if (qt_show_painter_debug_output)
4254 printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4261 QRect rect(r.normalized());
4264 d->extended->drawEllipse(rect);
4268 d->updateState(d->state);
4270 if (d->state->emulationSpecifier) {
4271 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4272 && d->state->matrix.type() == QTransform::TxTranslate) {
4273 rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4276 path.addEllipse(rect);
4277 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4282 d->engine->drawEllipse(rect);
4286 \fn QPainter::drawEllipse(int x, int y, int width, int height)
4290 Draws the ellipse defined by the rectangle beginning at (\a{x},
4291 \a{y}) with the given \a width and \a height.
4297 \fn QPainter::drawEllipse(const QPointF ¢er, qreal rx, qreal ry)
4301 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4307 \fn QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)
4311 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4315 \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4317 Draws the arc defined by the given \a rectangle, \a startAngle and
4320 The \a startAngle and \a spanAngle must be specified in 1/16th of
4321 a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4322 values for the angles mean counter-clockwise while negative values
4323 mean the clockwise direction. Zero degrees is at the 3 o'clock
4328 \li \inlineimage qpainter-arc.png
4330 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 10
4333 \sa drawPie(), drawChord(), {Coordinate System}
4336 void QPainter::drawArc(const QRectF &r, int a, int alen)
4338 #ifdef QT_DEBUG_DRAW
4339 if (qt_show_painter_debug_output)
4340 printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4341 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4348 QRectF rect = r.normalized();
4351 path.arcMoveTo(rect, a/16.0);
4352 path.arcTo(rect, a/16.0, alen/16.0);
4353 strokePath(path, d->state->pen);
4356 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4361 Draws the arc defined by the given \a rectangle, \a startAngle and
4366 \fn void QPainter::drawArc(int x, int y, int width, int height,
4367 int startAngle, int spanAngle)
4371 Draws the arc defined by the rectangle beginning at (\a x, \a y)
4372 with the specified \a width and \a height, and the given \a
4373 startAngle and \a spanAngle.
4377 \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4379 Draws a pie defined by the given \a rectangle, \a startAngle and
4382 The pie is filled with the current brush().
4384 The startAngle and spanAngle must be specified in 1/16th of a
4385 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4386 for the angles mean counter-clockwise while negative values mean
4387 the clockwise direction. Zero degrees is at the 3 o'clock
4392 \li \inlineimage qpainter-pie.png
4394 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 11
4397 \sa drawEllipse(), drawChord(), {Coordinate System}
4399 void QPainter::drawPie(const QRectF &r, int a, int alen)
4401 #ifdef QT_DEBUG_DRAW
4402 if (qt_show_painter_debug_output)
4403 printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4404 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4415 if (a < 0) a += (360*16);
4418 QRectF rect = r.normalized();
4421 path.moveTo(rect.center());
4422 path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4423 path.closeSubpath();
4429 \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4432 Draws a pie defined by the given \a rectangle, \a startAngle and
4437 \fn void QPainter::drawPie(int x, int y, int width, int height, int
4438 startAngle, int spanAngle)
4442 Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4443 the specified \a width and \a height, and the given \a startAngle and
4448 \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4450 Draws the chord defined by the given \a rectangle, \a startAngle and
4451 \a spanAngle. The chord is filled with the current brush().
4453 The startAngle and spanAngle must be specified in 1/16th of a
4454 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4455 for the angles mean counter-clockwise while negative values mean
4456 the clockwise direction. Zero degrees is at the 3 o'clock
4461 \li \inlineimage qpainter-chord.png
4463 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 12
4466 \sa drawArc(), drawPie(), {Coordinate System}
4468 void QPainter::drawChord(const QRectF &r, int a, int alen)
4470 #ifdef QT_DEBUG_DRAW
4471 if (qt_show_painter_debug_output)
4472 printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4473 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4480 QRectF rect = r.normalized();
4483 path.arcMoveTo(rect, a/16.0);
4484 path.arcTo(rect, a/16.0, alen/16.0);
4485 path.closeSubpath();
4489 \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4493 Draws the chord defined by the given \a rectangle, \a startAngle and
4498 \fn void QPainter::drawChord(int x, int y, int width, int height, int
4499 startAngle, int spanAngle)
4503 Draws the chord defined by the rectangle beginning at (\a x, \a y)
4504 with the specified \a width and \a height, and the given \a
4505 startAngle and \a spanAngle.
4510 Draws the first \a lineCount lines in the array \a lines
4511 using the current pen.
4513 \sa drawLine(), drawPolyline()
4515 void QPainter::drawLines(const QLineF *lines, int lineCount)
4517 #ifdef QT_DEBUG_DRAW
4518 if (qt_show_painter_debug_output)
4519 printf("QPainter::drawLines(), line count=%d\n", lineCount);
4524 if (!d->engine || lineCount < 1)
4528 d->extended->drawLines(lines, lineCount);
4532 d->updateState(d->state);
4534 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4536 if (lineEmulation) {
4537 if (lineEmulation == QPaintEngine::PrimitiveTransform
4538 && d->state->matrix.type() == QTransform::TxTranslate) {
4539 for (int i = 0; i < lineCount; ++i) {
4540 QLineF line = lines[i];
4541 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4542 d->engine->drawLines(&line, 1);
4545 QPainterPath linePath;
4546 for (int i = 0; i < lineCount; ++i) {
4547 linePath.moveTo(lines[i].p1());
4548 linePath.lineTo(lines[i].p2());
4550 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4554 d->engine->drawLines(lines, lineCount);
4558 \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4561 Draws the first \a lineCount lines in the array \a lines
4562 using the current pen.
4564 void QPainter::drawLines(const QLine *lines, int lineCount)
4566 #ifdef QT_DEBUG_DRAW
4567 if (qt_show_painter_debug_output)
4568 printf("QPainter::drawLine(), line count=%d\n", lineCount);
4573 if (!d->engine || lineCount < 1)
4577 d->extended->drawLines(lines, lineCount);
4581 d->updateState(d->state);
4583 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4585 if (lineEmulation) {
4586 if (lineEmulation == QPaintEngine::PrimitiveTransform
4587 && d->state->matrix.type() == QTransform::TxTranslate) {
4588 for (int i = 0; i < lineCount; ++i) {
4589 QLineF line = lines[i];
4590 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4591 d->engine->drawLines(&line, 1);
4594 QPainterPath linePath;
4595 for (int i = 0; i < lineCount; ++i) {
4596 linePath.moveTo(lines[i].p1());
4597 linePath.lineTo(lines[i].p2());
4599 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4603 d->engine->drawLines(lines, lineCount);
4609 Draws the first \a lineCount lines in the array \a pointPairs
4610 using the current pen. The lines are specified as pairs of points
4611 so the number of entries in \a pointPairs must be at least \a
4614 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4616 Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4618 drawLines((QLineF*)pointPairs, lineCount);
4624 Draws the first \a lineCount lines in the array \a pointPairs
4625 using the current pen.
4627 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4629 Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4631 drawLines((QLine*)pointPairs, lineCount);
4636 \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4639 Draws a line for each pair of points in the vector \a pointPairs
4640 using the current pen. If there is an odd number of points in the
4641 array, the last point will be ignored.
4645 \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4648 Draws a line for each pair of points in the vector \a pointPairs
4649 using the current pen.
4653 \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4656 Draws the set of lines defined by the list \a lines using the
4657 current pen and brush.
4661 \fn void QPainter::drawLines(const QVector<QLine> &lines)
4664 Draws the set of lines defined by the list \a lines using the
4665 current pen and brush.
4669 Draws the polyline defined by the first \a pointCount points in \a
4670 points using the current pen.
4672 Note that unlike the drawPolygon() function the last point is \e
4673 not connected to the first, neither is the polyline filled.
4678 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 13
4681 \sa drawLines(), drawPolygon(), {Coordinate System}
4683 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4685 #ifdef QT_DEBUG_DRAW
4686 if (qt_show_painter_debug_output)
4687 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4691 if (!d->engine || pointCount < 2)
4695 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4699 d->updateState(d->state);
4701 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4703 if (lineEmulation) {
4705 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4706 // && d->state->matrix.type() == QTransform::TxTranslate) {
4708 QPainterPath polylinePath(points[0]);
4709 for (int i=1; i<pointCount; ++i)
4710 polylinePath.lineTo(points[i]);
4711 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4714 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4721 Draws the polyline defined by the first \a pointCount points in \a
4722 points using the current pen.
4724 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4726 #ifdef QT_DEBUG_DRAW
4727 if (qt_show_painter_debug_output)
4728 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4732 if (!d->engine || pointCount < 2)
4736 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4740 d->updateState(d->state);
4742 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4744 if (lineEmulation) {
4746 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4747 // && d->state->matrix.type() == QTransform::TxTranslate) {
4749 QPainterPath polylinePath(points[0]);
4750 for (int i=1; i<pointCount; ++i)
4751 polylinePath.lineTo(points[i]);
4752 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4755 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4760 \fn void QPainter::drawPolyline(const QPolygonF &points)
4764 Draws the polyline defined by the given \a points using the
4769 \fn void QPainter::drawPolyline(const QPolygon &points)
4773 Draws the polyline defined by the given \a points using the
4778 Draws the polygon defined by the first \a pointCount points in the
4779 array \a points using the current pen and brush.
4783 \li \inlineimage qpainter-polygon.png
4785 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 14
4788 The first point is implicitly connected to the last point, and the
4789 polygon is filled with the current brush().
4791 If \a fillRule is Qt::WindingFill, the polygon is filled using the
4792 winding fill algorithm. If \a fillRule is Qt::OddEvenFill, the
4793 polygon is filled using the odd-even fill algorithm. See
4794 \l{Qt::FillRule} for a more detailed description of these fill
4797 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
4799 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
4801 #ifdef QT_DEBUG_DRAW
4802 if (qt_show_painter_debug_output)
4803 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4808 if (!d->engine || pointCount < 2)
4812 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4816 d->updateState(d->state);
4818 uint emulationSpecifier = d->state->emulationSpecifier;
4820 if (emulationSpecifier) {
4821 QPainterPath polygonPath(points[0]);
4822 for (int i=1; i<pointCount; ++i)
4823 polygonPath.lineTo(points[i]);
4824 polygonPath.closeSubpath();
4825 polygonPath.setFillRule(fillRule);
4826 d->draw_helper(polygonPath);
4830 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4835 Draws the polygon defined by the first \a pointCount points in the
4838 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
4840 #ifdef QT_DEBUG_DRAW
4841 if (qt_show_painter_debug_output)
4842 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4847 if (!d->engine || pointCount < 2)
4851 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4855 d->updateState(d->state);
4857 uint emulationSpecifier = d->state->emulationSpecifier;
4859 if (emulationSpecifier) {
4860 QPainterPath polygonPath(points[0]);
4861 for (int i=1; i<pointCount; ++i)
4862 polygonPath.lineTo(points[i]);
4863 polygonPath.closeSubpath();
4864 polygonPath.setFillRule(fillRule);
4865 d->draw_helper(polygonPath);
4869 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4872 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
4876 Draws the polygon defined by the given \a points using the fill
4880 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
4884 Draws the polygon defined by the given \a points using the fill
4889 \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4891 Draws the convex polygon defined by the first \a pointCount points
4892 in the array \a points using the current pen.
4896 \li \inlineimage qpainter-polygon.png
4898 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 15
4901 The first point is implicitly connected to the last point, and the
4902 polygon is filled with the current brush(). If the supplied
4903 polygon is not convex, i.e. it contains at least one angle larger
4904 than 180 degrees, the results are undefined.
4906 On some platforms (e.g. X11), the drawConvexPolygon() function can
4907 be faster than the drawPolygon() function.
4909 \sa drawPolygon(), drawPolyline(), {Coordinate System}
4913 \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4916 Draws the convex polygon defined by the first \a pointCount points
4917 in the array \a points using the current pen.
4921 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
4925 Draws the convex polygon defined by \a polygon using the current
4930 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
4933 Draws the convex polygon defined by \a polygon using the current
4937 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4939 #ifdef QT_DEBUG_DRAW
4940 if (qt_show_painter_debug_output)
4941 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4946 if (!d->engine || pointCount < 2)
4950 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4954 d->updateState(d->state);
4956 uint emulationSpecifier = d->state->emulationSpecifier;
4958 if (emulationSpecifier) {
4959 QPainterPath polygonPath(points[0]);
4960 for (int i=1; i<pointCount; ++i)
4961 polygonPath.lineTo(points[i]);
4962 polygonPath.closeSubpath();
4963 polygonPath.setFillRule(Qt::WindingFill);
4964 d->draw_helper(polygonPath);
4968 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4971 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4973 #ifdef QT_DEBUG_DRAW
4974 if (qt_show_painter_debug_output)
4975 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4980 if (!d->engine || pointCount < 2)
4984 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4988 d->updateState(d->state);
4990 uint emulationSpecifier = d->state->emulationSpecifier;
4992 if (emulationSpecifier) {
4993 QPainterPath polygonPath(points[0]);
4994 for (int i=1; i<pointCount; ++i)
4995 polygonPath.lineTo(points[i]);
4996 polygonPath.closeSubpath();
4997 polygonPath.setFillRule(Qt::WindingFill);
4998 d->draw_helper(polygonPath);
5002 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5005 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5007 return m.inverted().map(QPointF(m.map(p).toPoint()));
5011 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5013 Draws the rectangular portion \a source of the given \a pixmap
5014 into the given \a target in the paint device.
5016 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5021 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 16
5024 If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5025 using the pens color. If backgroundMode is Qt::OpaqueMode, the
5026 "unset" bits are drawn using the color of the background brush; if
5027 backgroundMode is Qt::TransparentMode, the "unset" bits are
5028 transparent. Drawing bitmaps with gradient or texture colors is
5033 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5035 #if defined QT_DEBUG_DRAW
5036 if (qt_show_painter_debug_output)
5037 printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5039 pm.width(), pm.height());
5044 if (!d->engine || pm.isNull())
5048 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5052 d->extended->drawPixmap(p, pm);
5060 int h = pm.height();
5065 // Emulate opaque background for bitmaps
5066 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5067 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5070 d->updateState(d->state);
5072 if ((d->state->matrix.type() > QTransform::TxTranslate
5073 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5074 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5075 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5078 // If there is no rotation involved we have to make sure we use the
5079 // antialiased and not the aliased coordinate system by rounding the coordinates.
5080 if (d->state->matrix.type() <= QTransform::TxScale) {
5081 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5086 setBackgroundMode(Qt::TransparentMode);
5087 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5088 QBrush brush(d->state->pen.color(), pm);
5091 setBrushOrigin(QPointF(0, 0));
5093 drawRect(pm.rect());
5096 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5097 x += d->state->matrix.dx();
5098 y += d->state->matrix.dy();
5100 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5104 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5106 #if defined QT_DEBUG_DRAW
5107 if (qt_show_painter_debug_output)
5108 printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5109 r.x(), r.y(), r.width(), r.height(),
5110 pm.width(), pm.height(),
5111 sr.x(), sr.y(), sr.width(), sr.height());
5115 if (!d->engine || pm.isNull())
5118 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5123 qreal w = r.width();
5124 qreal h = r.height();
5127 qreal sw = sr.width();
5128 qreal sh = sr.height();
5130 // Sanity-check clipping
5132 sw = pm.width() - sx;
5135 sh = pm.height() - sy;
5143 qreal w_ratio = sx * w/sw;
5151 qreal h_ratio = sy * h/sh;
5158 if (sw + sx > pm.width()) {
5159 qreal delta = sw - (pm.width() - sx);
5160 qreal w_ratio = delta * w/sw;
5165 if (sh + sy > pm.height()) {
5166 qreal delta = sh - (pm.height() - sy);
5167 qreal h_ratio = delta * h/sh;
5172 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5176 d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5180 // Emulate opaque background for bitmaps
5181 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5182 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5184 d->updateState(d->state);
5186 if ((d->state->matrix.type() > QTransform::TxTranslate
5187 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5188 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5189 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5190 || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5193 // If there is no rotation involved we have to make sure we use the
5194 // antialiased and not the aliased coordinate system by rounding the coordinates.
5195 if (d->state->matrix.type() <= QTransform::TxScale) {
5196 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5201 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5209 scale(w / sw, h / sh);
5210 setBackgroundMode(Qt::TransparentMode);
5211 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5214 if (sw == pm.width() && sh == pm.height())
5215 brush = QBrush(d->state->pen.color(), pm);
5217 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5222 drawRect(QRectF(0, 0, sw, sh));
5225 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5226 x += d->state->matrix.dx();
5227 y += d->state->matrix.dy();
5229 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5235 \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5236 const QRect &source)
5239 Draws the rectangular portion \a source of the given \a pixmap
5240 into the given \a target in the paint device.
5242 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5246 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5247 const QRectF &source)
5250 Draws the rectangular portion \a source of the given \a pixmap
5251 with its origin at the given \a point.
5255 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5256 const QRect &source)
5260 Draws the rectangular portion \a source of the given \a pixmap
5261 with its origin at the given \a point.
5265 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5268 Draws the given \a pixmap with its origin at the given \a point.
5272 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5275 Draws the given \a pixmap with its origin at the given \a point.
5279 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5283 Draws the given \a pixmap at position (\a{x}, \a{y}).
5287 \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5290 Draws the given \a pixmap into the given \a rectangle.
5292 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5296 \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5297 const QPixmap &pixmap)
5301 Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5302 with the given \a width and \a height.
5306 \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5307 int sx, int sy, int sw, int sh)
5311 Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5312 width \a sw and height \a sh, of the given \a pixmap , at the
5313 point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5314 If sw or sh are equal to zero the width/height of the pixmap
5315 is used and adjusted by the offset sx/sy;
5319 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5320 int sx, int sy, int sw, int sh)
5324 Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5325 pixmap into the paint device.
5327 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5328 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5329 pixmap that is to be drawn. The default is (0, 0).
5331 (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5332 The default, (0, 0) (and negative) means all the way to the
5333 bottom-right of the pixmap.
5336 void QPainter::drawImage(const QPointF &p, const QImage &image)
5340 if (!d->engine || image.isNull())
5344 d->extended->drawImage(p, image);
5351 int w = image.width();
5352 int h = image.height();
5354 d->updateState(d->state);
5356 if (((d->state->matrix.type() > QTransform::TxTranslate)
5357 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5358 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5359 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5362 // If there is no rotation involved we have to make sure we use the
5363 // antialiased and not the aliased coordinate system by rounding the coordinates.
5364 if (d->state->matrix.type() <= QTransform::TxScale) {
5365 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5370 setBackgroundMode(Qt::TransparentMode);
5371 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5372 QBrush brush(image);
5375 setBrushOrigin(QPointF(0, 0));
5377 drawRect(image.rect());
5382 if (d->state->matrix.type() == QTransform::TxTranslate
5383 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5384 x += d->state->matrix.dx();
5385 y += d->state->matrix.dy();
5388 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5391 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5392 Qt::ImageConversionFlags flags)
5396 if (!d->engine || image.isNull())
5399 qreal x = targetRect.x();
5400 qreal y = targetRect.y();
5401 qreal w = targetRect.width();
5402 qreal h = targetRect.height();
5403 qreal sx = sourceRect.x();
5404 qreal sy = sourceRect.y();
5405 qreal sw = sourceRect.width();
5406 qreal sh = sourceRect.height();
5408 // Sanity-check clipping
5410 sw = image.width() - sx;
5413 sh = image.height() - sy;
5421 qreal w_ratio = sx * w/sw;
5429 qreal h_ratio = sy * h/sh;
5436 if (sw + sx > image.width()) {
5437 qreal delta = sw - (image.width() - sx);
5438 qreal w_ratio = delta * w/sw;
5443 if (sh + sy > image.height()) {
5444 qreal delta = sh - (image.height() - sy);
5445 qreal h_ratio = delta * h/sh;
5450 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5454 d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5458 d->updateState(d->state);
5460 if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5461 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5462 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5463 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5466 // If there is no rotation involved we have to make sure we use the
5467 // antialiased and not the aliased coordinate system by rounding the coordinates.
5468 if (d->state->matrix.type() <= QTransform::TxScale) {
5469 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5474 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5481 scale(w / sw, h / sh);
5482 setBackgroundMode(Qt::TransparentMode);
5483 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5484 QBrush brush(image);
5487 setBrushOrigin(QPointF(-sx, -sy));
5489 drawRect(QRectF(0, 0, sw, sh));
5494 if (d->state->matrix.type() == QTransform::TxTranslate
5495 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5496 x += d->state->matrix.dx();
5497 y += d->state->matrix.dy();
5500 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5504 \fn void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphs)
5506 Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5507 edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5508 selected on \a glyphs and at offsets given by the positions in \a glyphs.
5512 \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes()
5514 #if !defined(QT_NO_RAWFONT)
5515 void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
5519 QRawFont font = glyphRun.rawFont();
5520 if (!font.isValid())
5523 QGlyphRunPrivate *glyphRun_d = QGlyphRunPrivate::get(glyphRun);
5525 const quint32 *glyphIndexes = glyphRun_d->glyphIndexData;
5526 const QPointF *glyphPositions = glyphRun_d->glyphPositionData;
5528 int count = qMin(glyphRun_d->glyphIndexDataSize, glyphRun_d->glyphPositionDataSize);
5529 QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5531 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5532 bool supportsTransformations = d->extended
5533 ? d->extended->supportsTransformations(fontD->fontEngine, d->state->matrix)
5534 : d->engine->type() == QPaintEngine::CoreGraphics || d->state->matrix.isAffine();
5536 for (int i=0; i<count; ++i) {
5537 QPointF processedPosition = position + glyphPositions[i];
5538 if (!supportsTransformations)
5539 processedPosition = d->state->transform().map(processedPosition);
5540 fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5543 d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, font, glyphRun.overline(),
5544 glyphRun.underline(), glyphRun.strikeOut());
5547 void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions,
5549 const QRawFont &font, bool overline, bool underline,
5556 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5557 QFontEngine *fontEngine = fontD->fontEngine;
5562 for (int i=0; i<glyphCount; ++i) {
5563 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5564 if (i == 0 || leftMost > positions[i].x)
5565 leftMost = positions[i].x;
5567 // We don't support glyphs that do not share a common baseline. If this turns out to
5568 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5569 // and do a drawTextItemDecorations call per cluster.
5570 if (i == 0 || baseLine < positions[i].y)
5571 baseLine = positions[i].y;
5573 // We use the advance rather than the actual bounds to match the algorithm in drawText()
5574 if (i == 0 || rightMost < positions[i].x + gm.xoff)
5575 rightMost = positions[i].x + gm.xoff;
5578 QFixed width = rightMost - leftMost;
5580 if (extended != 0 && state->matrix.isAffine()) {
5581 QStaticTextItem staticTextItem;
5582 staticTextItem.color = state->pen.color();
5583 staticTextItem.font = state->font;
5584 staticTextItem.setFontEngine(fontEngine);
5585 staticTextItem.numGlyphs = glyphCount;
5586 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5587 staticTextItem.glyphPositions = positions;
5589 extended->drawStaticTextItem(&staticTextItem);
5591 QTextItemInt textItem;
5592 textItem.fontEngine = fontEngine;
5594 QVarLengthArray<QFixed, 128> advances(glyphCount);
5595 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5596 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5597 memset(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5598 memset(advances.data(), 0, advances.size() * sizeof(QFixed));
5599 memset(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5601 textItem.glyphs.numGlyphs = glyphCount;
5602 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5603 textItem.glyphs.offsets = positions;
5604 textItem.glyphs.advances_x = advances.data();
5605 textItem.glyphs.advances_y = advances.data();
5606 textItem.glyphs.justifications = glyphJustifications.data();
5607 textItem.glyphs.attributes = glyphAttributes.data();
5609 engine->drawTextItem(QPointF(0, 0), textItem);
5612 QTextItemInt::RenderFlags flags;
5614 flags |= QTextItemInt::Underline;
5616 flags |= QTextItemInt::Overline;
5618 flags |= QTextItemInt::StrikeOut;
5620 drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5624 ? QTextCharFormat::SingleUnderline
5625 : QTextCharFormat::NoUnderline),
5626 flags, width.toReal(), QTextCharFormat());
5628 #endif // QT_NO_RAWFONT
5632 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5636 Draws the \a staticText at the \a topLeftPosition.
5638 \note The y-position is used as the top of the font.
5643 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5647 Draws the \a staticText at coordinates \a left and \a top.
5649 \note The y-position is used as the top of the font.
5653 \fn void QPainter::drawText(const QPointF &position, const QString &text)
5655 Draws the given \a text with the currently defined text direction,
5656 beginning at the given \a position.
5658 This function does not handle the newline character (\n), as it cannot
5659 break text into multiple lines, and it cannot display the newline character.
5660 Use the QPainter::drawText() overload that takes a rectangle instead
5661 if you want to draw multiple lines of text with the newline character, or
5662 if you want the text to be wrapped.
5664 By default, QPainter draws text anti-aliased.
5666 \note The y-position is used as the baseline of the font.
5669 void QPainter::drawText(const QPointF &p, const QString &str)
5671 drawText(p, str, 0, 0);
5677 Draws the given \a staticText at the given \a topLeftPosition.
5679 The text will be drawn using the font and the transformation set on the painter. If the
5680 font and/or transformation set on the painter are different from the ones used to initialize
5681 the layout of the QStaticText, then the layout will have to be recalculated. Use
5682 QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5683 it will later be drawn.
5685 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5686 last drawn, then there will be a slight overhead when translating the text to its new position.
5688 \note If the painter's transformation is not affine, then \a staticText will be drawn using
5689 regular calls to drawText(), losing any potential for performance improvement.
5691 \note The y-position is used as the top of the font.
5695 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5698 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5701 QStaticTextPrivate *staticText_d =
5702 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5704 if (font() != staticText_d->font) {
5705 staticText_d->font = font();
5706 staticText_d->needsRelayout = true;
5709 // If we don't have an extended paint engine, or if the painter is projected,
5710 // we go through standard code path
5711 if (d->extended == 0 || !d->state->matrix.isAffine()) {
5712 staticText_d->paintText(topLeftPosition, this);
5716 bool supportsTransformations = d->extended->supportsTransformations(staticText_d->font.d->engineForScript(QUnicodeTables::Common),
5718 if (supportsTransformations && !staticText_d->untransformedCoordinates) {
5719 staticText_d->untransformedCoordinates = true;
5720 staticText_d->needsRelayout = true;
5721 } else if (!supportsTransformations && staticText_d->untransformedCoordinates) {
5722 staticText_d->untransformedCoordinates = false;
5723 staticText_d->needsRelayout = true;
5726 // Don't recalculate entire layout because of translation, rather add the dx and dy
5727 // into the position to move each text item the correct distance.
5728 QPointF transformedPosition = topLeftPosition;
5729 if (!staticText_d->untransformedCoordinates)
5730 transformedPosition = transformedPosition * d->state->matrix;
5731 QTransform oldMatrix;
5733 // The translation has been applied to transformedPosition. Remove translation
5734 // component from matrix.
5735 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
5736 qreal m11 = d->state->matrix.m11();
5737 qreal m12 = d->state->matrix.m12();
5738 qreal m13 = d->state->matrix.m13();
5739 qreal m21 = d->state->matrix.m21();
5740 qreal m22 = d->state->matrix.m22();
5741 qreal m23 = d->state->matrix.m23();
5742 qreal m33 = d->state->matrix.m33();
5744 oldMatrix = d->state->matrix;
5745 d->state->matrix.setMatrix(m11, m12, m13,
5750 // If the transform is not identical to the text transform,
5751 // we have to relayout the text (for other transformations than plain translation)
5752 bool staticTextNeedsReinit = staticText_d->needsRelayout;
5753 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
5754 staticText_d->matrix = d->state->matrix;
5755 staticTextNeedsReinit = true;
5758 // Recreate the layout of the static text because the matrix or font has changed
5759 if (staticTextNeedsReinit)
5760 staticText_d->init();
5762 if (transformedPosition != staticText_d->position) { // Translate to actual position
5763 QFixed fx = QFixed::fromReal(transformedPosition.x());
5764 QFixed fy = QFixed::fromReal(transformedPosition.y());
5765 QFixed oldX = QFixed::fromReal(staticText_d->position.x());
5766 QFixed oldY = QFixed::fromReal(staticText_d->position.y());
5767 for (int item=0; item<staticText_d->itemCount;++item) {
5768 QStaticTextItem *textItem = staticText_d->items + item;
5769 for (int i=0; i<textItem->numGlyphs; ++i) {
5770 textItem->glyphPositions[i].x += fx - oldX;
5771 textItem->glyphPositions[i].y += fy - oldY;
5773 textItem->userDataNeedsUpdate = true;
5776 staticText_d->position = transformedPosition;
5779 QPen oldPen = d->state->pen;
5780 QColor currentColor = oldPen.color();
5781 for (int i=0; i<staticText_d->itemCount; ++i) {
5782 QStaticTextItem *item = staticText_d->items + i;
5783 if (item->color.isValid() && currentColor != item->color) {
5784 setPen(item->color);
5785 currentColor = item->color;
5787 d->extended->drawStaticTextItem(item);
5789 qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
5790 item->numGlyphs, item->fontEngine(), staticText_d->font,
5793 if (currentColor != oldPen.color())
5796 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
5797 d->state->matrix = oldMatrix;
5803 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
5805 #ifdef QT_DEBUG_DRAW
5806 if (qt_show_painter_debug_output)
5807 printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
5812 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
5815 if (tf & Qt::TextBypassShaping) {
5816 // Skip harfbuzz complex shaping, shape using glyph advances only
5817 int len = str.length();
5818 int numGlyphs = len;
5819 QVarLengthGlyphLayoutArray glyphs(len);
5820 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
5821 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
5822 glyphs.resize(numGlyphs);
5823 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
5824 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
5827 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
5828 drawTextItem(p, gf);
5832 QStackTextEngine engine(str, d->state->font);
5833 engine.option.setTextDirection(d->state->layoutDirection);
5834 if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
5835 engine.ignoreBidi = true;
5836 engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
5840 line.length = str.length();
5841 engine.shapeLine(line);
5843 int nItems = engine.layoutData->items.size();
5844 QVarLengthArray<int> visualOrder(nItems);
5845 QVarLengthArray<uchar> levels(nItems);
5846 for (int i = 0; i < nItems; ++i)
5847 levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
5848 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
5850 if (justificationPadding > 0) {
5851 engine.option.setAlignment(Qt::AlignJustify);
5852 engine.forceJustification = true;
5853 // this works because justify() is only interested in the difference between width and textWidth
5854 line.width = justificationPadding;
5855 engine.justify(line);
5857 QFixed x = QFixed::fromReal(p.x());
5859 for (int i = 0; i < nItems; ++i) {
5860 int item = visualOrder[i];
5861 const QScriptItem &si = engine.layoutData->items.at(item);
5862 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
5866 QFont f = engine.font(si);
5867 QTextItemInt gf(si, &f);
5868 gf.glyphs = engine.shapedGlyphs(&si);
5869 gf.chars = engine.layoutData->string.unicode() + si.position;
5870 gf.num_chars = engine.length(item);
5871 if (engine.forceJustification) {
5872 for (int j=0; j<gf.glyphs.numGlyphs; ++j)
5873 gf.width += gf.glyphs.effectiveAdvance(j);
5875 gf.width = si.width;
5877 gf.logClusters = engine.logClusters(&si);
5879 drawTextItem(QPointF(x.toReal(), p.y()), gf);
5885 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
5887 #ifdef QT_DEBUG_DRAW
5888 if (qt_show_painter_debug_output)
5889 printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
5890 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5895 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5899 d->updateState(d->state);
5902 qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
5904 *br = bounds.toAlignedRect();
5908 \fn void QPainter::drawText(const QPoint &position, const QString &text)
5912 Draws the given \a text with the currently defined text direction,
5913 beginning at the given \a position.
5915 By default, QPainter draws text anti-aliased.
5917 \note The y-position is used as the baseline of the font.
5922 \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
5925 Draws the given \a text within the provided \a rectangle.
5929 \li \inlineimage qpainter-text.png
5931 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 17
5934 The \a boundingRect (if not null) is set to the what the bounding rectangle
5935 should be in order to enclose the whole text. The \a flags argument is a bitwise
5936 OR of the following flags:
5941 \li Qt::AlignHCenter
5942 \li Qt::AlignJustify
5945 \li Qt::AlignVCenter
5947 \li Qt::TextDontClip
5948 \li Qt::TextSingleLine
5949 \li Qt::TextExpandTabs
5950 \li Qt::TextShowMnemonic
5951 \li Qt::TextWordWrap
5952 \li Qt::TextIncludeTrailingSpaces
5955 \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
5957 By default, QPainter draws text anti-aliased.
5959 \note The y-coordinate of \a rectangle is used as the top of the font.
5961 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
5963 #ifdef QT_DEBUG_DRAW
5964 if (qt_show_painter_debug_output)
5965 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
5966 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5971 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5975 d->updateState(d->state);
5977 qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
5981 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
5984 Draws the given \a text within the provided \a rectangle according
5985 to the specified \a flags. The \a boundingRect (if not null) is set to
5986 the what the bounding rectangle should be in order to enclose the whole text.
5988 By default, QPainter draws text anti-aliased.
5990 \note The y-coordinate of \a rectangle is used as the top of the font.
5994 \fn void QPainter::drawText(int x, int y, const QString &text)
5998 Draws the given \a text at position (\a{x}, \a{y}), using the painter's
5999 currently defined text direction.
6001 By default, QPainter draws text anti-aliased.
6003 \note The y-position is used as the baseline of the font.
6008 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6009 const QString &text, QRect *boundingRect)
6013 Draws the given \a text within the rectangle with origin (\a{x},
6014 \a{y}), \a width and \a height.
6016 The \a boundingRect (if not null) is set to the actual bounding
6017 rectangle of the output. The \a flags argument is a bitwise OR of
6018 the following flags:
6023 \li Qt::AlignHCenter
6024 \li Qt::AlignJustify
6027 \li Qt::AlignVCenter
6029 \li Qt::TextSingleLine
6030 \li Qt::TextExpandTabs
6031 \li Qt::TextShowMnemonic
6032 \li Qt::TextWordWrap
6035 By default, QPainter draws text anti-aliased.
6037 \note The y-position is used as the top of the font.
6039 \sa Qt::AlignmentFlag, Qt::TextFlag
6043 \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6044 const QTextOption &option)
6047 Draws the given \a text in the \a rectangle specified using the \a option
6048 to control its positioning and orientation.
6050 By default, QPainter draws text anti-aliased.
6052 \note The y-coordinate of \a rectangle is used as the top of the font.
6054 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6056 #ifdef QT_DEBUG_DRAW
6057 if (qt_show_painter_debug_output)
6058 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6059 r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6064 if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6068 d->updateState(d->state);
6070 qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6074 \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6081 \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6086 Draws the text item \a ti at position \a p.
6090 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6095 Draws the text item \a ti at position \a p.
6097 This method ignores the painters background mode and
6098 color. drawText and qt_format_text have to do it themselves, as
6099 only they know the extents of the complete string.
6101 It ignores the font set on the painter as the text item has one of its own.
6103 The underline and strikeout parameters of the text items font are
6104 ignored aswell. You'll need to pass in the correct flags to get
6105 underlining and strikeout.
6108 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6110 const qreal radiusBase = qMax(qreal(1), maxRadius);
6112 QString key = QLatin1Literal("WaveUnderline-")
6113 % pen.color().name()
6114 % HexString<qreal>(radiusBase);
6117 if (QPixmapCache::find(key, pixmap))
6120 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6121 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6122 const int radius = qFloor(radiusBase);
6129 while (xs < width) {
6132 path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6135 pixmap = QPixmap(width, radius * 2);
6136 pixmap.fill(Qt::transparent);
6139 wavePen.setCapStyle(Qt::SquareCap);
6141 // This is to protect against making the line too fat, as happens on Mac OS X
6142 // due to it having a rather thick width for the regular underline.
6143 const qreal maxPenWidth = .8 * radius;
6144 if (wavePen.widthF() > maxPenWidth)
6145 wavePen.setWidth(maxPenWidth);
6147 QPainter imgPainter(&pixmap);
6148 imgPainter.setPen(wavePen);
6149 imgPainter.setRenderHint(QPainter::Antialiasing);
6150 imgPainter.translate(0, radius);
6151 imgPainter.drawPath(path);
6154 QPixmapCache::insert(key, pixmap);
6159 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
6160 QTextCharFormat::UnderlineStyle underlineStyle,
6161 QTextItem::RenderFlags flags, qreal width,
6162 const QTextCharFormat &charFormat)
6164 if (underlineStyle == QTextCharFormat::NoUnderline
6165 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6168 const QPen oldPen = painter->pen();
6169 const QBrush oldBrush = painter->brush();
6170 painter->setBrush(Qt::NoBrush);
6172 pen.setStyle(Qt::SolidLine);
6173 pen.setWidthF(fe->lineThickness().toReal());
6174 pen.setCapStyle(Qt::FlatCap);
6176 QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6178 const qreal underlineOffset = fe->underlinePosition().toReal();
6179 // deliberately ceil the offset to avoid the underline coming too close to
6180 // the text above it.
6181 const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
6182 const qreal underlinePos = pos.y() + qCeil(underlineOffset) - aliasedCoordinateDelta;
6184 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6185 underlineStyle = QTextCharFormat::SpellCheckUnderline; // ### Qt5 QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle));
6188 if (underlineStyle == QTextCharFormat::WaveUnderline) {
6190 painter->translate(0, pos.y() + 1);
6192 QColor uc = charFormat.underlineColor();
6196 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6197 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6198 const int descent = (int) fe->descent().toReal();
6200 painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6201 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6203 } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6204 QColor uc = charFormat.underlineColor();
6208 pen.setStyle((Qt::PenStyle)(underlineStyle));
6209 painter->setPen(pen);
6210 QLineF underline(line.x1(), underlinePos, line.x2(), underlinePos);
6212 textEngine->addUnderline(painter, underline);
6214 painter->drawLine(underline);
6217 pen.setStyle(Qt::SolidLine);
6218 pen.setColor(oldPen.color());
6220 if (flags & QTextItem::StrikeOut) {
6221 QLineF strikeOutLine = line;
6222 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6223 painter->setPen(pen);
6225 textEngine->addStrikeOut(painter, strikeOutLine);
6227 painter->drawLine(strikeOutLine);
6230 if (flags & QTextItem::Overline) {
6231 QLineF overline = line;
6232 overline.translate(0., - fe->ascent().toReal());
6233 painter->setPen(pen);
6235 textEngine->addOverline(painter, overline);
6237 painter->drawLine(overline);
6240 painter->setPen(oldPen);
6241 painter->setBrush(oldBrush);
6244 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6245 const QFixedPoint *positions, int glyphCount,
6246 QFontEngine *fontEngine, const QFont &font,
6247 const QTextCharFormat &charFormat)
6249 if (!(font.underline() || font.strikeOut() || font.overline()))
6255 for (int i=0; i<glyphCount; ++i) {
6256 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6257 if (i == 0 || leftMost > positions[i].x)
6258 leftMost = positions[i].x;
6260 // We don't support glyphs that do not share a common baseline. If this turns out to
6261 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6262 // and do a drawTextItemDecoration call per cluster.
6263 if (i == 0 || baseLine < positions[i].y)
6264 baseLine = positions[i].y;
6266 // We use the advance rather than the actual bounds to match the algorithm in drawText()
6267 if (i == 0 || rightMost < positions[i].x + gm.xoff)
6268 rightMost = positions[i].x + gm.xoff;
6271 QFixed width = rightMost - leftMost;
6272 QTextItem::RenderFlags flags = 0;
6274 if (font.underline())
6275 flags |= QTextItem::Underline;
6276 if (font.overline())
6277 flags |= QTextItem::Overline;
6278 if (font.strikeOut())
6279 flags |= QTextItem::StrikeOut;
6281 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6284 font.underline() ? QTextCharFormat::SingleUnderline
6285 : QTextCharFormat::NoUnderline, flags,
6286 width.toReal(), charFormat);
6289 void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6293 d->drawTextItem(p, ti, static_cast<QTextEngine *>(0));
6296 void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine)
6298 #ifdef QT_DEBUG_DRAW
6299 if (qt_show_painter_debug_output)
6300 printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6301 p.x(), p.y(), qPrintable(_ti.text()));
6310 qt_painter_thread_test(device->devType(),
6312 QFontDatabase::supportsThreadedFontRendering());
6315 QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6317 if (!extended && state->bgMode == Qt::OpaqueMode) {
6318 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6319 q->fillRect(rect, state->bgBrush);
6322 if (q->pen().style() == Qt::NoPen)
6325 const QPainter::RenderHints oldRenderHints = state->renderHints;
6326 if (!state->renderHints & QPainter::Antialiasing && state->matrix.type() >= QTransform::TxScale) {
6327 // draw antialias decoration (underline/overline/strikeout) with
6331 const QTransform &m = state->matrix;
6332 if (state->matrix.type() < QTransform::TxShear) {
6333 bool isPlain90DegreeRotation =
6334 (qFuzzyIsNull(m.m11())
6335 && qFuzzyIsNull(m.m12() - qreal(1))
6336 && qFuzzyIsNull(m.m21() + qreal(1))
6337 && qFuzzyIsNull(m.m22())
6340 (qFuzzyIsNull(m.m11() + qreal(1))
6341 && qFuzzyIsNull(m.m12())
6342 && qFuzzyIsNull(m.m21())
6343 && qFuzzyIsNull(m.m22() + qreal(1))
6346 (qFuzzyIsNull(m.m11())
6347 && qFuzzyIsNull(m.m12() + qreal(1))
6348 && qFuzzyIsNull(m.m21() - qreal(1))
6349 && qFuzzyIsNull(m.m22())
6352 aa = !isPlain90DegreeRotation;
6355 q->setRenderHint(QPainter::Antialiasing, true);
6361 if (!ti.glyphs.numGlyphs) {
6363 } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6364 QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6366 const QGlyphLayout &glyphs = ti.glyphs;
6367 int which = glyphs.glyphs[0] >> 24;
6372 bool rtl = ti.flags & QTextItem::RightToLeft;
6374 x += ti.width.toReal();
6378 for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6379 const int e = glyphs.glyphs[end] >> 24;
6384 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6386 // set the high byte to zero and calc the width
6387 for (i = start; i < end; ++i) {
6388 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6389 ti2.width += ti.glyphs.effectiveAdvance(i);
6393 x -= ti2.width.toReal();
6395 engine->drawTextItem(QPointF(x, y), ti2);
6398 x += ti2.width.toReal();
6400 // reset the high byte for all glyphs and advance to the next sub-string
6401 const int hi = which << 24;
6402 for (i = start; i < end; ++i) {
6403 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6411 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6413 // set the high byte to zero and calc the width
6414 for (i = start; i < end; ++i) {
6415 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6416 ti2.width += ti.glyphs.effectiveAdvance(i);
6420 x -= ti2.width.toReal();
6423 extended->drawTextItem(QPointF(x, y), ti2);
6425 engine->drawTextItem(QPointF(x,y), ti2);
6427 // reset the high byte for all glyphs
6428 const int hi = which << 24;
6429 for (i = start; i < end; ++i)
6430 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6434 extended->drawTextItem(p, ti);
6436 engine->drawTextItem(p, ti);
6438 drawTextItemDecoration(q, p, ti.fontEngine, textEngine, ti.underlineStyle,
6439 ti.flags, ti.width.toReal(), ti.charFormat);
6441 if (state->renderHints != oldRenderHints) {
6442 state->renderHints = oldRenderHints;
6444 extended->renderHintsChanged();
6446 state->dirtyFlags |= QPaintEngine::DirtyHints;
6451 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6453 Returns the bounding rectangle of the \a text as it will appear
6454 when drawn inside the given \a rectangle with the specified \a
6455 flags using the currently set font(); i.e the function tells you
6456 where the drawText() function will draw when given the same
6459 If the \a text does not fit within the given \a rectangle using
6460 the specified \a flags, the function returns the required
6463 The \a flags argument is a bitwise OR of the following flags:
6467 \li Qt::AlignHCenter
6470 \li Qt::AlignVCenter
6472 \li Qt::TextSingleLine
6473 \li Qt::TextExpandTabs
6474 \li Qt::TextShowMnemonic
6475 \li Qt::TextWordWrap
6476 \li Qt::TextIncludeTrailingSpaces
6478 If several of the horizontal or several of the vertical alignment
6479 flags are set, the resulting alignment is undefined.
6481 \sa drawText(), Qt::Alignment, Qt::TextFlag
6485 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6486 const QString &text)
6490 Returns the bounding rectangle of the \a text as it will appear
6491 when drawn inside the given \a rectangle with the specified \a
6492 flags using the currently set font().
6496 \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6497 const QString &text);
6501 Returns the bounding rectangle of the given \a text as it will
6502 appear when drawn inside the rectangle beginning at the point
6503 (\a{x}, \a{y}) with width \a w and height \a h.
6505 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6508 return QRect(rect.x(),rect.y(), 0,0);
6510 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6516 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6519 return QRectF(rect.x(),rect.y(), 0,0);
6521 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6526 \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6527 const QString &text, const QTextOption &option)
6531 Instead of specifying flags as a bitwise OR of the
6532 Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6533 an \a option argument. The QTextOption class provides a
6534 description of general rich text properties.
6538 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6542 if (!d->engine || text.length() == 0)
6543 return QRectF(r.x(),r.y(), 0,0);
6546 qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6551 \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6553 Draws a tiled \a pixmap, inside the given \a rectangle with its
6554 origin at the given \a position.
6556 Calling drawTiledPixmap() is similar to calling drawPixmap()
6557 several times to fill (tile) an area with a pixmap, but is
6558 potentially much more efficient depending on the underlying window
6563 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6565 #ifdef QT_DEBUG_DRAW
6566 if (qt_show_painter_debug_output)
6567 printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6568 r.x(), r.y(), r.width(), r.height(),
6569 pixmap.width(), pixmap.height(),
6574 if (!d->engine || pixmap.isNull() || r.isEmpty())
6578 qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6581 qreal sw = pixmap.width();
6582 qreal sh = pixmap.height();
6586 sx = qRound(sw) - qRound(-sx) % qRound(sw);
6588 sx = qRound(sx) % qRound(sw);
6590 sy = qRound(sh) - -qRound(sy) % qRound(sh);
6592 sy = qRound(sy) % qRound(sh);
6596 d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6600 if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6601 fillRect(r, d->state->bgBrush);
6603 d->updateState(d->state);
6604 if ((d->state->matrix.type() > QTransform::TxTranslate
6605 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6606 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6609 setBackgroundMode(Qt::TransparentMode);
6610 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6611 setBrush(QBrush(d->state->pen.color(), pixmap));
6614 // If there is no rotation involved we have to make sure we use the
6615 // antialiased and not the aliased coordinate system by rounding the coordinates.
6616 if (d->state->matrix.type() <= QTransform::TxScale) {
6617 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6619 if (d->state->matrix.type() <= QTransform::TxTranslate) {
6624 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6625 drawRect(QRectF(p, r.size()));
6627 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6636 if (d->state->matrix.type() == QTransform::TxTranslate
6637 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6638 x += d->state->matrix.dx();
6639 y += d->state->matrix.dy();
6642 d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6646 \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6647 const QPoint &position = QPoint())
6650 Draws a tiled \a pixmap, inside the given \a rectangle with its
6651 origin at the given \a position.
6655 \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6656 QPixmap &pixmap, int sx, int sy);
6659 Draws a tiled \a pixmap in the specified rectangle.
6661 (\a{x}, \a{y}) specifies the top-left point in the paint device
6662 that is to be drawn onto; with the given \a width and \a
6663 height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6664 pixmap that is to be drawn; this defaults to (0, 0).
6667 #ifndef QT_NO_PICTURE
6670 \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6672 Replays the given \a picture at the given \a point.
6674 The QPicture class is a paint device that records and replays
6675 QPainter commands. A picture serializes the painter commands to an
6676 IO device in a platform-independent format. Everything that can be
6677 painted on a widget or pixmap can also be stored in a picture.
6679 This function does exactly the same as QPicture::play() when
6680 called with \a point = QPoint(0, 0).
6685 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 18
6688 \sa QPicture::play()
6691 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6699 d->updateState(d->state);
6703 const_cast<QPicture *>(&picture)->play(this);
6708 \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6711 Replays the given \a picture at the given \a point.
6715 \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6718 Draws the given \a picture at point (\a x, \a y).
6721 #endif // QT_NO_PICTURE
6724 \fn void QPainter::eraseRect(const QRectF &rectangle)
6726 Erases the area inside the given \a rectangle. Equivalent to
6728 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 19
6732 void QPainter::eraseRect(const QRectF &r)
6736 fillRect(r, d->state->bgBrush);
6739 static inline bool needsResolving(const QBrush &brush)
6741 Qt::BrushStyle s = brush.style();
6742 return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
6743 s == Qt::ConicalGradientPattern) &&
6744 brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
6748 \fn void QPainter::eraseRect(const QRect &rectangle)
6751 Erases the area inside the given \a rectangle.
6755 \fn void QPainter::eraseRect(int x, int y, int width, int height)
6758 Erases the area inside the rectangle beginning at (\a x, \a y)
6759 with the given \a width and \a height.
6764 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
6767 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6768 width and \a height, using the brush \a style specified.
6774 \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
6777 Fills the given \a rectangle with the brush \a style specified.
6783 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
6786 Fills the given \a rectangle with the brush \a style specified.
6792 \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
6794 Fills the given \a rectangle with the \a brush specified.
6796 Alternatively, you can specify a QColor instead of a QBrush; the
6797 QBrush constructor (taking a QColor argument) will automatically
6798 create a solid pattern brush.
6802 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
6810 const QGradient *g = brush.gradient();
6811 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6812 d->extended->fillRect(r, brush);
6817 QPen oldPen = pen();
6818 QBrush oldBrush = this->brush();
6820 if (brush.style() == Qt::SolidPattern) {
6821 d->colorBrush.setStyle(Qt::SolidPattern);
6822 d->colorBrush.setColor(brush.color());
6823 setBrush(d->colorBrush);
6834 \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
6837 Fills the given \a rectangle with the specified \a brush.
6840 void QPainter::fillRect(const QRect &r, const QBrush &brush)
6848 const QGradient *g = brush.gradient();
6849 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6850 d->extended->fillRect(r, brush);
6855 QPen oldPen = pen();
6856 QBrush oldBrush = this->brush();
6858 if (brush.style() == Qt::SolidPattern) {
6859 d->colorBrush.setStyle(Qt::SolidPattern);
6860 d->colorBrush.setColor(brush.color());
6861 setBrush(d->colorBrush);
6874 \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
6877 Fills the given \a rectangle with the \a color specified.
6881 void QPainter::fillRect(const QRect &r, const QColor &color)
6889 d->extended->fillRect(r, color);
6893 fillRect(r, QBrush(color));
6898 \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
6901 Fills the given \a rectangle with the \a color specified.
6905 void QPainter::fillRect(const QRectF &r, const QColor &color)
6913 d->extended->fillRect(r, color);
6917 fillRect(r, QBrush(color));
6921 \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
6925 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6926 width and \a height, using the given \a brush.
6930 \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
6934 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6935 width and \a height, using the given \a color.
6941 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
6945 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6946 width and \a height, using the given \a color.
6952 \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
6956 Fills the given \a rectangle with the specified \a color.
6962 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
6966 Fills the given \a rectangle with the specified \a color.
6972 Sets the given render \a hint on the painter if \a on is true;
6973 otherwise clears the render hint.
6975 \sa setRenderHints(), renderHints(), {QPainter#Rendering
6976 Quality}{Rendering Quality}
6978 void QPainter::setRenderHint(RenderHint hint, bool on)
6980 #ifdef QT_DEBUG_DRAW
6981 if (qt_show_painter_debug_output)
6982 printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
6986 static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
6987 if (hint == QPainter::Antialiasing && antialiasingDisabled)
6991 setRenderHints(hint, on);
6997 Sets the given render \a hints on the painter if \a on is true;
6998 otherwise clears the render hints.
7000 \sa setRenderHint(), renderHints(), {QPainter#Rendering
7001 Quality}{Rendering Quality}
7004 void QPainter::setRenderHints(RenderHints hints, bool on)
7009 qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7014 d->state->renderHints |= hints;
7016 d->state->renderHints &= ~hints;
7019 d->extended->renderHintsChanged();
7021 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7025 Returns a flag that specifies the rendering hints that are set for
7028 \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7030 QPainter::RenderHints QPainter::renderHints() const
7032 Q_D(const QPainter);
7037 return d->state->renderHints;
7041 \fn bool QPainter::testRenderHint(RenderHint hint) const
7044 Returns true if \a hint is set; otherwise returns false.
7046 \sa renderHints(), setRenderHint()
7050 Returns true if view transformation is enabled; otherwise returns
7053 \sa setViewTransformEnabled(), worldTransform()
7056 bool QPainter::viewTransformEnabled() const
7058 Q_D(const QPainter);
7060 qWarning("QPainter::viewTransformEnabled: Painter not active");
7063 return d->state->VxF;
7067 \fn void QPainter::setWindow(const QRect &rectangle)
7069 Sets the painter's window to the given \a rectangle, and enables
7070 view transformations.
7072 The window rectangle is part of the view transformation. The
7073 window specifies the logical coordinate system. Its sister, the
7074 viewport(), specifies the device coordinate system.
7076 The default window rectangle is the same as the device's
7079 \sa window(), viewTransformEnabled(), {Coordinate
7080 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7084 \fn void QPainter::setWindow(int x, int y, int width, int height)
7087 Sets the painter's window to the rectangle beginning at (\a x, \a
7088 y) and the given \a width and \a height.
7091 void QPainter::setWindow(const QRect &r)
7093 #ifdef QT_DEBUG_DRAW
7094 if (qt_show_painter_debug_output)
7095 printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7101 qWarning("QPainter::setWindow: Painter not active");
7105 d->state->wx = r.x();
7106 d->state->wy = r.y();
7107 d->state->ww = r.width();
7108 d->state->wh = r.height();
7110 d->state->VxF = true;
7115 Returns the window rectangle.
7117 \sa setWindow(), setViewTransformEnabled()
7120 QRect QPainter::window() const
7122 Q_D(const QPainter);
7124 qWarning("QPainter::window: Painter not active");
7127 return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7131 \fn void QPainter::setViewport(const QRect &rectangle)
7133 Sets the painter's viewport rectangle to the given \a rectangle,
7134 and enables view transformations.
7136 The viewport rectangle is part of the view transformation. The
7137 viewport specifies the device coordinate system. Its sister, the
7138 window(), specifies the logical coordinate system.
7140 The default viewport rectangle is the same as the device's
7143 \sa viewport(), viewTransformEnabled() {Coordinate
7144 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7148 \fn void QPainter::setViewport(int x, int y, int width, int height)
7151 Sets the painter's viewport rectangle to be the rectangle
7152 beginning at (\a x, \a y) with the given \a width and \a height.
7155 void QPainter::setViewport(const QRect &r)
7157 #ifdef QT_DEBUG_DRAW
7158 if (qt_show_painter_debug_output)
7159 printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7165 qWarning("QPainter::setViewport: Painter not active");
7169 d->state->vx = r.x();
7170 d->state->vy = r.y();
7171 d->state->vw = r.width();
7172 d->state->vh = r.height();
7174 d->state->VxF = true;
7179 Returns the viewport rectangle.
7181 \sa setViewport(), setViewTransformEnabled()
7184 QRect QPainter::viewport() const
7186 Q_D(const QPainter);
7188 qWarning("QPainter::viewport: Painter not active");
7191 return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7195 Enables view transformations if \a enable is true, or disables
7196 view transformations if \a enable is false.
7198 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7199 Conversion}{Window-Viewport Conversion}
7202 void QPainter::setViewTransformEnabled(bool enable)
7204 #ifdef QT_DEBUG_DRAW
7205 if (qt_show_painter_debug_output)
7206 printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7212 qWarning("QPainter::setViewTransformEnabled: Painter not active");
7216 if (enable == d->state->VxF)
7219 d->state->VxF = enable;
7228 Please use QWidget::render() instead.
7230 Redirects all paint commands for the given paint \a device, to the
7231 \a replacement device. The optional point \a offset defines an
7232 offset within the source device.
7234 The redirection will not be effective until the begin() function
7235 has been called; make sure to call end() for the given \a
7236 device's painter (if any) before redirecting. Call
7237 restoreRedirected() to restore the previous redirection.
7239 \warning Making use of redirections in the QPainter API implies
7240 that QPainter::begin() and QPaintDevice destructors need to hold
7241 a mutex for a short period. This can impact performance. Use of
7242 QWidget::render is strongly encouraged.
7244 \sa redirected(), restoreRedirected()
7246 void QPainter::setRedirected(const QPaintDevice *device,
7247 QPaintDevice *replacement,
7248 const QPoint &offset)
7250 Q_ASSERT(device != 0);
7252 Q_UNUSED(replacement)
7254 qWarning("QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7262 Using QWidget::render() obsoletes the use of this function.
7264 Restores the previous redirection for the given \a device after a
7265 call to setRedirected().
7267 \warning Making use of redirections in the QPainter API implies
7268 that QPainter::begin() and QPaintDevice destructors need to hold
7269 a mutex for a short period. This can impact performance. Use of
7270 QWidget::render is strongly encouraged.
7274 void QPainter::restoreRedirected(const QPaintDevice *device)
7277 qWarning("QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7285 Using QWidget::render() obsoletes the use of this function.
7287 Returns the replacement for given \a device. The optional out
7288 parameter \a offset returns the offset within the replaced device.
7290 \warning Making use of redirections in the QPainter API implies
7291 that QPainter::begin() and QPaintDevice destructors need to hold
7292 a mutex for a short period. This can impact performance. Use of
7293 QWidget::render is strongly encouraged.
7295 \sa setRedirected(), restoreRedirected()
7297 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7304 void qt_format_text(const QFont &fnt, const QRectF &_r,
7305 int tf, const QString& str, QRectF *brect,
7306 int tabstops, int *ta, int tabarraylen,
7309 qt_format_text(fnt, _r,
7311 tabstops, ta, tabarraylen,
7314 void qt_format_text(const QFont &fnt, const QRectF &_r,
7315 int tf, const QTextOption *option, const QString& str, QRectF *brect,
7316 int tabstops, int *ta, int tabarraylen,
7320 Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
7323 tf |= option->alignment();
7324 if (option->wrapMode() != QTextOption::NoWrap)
7325 tf |= Qt::TextWordWrap;
7327 if (option->flags() & QTextOption::IncludeTrailingSpaces)
7328 tf |= Qt::TextIncludeTrailingSpaces;
7330 if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
7331 tf |= Qt::TextExpandTabs;
7334 // we need to copy r here to protect against the case (&r == brect).
7337 bool dontclip = (tf & Qt::TextDontClip);
7338 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
7339 bool singleline = (tf & Qt::TextSingleLine);
7340 bool showmnemonic = (tf & Qt::TextShowMnemonic);
7341 bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
7343 Qt::LayoutDirection layout_direction;
7344 if (tf & Qt::TextForceLeftToRight)
7345 layout_direction = Qt::LeftToRight;
7346 else if (tf & Qt::TextForceRightToLeft)
7347 layout_direction = Qt::RightToLeft;
7349 layout_direction = option->textDirection();
7351 layout_direction = painter->layoutDirection();
7353 layout_direction = Qt::LeftToRight;
7355 tf = QGuiApplicationPrivate::visualAlignment(layout_direction, QFlag(tf));
7357 bool isRightToLeft = layout_direction == Qt::RightToLeft;
7358 bool expandtabs = ((tf & Qt::TextExpandTabs) &&
7359 (((tf & Qt::AlignLeft) && !isRightToLeft) ||
7360 ((tf & Qt::AlignRight) && isRightToLeft)));
7363 tf |= Qt::TextDontPrint;
7365 uint maxUnderlines = 0;
7366 int numUnderlines = 0;
7367 QVarLengthArray<int, 32> underlinePositions(1);
7369 QFontMetricsF fm(fnt);
7372 start_lengthVariant:
7373 bool hasMoreLengthVariants = false;
7374 // compatible behaviour to the old implementation. Replace
7376 int old_offset = offset;
7377 for (; offset < text.length(); offset++) {
7378 QChar chr = text.at(offset);
7379 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
7380 text[offset] = QLatin1Char(' ');
7381 } else if (chr == QLatin1Char('\n')) {
7382 text[offset] = QChar::LineSeparator;
7383 } else if (chr == QLatin1Char('&')) {
7385 } else if (chr == QLatin1Char('\t')) {
7387 text[offset] = QLatin1Char(' ');
7388 } else if (!tabarraylen && !tabstops) {
7389 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
7391 } else if (chr == QChar(ushort(0x9c))) {
7392 // string with multiple length variants
7393 hasMoreLengthVariants = true;
7398 int length = offset - old_offset;
7399 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
7400 underlinePositions.resize(maxUnderlines + 1);
7402 QChar *cout = text.data() + old_offset;
7406 if (*cin == QLatin1Char('&')) {
7412 if (*cin != QLatin1Char('&') && !hidemnmemonic)
7413 underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
7422 // no need to do extra work for underlines if we don't paint
7423 if (tf & Qt::TextDontPrint)
7426 underlinePositions[numUnderlines] = -1;
7430 QString finalText = text.mid(old_offset, length);
7431 QStackTextEngine engine(finalText, fnt);
7433 engine.option = *option;
7436 if (engine.option.tabStop() < 0 && tabstops > 0)
7437 engine.option.setTabStop(tabstops);
7439 if (engine.option.tabs().isEmpty() && ta) {
7441 for (int i = 0; i < tabarraylen; i++)
7442 tabs.append(qreal(ta[i]));
7443 engine.option.setTabArray(tabs);
7446 engine.option.setTextDirection(layout_direction);
7447 if (tf & Qt::AlignJustify)
7448 engine.option.setAlignment(Qt::AlignJustify);
7450 engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
7452 if (!option && (tf & Qt::TextWrapAnywhere))
7453 engine.option.setWrapMode(QTextOption::WrapAnywhere);
7455 if (tf & Qt::TextJustificationForced)
7456 engine.forceJustification = true;
7457 QTextLayout textLayout(&engine);
7458 textLayout.setCacheEnabled(true);
7459 textLayout.engine()->underlinePositions = underlinePositions.data();
7461 if (finalText.isEmpty()) {
7462 height = fm.height();
7464 tf |= Qt::TextDontPrint;
7466 qreal lineWidth = 0x01000000;
7467 if (wordwrap || (tf & Qt::TextJustificationForced))
7468 lineWidth = qMax<qreal>(0, r.width());
7470 tf |= Qt::TextIncludeTrailingSpaces;
7471 textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
7472 textLayout.beginLayout();
7474 qreal leading = fm.leading();
7478 QTextLine l = textLayout.createLine();
7482 l.setLineWidth(lineWidth);
7484 l.setPosition(QPointF(0., height));
7485 height += l.height();
7486 width = qMax(width, l.naturalTextWidth());
7487 if (!dontclip && !brect && height >= r.height())
7490 textLayout.endLayout();
7495 if (tf & Qt::AlignBottom) {
7496 yoff = r.height() - height;
7497 } else if (tf & Qt::AlignVCenter) {
7498 yoff = (r.height() - height)/2;
7500 QTransform::TransformationType type = painter->transform().type();
7501 if (type <= QTransform::TxScale) {
7502 // do the rounding manually to work around inconsistencies
7503 // in the paint engines when drawing on floating point offsets
7504 const qreal scale = painter->transform().m22();
7506 yoff = -qRound(-yoff * scale) / scale;
7510 if (tf & Qt::AlignRight) {
7511 xoff = r.width() - width;
7512 } else if (tf & Qt::AlignHCenter) {
7513 xoff = (r.width() - width)/2;
7515 QTransform::TransformationType type = painter->transform().type();
7516 if (type <= QTransform::TxScale) {
7517 // do the rounding manually to work around inconsistencies
7518 // in the paint engines when drawing on floating point offsets
7519 const qreal scale = painter->transform().m11();
7521 xoff = qRound(xoff * scale) / scale;
7525 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
7527 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
7529 goto start_lengthVariant;
7534 if (!(tf & Qt::TextDontPrint)) {
7535 bool restore = false;
7536 if (!dontclip && !r.contains(bounds)) {
7539 painter->setClipRect(r, Qt::IntersectClip);
7542 for (int i = 0; i < textLayout.lineCount(); i++) {
7543 QTextLine line = textLayout.lineAt(i);
7544 QTextEngine *eng = textLayout.engine();
7545 eng->enableDelayDecorations();
7547 qreal advance = line.horizontalAdvance();
7549 if (tf & Qt::AlignRight) {
7550 xoff = r.width() - advance -
7551 eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
7553 else if (tf & Qt::AlignHCenter)
7554 xoff = (r.width() - advance) / 2;
7556 line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
7557 eng->drawDecorations(painter);
7567 Sets the layout direction used by the painter when drawing text,
7568 to the specified \a direction.
7570 The default is Qt::LayoutDirectionAuto, which will implicitly determine the
7571 direction from the text drawn.
7573 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
7575 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
7579 d->state->layoutDirection = direction;
7583 Returns the layout direction used by the painter when drawing text.
7585 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
7587 Qt::LayoutDirection QPainter::layoutDirection() const
7589 Q_D(const QPainter);
7590 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
7593 QPainterState::QPainterState(const QPainterState *s)
7594 : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
7595 pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
7596 clipRegion(s->clipRegion), clipPath(s->clipPath),
7597 clipOperation(s->clipOperation),
7598 renderHints(s->renderHints), clipInfo(s->clipInfo),
7599 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
7600 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
7601 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
7602 opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
7603 clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
7604 layoutDirection(s->layoutDirection),
7605 composition_mode(s->composition_mode),
7606 emulationSpecifier(s->emulationSpecifier), changeFlags(0)
7608 dirtyFlags = s->dirtyFlags;
7611 QPainterState::QPainterState()
7612 : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
7614 wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
7615 opacity(1), WxF(false), VxF(false), clipEnabled(true),
7616 bgMode(Qt::TransparentMode), painter(0),
7617 layoutDirection(QGuiApplication::layoutDirection()),
7618 composition_mode(QPainter::CompositionMode_SourceOver),
7619 emulationSpecifier(0), changeFlags(0)
7624 QPainterState::~QPainterState()
7628 void QPainterState::init(QPainter *p) {
7629 bgBrush = Qt::white;
7630 bgMode = Qt::TransparentMode;
7634 wx = wy = ww = wh = 0;
7635 vx = vy = vw = vh = 0;
7638 brushOrigin = QPointF(0, 0);
7640 font = deviceFont = QFont();
7641 clipRegion = QRegion();
7642 clipPath = QPainterPath();
7643 clipOperation = Qt::NoClip;
7645 worldMatrix.reset();
7647 layoutDirection = QGuiApplication::layoutDirection();
7648 composition_mode = QPainter::CompositionMode_SourceOver;
7649 emulationSpecifier = 0;
7657 \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
7658 Qt::ImageConversionFlags flags)
7660 Draws the rectangular portion \a source of the given \a image
7661 into the \a target rectangle in the paint device.
7663 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7665 If the image needs to be modified to fit in a lower-resolution
7666 result (e.g. converting from 32-bit to 8-bit), use the \a flags to
7667 specify how you would prefer this to happen.
7672 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 20
7679 \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
7680 Qt::ImageConversionFlags flags)
7683 Draws the rectangular portion \a source of the given \a image
7684 into the \a target rectangle in the paint device.
7686 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7690 \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
7694 Draws the given \a image at the given \a point.
7698 \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
7702 Draws the given \a image at the given \a point.
7706 \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
7707 Qt::ImageConversionFlags flags = 0)
7711 Draws the rectangular portion \a source of the given \a image with
7712 its origin at the given \a point.
7716 \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
7717 Qt::ImageConversionFlags flags = 0)
7720 Draws the rectangular portion \a source of the given \a image with
7721 its origin at the given \a point.
7725 \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
7729 Draws the given \a image into the given \a rectangle.
7731 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7735 \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
7739 Draws the given \a image into the given \a rectangle.
7741 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7745 \fn void QPainter::drawImage(int x, int y, const QImage &image,
7746 int sx, int sy, int sw, int sh,
7747 Qt::ImageConversionFlags flags)
7750 Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
7753 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
7754 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
7755 image that is to be drawn. The default is (0, 0).
7757 (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
7758 The default, (0, 0) (and negative) means all the way to the
7759 bottom-right of the image.
7763 \class QPaintEngineState
7766 \brief The QPaintEngineState class provides information about the
7767 active paint engine's current state.
7770 QPaintEngineState records which properties that have changed since
7771 the last time the paint engine was updated, as well as their
7774 Which properties that have changed can at any time be retrieved
7775 using the state() function. This function returns an instance of
7776 the QPaintEngine::DirtyFlags type which stores an OR combination
7777 of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
7778 enum defines whether a property has changed since the last update
7781 If a property is marked with a dirty flag, its current value can
7782 be retrieved using the corresponding get function:
7787 \header \li Property Flag \li Current Property Value
7788 \row \li QPaintEngine::DirtyBackground \li backgroundBrush()
7789 \row \li QPaintEngine::DirtyBackgroundMode \li backgroundMode()
7790 \row \li QPaintEngine::DirtyBrush \li brush()
7791 \row \li QPaintEngine::DirtyBrushOrigin \li brushOrigin()
7792 \row \li QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
7794 \row \li QPaintEngine::DirtyClipPath \li clipPath()
7795 \row \li QPaintEngine::DirtyClipRegion \li clipRegion()
7796 \row \li QPaintEngine::DirtyCompositionMode \li compositionMode()
7797 \row \li QPaintEngine::DirtyFont \li font()
7798 \row \li QPaintEngine::DirtyTransform \li transform()
7799 \row \li QPaintEngine::DirtyClipEnabled \li isClipEnabled()
7800 \row \li QPaintEngine::DirtyPen \li pen()
7801 \row \li QPaintEngine::DirtyHints \li renderHints()
7804 The QPaintEngineState class also provide the painter() function
7805 which returns a pointer to the painter that is currently updating
7808 An instance of this class, representing the current state of the
7809 active paint engine, is passed as argument to the
7810 QPaintEngine::updateState() function. The only situation in which
7811 you will have to use this class directly is when implementing your
7819 \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
7821 Returns a combination of flags identifying the set of properties
7822 that need to be updated when updating the paint engine's state
7823 (i.e. during a call to the QPaintEngine::updateState() function).
7825 \sa QPaintEngine::updateState()
7830 Returns the pen in the current paint engine state.
7832 This variable should only be used when the state() returns a
7833 combination which includes the QPaintEngine::DirtyPen flag.
7835 \sa state(), QPaintEngine::updateState()
7838 QPen QPaintEngineState::pen() const
7840 return static_cast<const QPainterState *>(this)->pen;
7844 Returns the brush in the current paint engine state.
7846 This variable should only be used when the state() returns a
7847 combination which includes the QPaintEngine::DirtyBrush flag.
7849 \sa state(), QPaintEngine::updateState()
7852 QBrush QPaintEngineState::brush() const
7854 return static_cast<const QPainterState *>(this)->brush;
7858 Returns the brush origin in the current paint engine state.
7860 This variable should only be used when the state() returns a
7861 combination which includes the QPaintEngine::DirtyBrushOrigin flag.
7863 \sa state(), QPaintEngine::updateState()
7866 QPointF QPaintEngineState::brushOrigin() const
7868 return static_cast<const QPainterState *>(this)->brushOrigin;
7872 Returns the background brush in the current paint engine state.
7874 This variable should only be used when the state() returns a
7875 combination which includes the QPaintEngine::DirtyBackground flag.
7877 \sa state(), QPaintEngine::updateState()
7880 QBrush QPaintEngineState::backgroundBrush() const
7882 return static_cast<const QPainterState *>(this)->bgBrush;
7886 Returns the background mode in the current paint engine
7889 This variable should only be used when the state() returns a
7890 combination which includes the QPaintEngine::DirtyBackgroundMode flag.
7892 \sa state(), QPaintEngine::updateState()
7895 Qt::BGMode QPaintEngineState::backgroundMode() const
7897 return static_cast<const QPainterState *>(this)->bgMode;
7901 Returns the font in the current paint engine
7904 This variable should only be used when the state() returns a
7905 combination which includes the QPaintEngine::DirtyFont flag.
7907 \sa state(), QPaintEngine::updateState()
7910 QFont QPaintEngineState::font() const
7912 return static_cast<const QPainterState *>(this)->font;
7919 Returns the matrix in the current paint engine
7922 \note It is advisable to use transform() instead of this function to
7923 preserve the properties of perspective transformations.
7925 This variable should only be used when the state() returns a
7926 combination which includes the QPaintEngine::DirtyTransform flag.
7928 \sa state(), QPaintEngine::updateState()
7931 QMatrix QPaintEngineState::matrix() const
7933 const QPainterState *st = static_cast<const QPainterState *>(this);
7935 return st->matrix.toAffine();
7941 Returns the matrix in the current paint engine state.
7943 This variable should only be used when the state() returns a
7944 combination which includes the QPaintEngine::DirtyTransform flag.
7946 \sa state(), QPaintEngine::updateState()
7950 QTransform QPaintEngineState::transform() const
7952 const QPainterState *st = static_cast<const QPainterState *>(this);
7959 Returns the clip operation in the current paint engine
7962 This variable should only be used when the state() returns a
7963 combination which includes either the QPaintEngine::DirtyClipPath
7964 or the QPaintEngine::DirtyClipRegion flag.
7966 \sa state(), QPaintEngine::updateState()
7969 Qt::ClipOperation QPaintEngineState::clipOperation() const
7971 return static_cast<const QPainterState *>(this)->clipOperation;
7977 Returns whether the coordinate of the fill have been specified
7978 as bounded by the current rendering operation and have to be
7979 resolved (about the currently rendered primitive).
7981 bool QPaintEngineState::brushNeedsResolving() const
7983 const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
7984 return needsResolving(brush);
7991 Returns whether the coordinate of the stroke have been specified
7992 as bounded by the current rendering operation and have to be
7993 resolved (about the currently rendered primitive).
7995 bool QPaintEngineState::penNeedsResolving() const
7997 const QPen &pen = static_cast<const QPainterState *>(this)->pen;
7998 return needsResolving(pen.brush());
8002 Returns the clip region in the current paint engine state.
8004 This variable should only be used when the state() returns a
8005 combination which includes the QPaintEngine::DirtyClipRegion flag.
8007 \sa state(), QPaintEngine::updateState()
8010 QRegion QPaintEngineState::clipRegion() const
8012 return static_cast<const QPainterState *>(this)->clipRegion;
8016 Returns the clip path in the current paint engine state.
8018 This variable should only be used when the state() returns a
8019 combination which includes the QPaintEngine::DirtyClipPath flag.
8021 \sa state(), QPaintEngine::updateState()
8024 QPainterPath QPaintEngineState::clipPath() const
8026 return static_cast<const QPainterState *>(this)->clipPath;
8030 Returns whether clipping is enabled or not in the current paint
8033 This variable should only be used when the state() returns a
8034 combination which includes the QPaintEngine::DirtyClipEnabled
8037 \sa state(), QPaintEngine::updateState()
8040 bool QPaintEngineState::isClipEnabled() const
8042 return static_cast<const QPainterState *>(this)->clipEnabled;
8046 Returns the render hints in the current paint engine state.
8048 This variable should only be used when the state() returns a
8049 combination which includes the QPaintEngine::DirtyHints
8052 \sa state(), QPaintEngine::updateState()
8055 QPainter::RenderHints QPaintEngineState::renderHints() const
8057 return static_cast<const QPainterState *>(this)->renderHints;
8061 Returns the composition mode in the current paint engine state.
8063 This variable should only be used when the state() returns a
8064 combination which includes the QPaintEngine::DirtyCompositionMode
8067 \sa state(), QPaintEngine::updateState()
8070 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8072 return static_cast<const QPainterState *>(this)->composition_mode;
8077 Returns a pointer to the painter currently updating the paint
8081 QPainter *QPaintEngineState::painter() const
8083 return static_cast<const QPainterState *>(this)->painter;
8090 Returns the opacity in the current paint engine state.
8093 qreal QPaintEngineState::opacity() const
8095 return static_cast<const QPainterState *>(this)->opacity;
8101 Sets the world transformation matrix.
8102 If \a combine is true, the specified \a transform is combined with
8103 the current matrix; otherwise it replaces the current matrix.
8105 \sa transform() setWorldTransform()
8108 void QPainter::setTransform(const QTransform &transform, bool combine )
8110 setWorldTransform(transform, combine);
8114 Returns the world transformation matrix.
8116 \sa worldTransform()
8119 const QTransform & QPainter::transform() const
8121 return worldTransform();
8126 Returns the matrix that transforms from logical coordinates to
8127 device coordinates of the platform dependent paint device.
8129 This function is \e only needed when using platform painting
8130 commands on the platform dependent handle (Qt::HANDLE), and the
8131 platform does not do transformations nativly.
8133 The QPaintEngine::PaintEngineFeature enum can be queried to
8134 determine whether the platform performs the transformations or
8137 \sa worldTransform(), QPaintEngine::hasFeature(),
8140 const QTransform & QPainter::deviceTransform() const
8142 Q_D(const QPainter);
8144 qWarning("QPainter::deviceTransform: Painter not active");
8145 return d->fakeState()->transform;
8147 return d->state->matrix;
8152 Resets any transformations that were made using translate(),
8153 scale(), shear(), rotate(), setWorldTransform(), setViewport()
8156 \sa {Coordinate Transformations}
8159 void QPainter::resetTransform()
8162 #ifdef QT_DEBUG_DRAW
8163 if (qt_show_painter_debug_output)
8164 printf("QPainter::resetMatrix()\n");
8167 qWarning("QPainter::resetMatrix: Painter not active");
8171 d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins
8172 d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
8173 d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
8174 d->state->worldMatrix = QTransform();
8175 setMatrixEnabled(false);
8176 setViewTransformEnabled(false);
8178 d->extended->transformChanged();
8180 d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
8184 Sets the world transformation matrix.
8185 If \a combine is true, the specified \a matrix is combined with the current matrix;
8186 otherwise it replaces the current matrix.
8188 \sa transform(), setTransform()
8191 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
8196 qWarning("QPainter::setWorldTransform: Painter not active");
8201 d->state->worldMatrix = matrix * d->state->worldMatrix; // combines
8203 d->state->worldMatrix = matrix; // set new matrix
8205 d->state->WxF = true;
8210 Returns the world transformation matrix.
8213 const QTransform & QPainter::worldTransform() const
8215 Q_D(const QPainter);
8217 qWarning("QPainter::worldTransform: Painter not active");
8218 return d->fakeState()->transform;
8220 return d->state->worldMatrix;
8224 Returns the transformation matrix combining the current
8225 window/viewport and world transformation.
8227 \sa setWorldTransform(), setWindow(), setViewport()
8230 QTransform QPainter::combinedTransform() const
8232 Q_D(const QPainter);
8234 qWarning("QPainter::combinedTransform: Painter not active");
8235 return QTransform();
8237 return d->state->worldMatrix * d->viewTransform();
8243 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
8244 at multiple positions with different scale, rotation and opacity. \a
8245 fragments is an array of \a fragmentCount elements specifying the
8246 parameters used to draw each pixmap fragment. The \a hints
8247 parameter can be used to pass in drawing hints.
8249 This function is potentially faster than multiple calls to drawPixmap(),
8250 since the backend can optimize state changes.
8252 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
8255 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
8256 const QPixmap &pixmap, PixmapFragmentHints hints)
8260 if (!d->engine || pixmap.isNull())
8264 for (int i = 0; i < fragmentCount; ++i) {
8265 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8266 fragments[i].width, fragments[i].height);
8267 if (!(QRectF(pixmap.rect()).contains(sourceRect)))
8268 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
8272 if (d->engine->isExtended()) {
8273 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
8275 qreal oldOpacity = opacity();
8276 QTransform oldTransform = transform();
8278 for (int i = 0; i < fragmentCount; ++i) {
8279 QTransform transform = oldTransform;
8282 if (fragments[i].rotation == 0) {
8283 xOffset = fragments[i].x;
8284 yOffset = fragments[i].y;
8286 transform.translate(fragments[i].x, fragments[i].y);
8287 transform.rotate(fragments[i].rotation);
8289 setOpacity(oldOpacity * fragments[i].opacity);
8290 setTransform(transform);
8292 qreal w = fragments[i].scaleX * fragments[i].width;
8293 qreal h = fragments[i].scaleY * fragments[i].height;
8294 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8295 fragments[i].width, fragments[i].height);
8296 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
8299 setOpacity(oldOpacity);
8300 setTransform(oldTransform);
8306 \class QPainter::PixmapFragment
8308 \brief This class is used in conjunction with the
8309 QPainter::drawPixmapFragments() function to specify how a pixmap, or
8310 sub-rect of a pixmap, is drawn.
8312 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
8313 as a source rectangle within the pixmap passed into the
8314 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
8315 width and \a height are used to calculate the target rectangle that is
8316 drawn. \a x and \a y denotes the center of the target rectangle. The \a
8317 width and \a height in the target rectangle is scaled by the \a scaleX and
8318 \a scaleY values. The resulting target rectangle is then rotated \a
8319 rotation degrees around the \a x, \a y center point.
8321 \sa QPainter::drawPixmapFragments()
8327 This is a convenience function that returns a QPainter::PixmapFragment that is
8328 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
8329 rotation, \a opacity parameters.
8332 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
8333 qreal scaleX, qreal scaleY, qreal rotation,
8336 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
8337 sourceRect.height(), scaleX, scaleY, rotation, opacity};
8342 \variable QPainter::PixmapFragment::x
8343 \brief the x coordinate of center point in the target rectangle.
8347 \variable QPainter::PixmapFragment::y
8348 \brief the y coordinate of the center point in the target rectangle.
8352 \variable QPainter::PixmapFragment::sourceLeft
8353 \brief the left coordinate of the source rectangle.
8357 \variable QPainter::PixmapFragment::sourceTop
8358 \brief the top coordinate of the source rectangle.
8362 \variable QPainter::PixmapFragment::width
8364 \brief the width of the source rectangle and is used to calculate the width
8365 of the target rectangle.
8369 \variable QPainter::PixmapFragment::height
8371 \brief the height of the source rectangle and is used to calculate the
8372 height of the target rectangle.
8376 \variable QPainter::PixmapFragment::scaleX
8377 \brief the horizontal scale of the target rectangle.
8381 \variable QPainter::PixmapFragment::scaleY
8382 \brief the vertical scale of the target rectangle.
8386 \variable QPainter::PixmapFragment::rotation
8388 \brief the rotation of the target rectangle in degrees. The target
8389 rectangle is rotated after it has been scaled.
8393 \variable QPainter::PixmapFragment::opacity
8395 \brief the opacity of the target rectangle, where 0.0 is fully transparent
8396 and 1.0 is fully opaque.
8402 \enum QPainter::PixmapFragmentHint
8404 \value OpaqueHint Indicates that the pixmap fragments to be drawn are
8405 opaque. Opaque fragments are potentially faster to draw.
8407 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
8410 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
8412 p->draw_helper(path, operation);