1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
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,
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);
152 static bool qt_paintengine_supports_transformations(QPaintEngine::Type type)
154 return type == QPaintEngine::OpenGL2
155 || type == QPaintEngine::OpenVG
156 || type == QPaintEngine::OpenGL
157 || type == QPaintEngine::CoreGraphics;
161 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
164 case QInternal::Image:
165 case QInternal::Printer:
166 case QInternal::Picture:
167 // can be drawn onto these devices safely from any thread
174 if (QApplication::testAttribute(Qt::AA_X11InitThreads))
177 if (!extraCondition && QThread::currentThread() != qApp->thread()) {
178 qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
187 void QPainterPrivate::checkEmulation()
190 if (extended->flags() & QPaintEngineEx::DoNotEmulate)
193 bool doEmulation = false;
194 if (state->bgMode == Qt::OpaqueMode)
197 const QGradient *bg = state->brush.gradient();
198 if (bg && bg->coordinateMode() > QGradient::LogicalMode)
201 const QGradient *pg = qpen_brush(state->pen).gradient();
202 if (pg && pg->coordinateMode() > QGradient::LogicalMode)
206 if (extended != emulationEngine) {
207 if (!emulationEngine)
208 emulationEngine = new QEmulationPaintEngine(extended);
209 extended = emulationEngine;
210 extended->setState(state);
212 } else if (emulationEngine == extended) {
213 extended = emulationEngine->real_engine;
218 QPainterPrivate::~QPainterPrivate()
220 delete emulationEngine;
221 for (int i=0; i<states.size(); ++i)
229 QTransform QPainterPrivate::viewTransform() const
232 qreal scaleW = qreal(state->vw)/qreal(state->ww);
233 qreal scaleH = qreal(state->vh)/qreal(state->wh);
234 return QTransform(scaleW, 0, 0, scaleH,
235 state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
243 Returns true if using a shared painter; otherwise false.
245 bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
250 QPainter *sp = pdev->sharedPainter();
254 // Save the current state of the shared painter and assign
255 // the current d_ptr to the shared painter's d_ptr.
257 if (!sp->d_ptr->d_ptrs) {
258 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
259 // redirections within the same paintEvent(), which should be enough
260 // in 99% of all cases). E.g: A renders B which renders C which renders D.
261 sp->d_ptr->d_ptrs_size = 4;
262 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
263 Q_CHECK_PTR(sp->d_ptr->d_ptrs);
264 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
265 // However, to support corner cases we grow the array dynamically if needed.
266 sp->d_ptr->d_ptrs_size <<= 1;
267 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
268 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
270 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
272 q->d_ptr.reset(sp->d_ptr.data());
274 Q_ASSERT(q->d_ptr->state);
276 // Now initialize the painter with correct widget properties.
279 pdev->redirected(&offset);
280 offset += q->d_ptr->engine->coordinateOffset();
282 // Update system rect.
283 q->d_ptr->state->ww = q->d_ptr->state->vw = pdev->width();
284 q->d_ptr->state->wh = q->d_ptr->state->vh = pdev->height();
287 if (q->d_ptr->state->WxF) {
288 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix;
289 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
290 q->d_ptr->state->worldMatrix = QTransform();
291 q->d_ptr->state->WxF = false;
293 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
295 q->d_ptr->updateMatrix();
297 QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
298 if (enginePrivate->currentClipDevice == pdev) {
299 enginePrivate->systemStateChanged();
303 // Update system transform and clip.
304 enginePrivate->currentClipDevice = pdev;
305 enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
309 void QPainterPrivate::detachPainterPrivate(QPainter *q)
311 Q_ASSERT(refcount > 1);
314 QPainterPrivate *original = d_ptrs[--refcount - 1];
316 inDestructor = false;
318 original->inDestructor = true;
319 } else if (!original) {
320 original = new QPainterPrivate(q);
323 d_ptrs[refcount - 1] = 0;
326 q->d_ptr.reset(original);
328 if (emulationEngine) {
329 extended = emulationEngine->real_engine;
330 delete emulationEngine;
336 void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op)
339 if (qt_show_painter_debug_output) {
340 printf("QPainter::drawHelper\n");
344 if (originalPath.isEmpty())
347 QPaintEngine::PaintEngineFeatures gradientStretch =
348 QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
349 | QPaintEngine::ObjectBoundingModeGradients);
351 const bool mustEmulateObjectBoundingModeGradients = extended
352 || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients)
353 && !engine->hasFeature(QPaintEngine::PatternTransform));
355 if (!(state->emulationSpecifier & ~gradientStretch)
356 && !mustEmulateObjectBoundingModeGradients) {
357 drawStretchedGradient(originalPath, op);
359 } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {
360 drawOpaqueBackground(originalPath, op);
366 qreal strokeOffsetX = 0, strokeOffsetY = 0;
368 QPainterPath path = originalPath * state->matrix;
369 QRectF pathBounds = path.boundingRect();
371 bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
373 qreal penWidth = state->pen.widthF();
378 // In case of complex xform
379 if (state->matrix.type() > QTransform::TxScale) {
380 QPainterPathStroker stroker;
381 stroker.setWidth(penWidth);
382 stroker.setJoinStyle(state->pen.joinStyle());
383 stroker.setCapStyle(state->pen.capStyle());
384 QPainterPath stroke = stroker.createStroke(originalPath);
385 strokeBounds = (stroke * state->matrix).boundingRect();
387 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);
388 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);
394 if (!strokeBounds.isEmpty()) {
395 absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
397 absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
398 .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
401 if (q->hasClipping()) {
402 bool hasPerspectiveTransform = false;
403 for (int i = 0; i < state->clipInfo.size(); ++i) {
404 const QPainterClipInfo &info = state->clipInfo.at(i);
405 if (info.matrix.type() == QTransform::TxProject) {
406 hasPerspectiveTransform = true;
410 // avoid mapping QRegions with perspective transforms
411 if (!hasPerspectiveTransform) {
412 // The trick with txinv and invMatrix is done in order to
413 // avoid transforming the clip to logical coordinates, and
414 // then back to device coordinates. This is a problem with
415 // QRegion/QRect based clips, since they use integer
416 // coordinates and converting to/from logical coordinates will
418 bool old_txinv = txinv;
419 QTransform old_invMatrix = invMatrix;
421 invMatrix = QTransform();
422 QPainterPath clipPath = q->clipPath();
423 QRectF r = clipPath.boundingRect().intersected(absPathRect);
424 absPathRect = r.toAlignedRect();
426 invMatrix = old_invMatrix;
430 // qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
431 // devMinX, devMinY, device->width(), device->height());
432 // qDebug() << " - matrix" << state->matrix;
433 // qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
434 // qDebug() << " - path.bounds" << path.boundingRect();
436 if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
439 QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
444 p.d_ptr->helper_device = helper_device;
446 p.setOpacity(state->opacity);
447 p.translate(-absPathRect.x(), -absPathRect.y());
448 p.setTransform(state->matrix, true);
449 p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
450 p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
451 p.setBackground(state->bgBrush);
452 p.setBackgroundMode(state->bgMode);
453 p.setBrushOrigin(state->brushOrigin);
455 p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);
456 p.setRenderHint(QPainter::SmoothPixmapTransform,
457 state->renderHints & QPainter::SmoothPixmapTransform);
459 p.drawPath(originalPath);
462 static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0;
463 if (do_fallback_overlay) {
464 QImage block(8, 8, QImage::Format_ARGB32_Premultiplied);
466 pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
467 pt.drawLine(0, 0, 8, 8);
470 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
472 p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
479 state->matrix = QTransform();
481 extended->transformChanged();
483 state->dirtyFlags |= QPaintEngine::DirtyTransform;
486 engine->drawImage(absPathRect,
488 QRectF(0, 0, absPathRect.width(), absPathRect.height()),
489 Qt::OrderedDither | Qt::OrderedAlphaDither);
493 void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op)
497 q->setBackgroundMode(Qt::TransparentMode);
499 if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
500 q->fillPath(path, state->bgBrush.color());
501 q->fillPath(path, state->brush);
504 if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
505 q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
506 q->strokePath(path, state->pen);
509 q->setBackgroundMode(Qt::OpaqueMode);
512 static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
514 Q_ASSERT(brush.style() >= Qt::LinearGradientPattern
515 && brush.style() <= Qt::ConicalGradientPattern);
517 QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
518 boundingRect.x(), boundingRect.y());
520 QGradient g = *brush.gradient();
521 g.setCoordinateMode(QGradient::LogicalMode);
524 b.setTransform(gradientToUser * b.transform());
528 void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op)
532 const qreal sw = helper_device->width();
533 const qreal sh = helper_device->height();
535 bool changedPen = false;
536 bool changedBrush = false;
537 bool needsFill = false;
539 const QPen pen = state->pen;
540 const QBrush brush = state->brush;
542 const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
543 const QGradient::CoordinateMode brushMode = coordinateMode(brush);
547 // Draw the xformed fill if the brush is a stretch gradient.
548 if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
549 if (brushMode == QGradient::StretchToDeviceMode) {
550 q->setPen(Qt::NoPen);
551 changedPen = pen.style() != Qt::NoPen;
555 const qreal isw = 1.0 / sw;
556 const qreal ish = 1.0 / sh;
557 QTransform inv(isw, 0, 0, ish, 0, 0);
558 engine->drawPath(path * inv);
563 if (brushMode == QGradient::ObjectBoundingMode) {
564 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
565 boundingRect = path.boundingRect();
566 q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
572 if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
573 // Draw the xformed outline if the pen is a stretch gradient.
574 if (penMode == QGradient::StretchToDeviceMode) {
575 q->setPen(Qt::NoPen);
580 engine->drawPath(path);
584 q->setBrush(pen.brush());
588 QPainterPathStroker stroker;
589 stroker.setDashPattern(pen.style());
590 stroker.setWidth(pen.widthF());
591 stroker.setJoinStyle(pen.joinStyle());
592 stroker.setCapStyle(pen.capStyle());
593 stroker.setMiterLimit(pen.miterLimit());
594 QPainterPath stroke = stroker.createStroke(path);
596 const qreal isw = 1.0 / sw;
597 const qreal ish = 1.0 / sh;
598 QTransform inv(isw, 0, 0, ish, 0, 0);
599 engine->drawPath(stroke * inv);
602 if (!needsFill && brush.style() != Qt::NoBrush) {
603 q->setBrush(Qt::NoBrush);
607 if (penMode == QGradient::ObjectBoundingMode) {
608 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
610 // avoid computing the bounding rect twice
611 if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
612 boundingRect = path.boundingRect();
615 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect));
618 } else if (changedPen) {
624 engine->drawPath(path);
626 } else if (needsFill) {
627 if (pen.style() != Qt::NoPen) {
628 q->setPen(Qt::NoPen);
633 engine->drawPath(path);
643 void QPainterPrivate::updateMatrix()
645 state->matrix = state->WxF ? state->worldMatrix : QTransform();
647 state->matrix *= viewTransform();
649 txinv = false; // no inverted matrix
650 state->matrix *= state->redirectionMatrix;
652 extended->transformChanged();
654 state->dirtyFlags |= QPaintEngine::DirtyTransform;
656 // printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
657 // qDebug() << " --- using matrix" << state->matrix << redirection_offset;
661 void QPainterPrivate::updateInvMatrix()
663 Q_ASSERT(txinv == false);
664 txinv = true; // creating inverted matrix
665 invMatrix = state->matrix.inverted();
668 extern bool qt_isExtendedRadialGradient(const QBrush &brush);
670 void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
673 bool linearGradient = false;
674 bool radialGradient = false;
675 bool extendedRadialGradient = false;
676 bool conicalGradient = false;
677 bool patternBrush = false;
679 bool complexXform = false;
683 // Pen and brush properties (we have to check both if one changes because the
684 // one that's unchanged can still be in a state which requires emulation)
685 if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) {
686 // Check Brush stroke emulation
687 if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke))
688 s->emulationSpecifier |= QPaintEngine::BrushStroke;
690 s->emulationSpecifier &= ~QPaintEngine::BrushStroke;
694 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
695 Qt::BrushStyle brushStyle = qbrush_style(s->brush);
696 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
697 alpha = (penBrushStyle != Qt::NoBrush
698 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
699 && !penBrush.isOpaque())
700 || (brushStyle != Qt::NoBrush
701 && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
702 && !s->brush.isOpaque());
703 linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
704 (brushStyle == Qt::LinearGradientPattern));
705 radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
706 (brushStyle == Qt::RadialGradientPattern));
707 extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
708 conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
709 (brushStyle == Qt::ConicalGradientPattern));
710 patternBrush = (((penBrushStyle > Qt::SolidPattern
711 && penBrushStyle < Qt::LinearGradientPattern)
712 || penBrushStyle == Qt::TexturePattern) ||
713 ((brushStyle > Qt::SolidPattern
714 && brushStyle < Qt::LinearGradientPattern)
715 || brushStyle == Qt::TexturePattern));
717 bool penTextureAlpha = false;
718 if (penBrush.style() == Qt::TexturePattern)
719 penTextureAlpha = qHasPixmapTexture(penBrush)
720 ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
721 : penBrush.textureImage().hasAlphaChannel();
722 bool brushTextureAlpha = false;
723 if (s->brush.style() == Qt::TexturePattern) {
724 brushTextureAlpha = qHasPixmapTexture(s->brush)
725 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
726 : s->brush.textureImage().hasAlphaChannel();
728 if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
729 || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
730 && !engine->hasFeature(QPaintEngine::MaskedBrush))
731 s->emulationSpecifier |= QPaintEngine::MaskedBrush;
733 s->emulationSpecifier &= ~QPaintEngine::MaskedBrush;
736 if (s->state() & (QPaintEngine::DirtyHints
737 | QPaintEngine::DirtyOpacity
738 | QPaintEngine::DirtyBackgroundMode)) {
746 qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
748 " - linearGradient: %d\n"
749 " - radialGradient: %d\n"
750 " - conicalGradient: %d\n"
751 " - patternBrush: %d\n"
760 uint(s->renderHints),
765 if (s->state() & QPaintEngine::DirtyTransform) {
766 xform = !s->matrix.isIdentity();
767 complexXform = !s->matrix.isAffine();
768 } else if (s->matrix.type() >= QTransform::TxTranslate) {
770 complexXform = !s->matrix.isAffine();
773 const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone);
774 const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone);
776 const bool patternXform = patternBrush && (xform || brushXform || penXform);
778 // Check alphablending
779 if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend))
780 s->emulationSpecifier |= QPaintEngine::AlphaBlend;
782 s->emulationSpecifier &= ~QPaintEngine::AlphaBlend;
784 // Linear gradient emulation
785 if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill))
786 s->emulationSpecifier |= QPaintEngine::LinearGradientFill;
788 s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
790 // Radial gradient emulation
791 if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
792 s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
794 s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
796 // Conical gradient emulation
797 if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
798 s->emulationSpecifier |= QPaintEngine::ConicalGradientFill;
800 s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill;
803 if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
804 s->emulationSpecifier |= QPaintEngine::PatternBrush;
806 s->emulationSpecifier &= ~QPaintEngine::PatternBrush;
809 if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform))
810 s->emulationSpecifier |= QPaintEngine::PatternTransform;
812 s->emulationSpecifier &= ~QPaintEngine::PatternTransform;
815 if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform))
816 s->emulationSpecifier |= QPaintEngine::PrimitiveTransform;
818 s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform;
820 // Perspective XForms
821 if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform))
822 s->emulationSpecifier |= QPaintEngine::PerspectiveTransform;
824 s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform;
827 if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity))
828 s->emulationSpecifier |= QPaintEngine::ConstantOpacity;
830 s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity;
832 bool gradientStretch = false;
833 bool objectBoundingMode = false;
834 if (linearGradient || conicalGradient || radialGradient) {
835 QGradient::CoordinateMode brushMode = coordinateMode(s->brush);
836 QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush());
838 gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
839 gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
841 objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
842 objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
845 s->emulationSpecifier |= QGradient_StretchToDevice;
847 s->emulationSpecifier &= ~QGradient_StretchToDevice;
849 if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
850 s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients;
852 s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients;
854 // Opaque backgrounds...
855 if (s->bgMode == Qt::OpaqueMode &&
856 (is_pen_transparent(s->pen) || is_brush_transparent(s->brush)))
857 s->emulationSpecifier |= QPaintEngine_OpaqueBackground;
859 s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground;
862 //won't be correct either way because the device can already have
863 // something rendered to it in which case subsequent emulation
864 // on a fully transparent qimage and then blitting the results
865 // won't produce correct results
867 if (state->composition_mode > QPainter::CompositionMode_Xor &&
868 !engine->hasFeature(QPaintEngine::BlendModes))
869 s->emulationSpecifier |= QPaintEngine::BlendModes;
871 s->emulationSpecifier &= ~QPaintEngine::BlendModes;
875 void QPainterPrivate::updateStateImpl(QPainterState *newState)
877 // ### we might have to call QPainter::begin() here...
878 if (!engine->state) {
879 engine->state = newState;
880 engine->setDirty(QPaintEngine::AllDirty);
883 if (engine->state->painter() != newState->painter)
884 // ### this could break with clip regions vs paths.
885 engine->setDirty(QPaintEngine::AllDirty);
887 // Upon restore, revert all changes since last save
888 else if (engine->state != newState)
889 newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
891 // We need to store all changes made so that restore can deal with them
893 newState->changeFlags |= newState->dirtyFlags;
895 updateEmulationSpecifier(newState);
897 // Unset potential dirty background mode
898 newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode
899 | QPaintEngine::DirtyBackground);
901 engine->state = newState;
902 engine->updateState(*newState);
903 engine->clearDirty(QPaintEngine::AllDirty);
907 void QPainterPrivate::updateState(QPainterState *newState)
911 engine->state = newState;
913 } else if (newState->state() || engine->state!=newState) {
914 bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
915 && newState->pen.widthF() == 0;
916 if (setNonCosmeticPen) {
917 // Override the default pen's cosmetic state if the
918 // NonCosmeticDefaultPen render hint is used.
919 QPen oldPen = newState->pen;
920 newState->pen.setWidth(1);
921 newState->pen.setCosmetic(false);
922 newState->dirtyFlags |= QPaintEngine::DirtyPen;
924 updateStateImpl(newState);
926 // Restore the state pen back to its default to preserve visible
928 newState->pen = oldPen;
930 updateStateImpl(newState);
938 \brief The QPainter class performs low-level painting on widgets and
945 QPainter provides highly optimized functions to do most of the
946 drawing GUI programs require. It can draw everything from simple
947 lines to complex shapes like pies and chords. It can also draw
948 aligned text and pixmaps. Normally, it draws in a "natural"
949 coordinate system, but it can also do view and world
950 transformation. QPainter can operate on any object that inherits
951 the QPaintDevice class.
953 The common use of QPainter is inside a widget's paint event:
954 Construct and customize (e.g. set the pen or the brush) the
955 painter. Then draw. Remember to destroy the QPainter object after
956 drawing. For example:
958 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 0
960 The core functionality of QPainter is drawing, but the class also
961 provide several functions that allows you to customize QPainter's
962 settings and its rendering quality, and others that enable
963 clipping. In addition you can control how different shapes are
964 merged together by specifying the painter's composition mode.
966 The isActive() function indicates whether the painter is active. A
967 painter is activated by the begin() function and the constructor
968 that takes a QPaintDevice argument. The end() function, and the
969 destructor, deactivates it.
971 Together with the QPaintDevice and QPaintEngine classes, QPainter
972 form the basis for Qt's paint system. QPainter is the class used
973 to perform drawing operations. QPaintDevice represents a device
974 that can be painted on using a QPainter. QPaintEngine provides the
975 interface that the painter uses to draw onto different types of
976 devices. If the painter is active, device() returns the paint
977 device on which the painter paints, and paintEngine() returns the
978 paint engine that the painter is currently operating on. For more
979 information, see the \l {Paint System}.
981 Sometimes it is desirable to make someone else paint on an unusual
982 QPaintDevice. QPainter supports a static function to do this,
985 \warning When the paintdevice is a widget, QPainter can only be
986 used inside a paintEvent() function or in a function called by
987 paintEvent(); that is unless the Qt::WA_PaintOutsidePaintEvent
988 widget attribute is set. On Mac OS X and Windows, you can only
989 paint in a paintEvent() function regardless of this attribute's
996 There are several settings that you can customize to make QPainter
997 draw according to your preferences:
1001 \o font() is the font used for drawing text. If the painter
1002 isActive(), you can retrieve information about the currently set
1003 font, and its metrics, using the fontInfo() and fontMetrics()
1004 functions respectively.
1006 \o brush() defines the color or pattern that is used for filling
1009 \o pen() defines the color or stipple that is used for drawing
1010 lines or boundaries.
1012 \o backgroundMode() defines whether there is a background() or
1013 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
1015 \o background() only applies when backgroundMode() is \l
1016 Qt::OpaqueMode and pen() is a stipple. In that case, it
1017 describes the color of the background pixels in the stipple.
1019 \o brushOrigin() defines the origin of the tiled brushes, normally
1020 the origin of widget's background.
1022 \o viewport(), window(), worldTransform() make up the painter's coordinate
1023 transformation system. For more information, see the \l
1024 {Coordinate Transformations} section and the \l {Coordinate
1025 System} documentation.
1027 \o hasClipping() tells whether the painter clips at all. (The paint
1028 device clips, too.) If the painter clips, it clips to clipRegion().
1030 \o layoutDirection() defines the layout direction used by the
1031 painter when drawing text.
1033 \o worldMatrixEnabled() tells whether world transformation is enabled.
1035 \o viewTransformEnabled() tells whether view transformation is
1040 Note that some of these settings mirror settings in some paint
1041 devices, e.g. QWidget::font(). The QPainter::begin() function (or
1042 equivalently the QPainter constructor) copies these attributes
1043 from the paint device.
1045 You can at any time save the QPainter's state by calling the
1046 save() function which saves all the available settings on an
1047 internal stack. The restore() function pops them back.
1051 QPainter provides functions to draw most primitives: drawPoint(),
1052 drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1053 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1054 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
1055 convenience functions, drawRects() and drawLines(), draw the given
1056 number of rectangles or lines in the given array of \l
1057 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1060 The QPainter class also provides the fillRect() function which
1061 fills the given QRect, with the given QBrush, and the eraseRect()
1062 function that erases the area inside the given rectangle.
1064 All of these functions have both integer and floating point
1069 \o \inlineimage qpainter-basicdrawing.png
1071 \bold {Basic Drawing Example}
1073 The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1074 display basic graphics primitives in a variety of styles using the
1079 If you need to draw a complex shape, especially if you need to do
1080 so repeatedly, consider creating a QPainterPath and drawing it
1086 \bold {Painter Paths example}
1088 The QPainterPath class provides a container for painting
1089 operations, enabling graphical shapes to be constructed and
1092 The \l {painting/painterpaths}{Painter Paths} example shows how
1093 painter paths can be used to build complex shapes for rendering.
1095 \o \inlineimage qpainter-painterpaths.png
1098 QPainter also provides the fillPath() function which fills the
1099 given QPainterPath with the given QBrush, and the strokePath()
1100 function that draws the outline of the given path (i.e. strokes
1103 See also the \l {demos/deform}{Vector Deformation} demo which
1104 shows how to use advanced vector techniques to draw text using a
1105 QPainterPath, the \l {demos/gradients}{Gradients} demo which shows
1106 the different types of gradients that are available in Qt, and the \l
1107 {demos/pathstroke}{Path Stroking} demo which shows Qt's built-in
1108 dash patterns and shows how custom patterns can be used to extend
1109 the range of available patterns.
1113 \o \l {demos/deform}{Vector Deformation}
1114 \o \l {demos/gradients}{Gradients}
1115 \o \l {demos/pathstroke}{Path Stroking}
1117 \o \inlineimage qpainter-vectordeformation.png
1118 \o \inlineimage qpainter-gradients.png
1119 \o \inlineimage qpainter-pathstroking.png
1123 There are functions to draw pixmaps/images, namely drawPixmap(),
1124 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1125 produce the same result, except that drawPixmap() is faster
1126 on-screen while drawImage() may be faster on a QPrinter or other
1129 Text drawing is done using drawText(). When you need
1130 fine-grained positioning, boundingRect() tells you where a given
1131 drawText() command will draw.
1133 There is a drawPicture() function that draws the contents of an
1134 entire QPicture. The drawPicture() function is the only function
1135 that disregards all the painter's settings as QPicture has its own
1138 \section1 Rendering Quality
1140 To get the optimal rendering result using QPainter, you should use
1141 the platform independent QImage as paint device; i.e. using QImage
1142 will ensure that the result has an identical pixel representation
1145 The QPainter class also provides a means of controlling the
1146 rendering quality through its RenderHint enum and the support for
1147 floating point precision: All the functions for drawing primitives
1148 has a floating point version. These are often used in combination
1149 with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1153 \o \inlineimage qpainter-concentriccircles.png
1155 \bold {Concentric Circles Example}
1157 The \l {painting/concentriccircles}{Concentric Circles} example
1158 shows the improved rendering quality that can be obtained using
1159 floating point precision and anti-aliasing when drawing custom
1162 The application's main window displays several widgets which are
1163 drawn using the various combinations of precision and
1168 The RenderHint enum specifies flags to QPainter that may or may
1169 not be respected by any given engine. \l
1170 {RenderHint}{QPainter::Antialiasing} indicates that the engine
1171 should antialias edges of primitives if possible, \l
1172 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1173 should antialias text if possible, and the \l
1174 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1175 engine should use a smooth pixmap transformation algorithm.
1176 \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
1177 indicating that the engine should use fragment programs and offscreen
1178 rendering for antialiasing.
1180 The renderHints() function returns a flag that specifies the
1181 rendering hints that are set for this painter. Use the
1182 setRenderHint() function to set or clear the currently set
1185 \section1 Coordinate Transformations
1187 Normally, the QPainter operates on the device's own coordinate
1188 system (usually pixels), but QPainter has good support for
1189 coordinate transformations.
1193 \o nop \o rotate() \o scale() \o translate()
1195 \o \inlineimage qpainter-clock.png
1196 \o \inlineimage qpainter-rotation.png
1197 \o \inlineimage qpainter-scale.png
1198 \o \inlineimage qpainter-translation.png
1201 The most commonly used transformations are scaling, rotation,
1202 translation and shearing. Use the scale() function to scale the
1203 coordinate system by a given offset, the rotate() function to
1204 rotate it clockwise and translate() to translate it (i.e. adding a
1205 given offset to the points). You can also twist the coordinate
1206 system around the origin using the shear() function. See the \l
1207 {demos/affine}{Affine Transformations} demo for a visualization of
1208 a sheared coordinate system.
1210 See also the \l {painting/transformations}{Transformations}
1211 example which shows how transformations influence the way that
1212 QPainter renders graphics primitives. In particular it shows how
1213 the order of transformations affects the result.
1218 \bold {Affine Transformations Demo}
1220 The \l {demos/affine}{Affine Transformations} demo show Qt's
1221 ability to perform affine transformations on painting
1222 operations. The demo also allows the user to experiment with the
1223 transformation operations and see the results immediately.
1225 \o \inlineimage qpainter-affinetransformations.png
1228 All the tranformation operations operate on the transformation
1229 worldTransform(). A matrix transforms a point in the plane to another
1230 point. For more information about the transformation matrix, see
1231 the \l {Coordinate System} and QTransform documentation.
1233 The setWorldTransform() function can replace or add to the currently
1234 set worldTransform(). The resetTransform() function resets any
1235 transformations that were made using translate(), scale(),
1236 shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1237 functions. The deviceTransform() returns the matrix that transforms
1238 from logical coordinates to device coordinates of the platform
1239 dependent paint device. The latter function is only needed when
1240 using platform painting commands on the platform dependent handle,
1241 and the platform does not do transformations nativly.
1243 When drawing with QPainter, we specify points using logical
1244 coordinates which then are converted into the physical coordinates
1245 of the paint device. The mapping of the logical coordinates to the
1246 physical coordinates are handled by QPainter's combinedTransform(), a
1247 combination of viewport() and window() and worldTransform(). The
1248 viewport() represents the physical coordinates specifying an
1249 arbitrary rectangle, the window() describes the same rectangle in
1250 logical coordinates, and the worldTransform() is identical with the
1251 transformation matrix.
1253 See also \l {Coordinate System}
1257 QPainter can clip any drawing operation to a rectangle, a region,
1258 or a vector path. The current clip is available using the
1259 functions clipRegion() and clipPath(). Whether paths or regions are
1260 preferred (faster) depends on the underlying paintEngine(). For
1261 example, the QImage paint engine prefers paths while the X11 paint
1262 engine prefers regions. Setting a clip is done in the painters
1263 logical coordinates.
1265 After QPainter's clipping, the paint device may also clip. For
1266 example, most widgets clip away the pixels used by child widgets,
1267 and most printers clip away an area near the edges of the paper.
1268 This additional clipping is not reflected by the return value of
1269 clipRegion() or hasClipping().
1271 \section1 Composition Modes
1272 \target Composition Modes
1274 QPainter provides the CompositionMode enum which defines the
1275 Porter-Duff rules for digital image compositing; it describes a
1276 model for combining the pixels in one image, the source, with the
1277 pixels in another image, the destination.
1279 The two most common forms of composition are \l
1280 {QPainter::CompositionMode}{Source} and \l
1281 {QPainter::CompositionMode}{SourceOver}. \l
1282 {QPainter::CompositionMode}{Source} is used to draw opaque objects
1283 onto a paint device. In this mode, each pixel in the source
1284 replaces the corresponding pixel in the destination. In \l
1285 {QPainter::CompositionMode}{SourceOver} composition mode, the
1286 source object is transparent and is drawn on top of the
1289 Note that composition transformation operates pixelwise. For that
1290 reason, there is a difference between using the graphic primitive
1291 itself and its bounding rectangle: The bounding rect contains
1292 pixels with alpha == 0 (i.e the pixels surrounding the
1293 primitive). These pixels will overwrite the other image's pixels,
1294 affectively clearing those, while the primitive only overwrites
1299 \o \inlineimage qpainter-compositiondemo.png
1302 \bold {Composition Modes Demo}
1304 The \l {demos/composition}{Composition Modes} demo, available in
1305 Qt's demo directory, allows you to experiment with the various
1306 composition modes and see the results immediately.
1310 \section1 Limitations
1313 If you are using coordinates with Qt's raster-based paint engine, it is
1314 important to note that, while coordinates greater than +/- 2\sup 15 can
1315 be used, any painting performed with coordinates outside this range is not
1316 guaranteed to be shown; the drawing may be clipped. This is due to the
1317 use of \c{short int} in the implementation.
1319 The outlines generated by Qt's stroker are only an approximation when dealing
1320 with curved shapes. It is in most cases impossible to represent the outline of
1321 a bezier curve segment using another bezier curve segment, and so Qt approximates
1322 the curve outlines by using several smaller curves. For performance reasons there
1323 is a limit to how many curves Qt uses for these outlines, and thus when using
1324 large pen widths or scales the outline error increases. To generate outlines with
1325 smaller errors it is possible to use the QPainterPathStroker class, which has the
1326 setCurveThreshold member function which let's the user specify the error tolerance.
1327 Another workaround is to convert the paths to polygons first and then draw the
1330 \section1 Performance
1332 QPainter is a rich framework that allows developers to do a great
1333 variety of graphical operations, such as gradients, composition
1334 modes and vector graphics. And QPainter can do this across a
1335 variety of different hardware and software stacks. Naturally the
1336 underlying combination of hardware and software has some
1337 implications for performance, and ensuring that every single
1338 operation is fast in combination with all the various combinations
1339 of composition modes, brushes, clipping, transformation, etc, is
1340 close to an impossible task because of the number of
1341 permutations. As a compromise we have selected a subset of the
1342 QPainter API and backends, where performance is guaranteed to be as
1343 good as we can sensibly get it for the given combination of
1344 hardware and software.
1346 The backends we focus on as high-performance engines are:
1350 \o Raster - This backend implements all rendering in pure software
1351 and is always used to render into QImages. For optimal performance
1352 only use the format types QImage::Format_ARGB32_Premultiplied,
1353 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1354 including QImage::Format_ARGB32, has significantly worse
1355 performance. This engine is used by default for QWidget and QPixmap.
1357 \o OpenGL 2.0 (ES) - This backend is the primary backend for
1358 hardware accelerated graphics. It can be run on desktop machines
1359 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1360 specification. This includes most graphics chips produced in the
1361 last couple of years. The engine can be enabled by using QPainter
1362 onto a QGLWidget or by passing \c {-graphicssystem opengl} on the
1363 command line when the underlying system supports it.
1365 \o OpenVG - This backend implements the Khronos standard for 2D
1366 and Vector Graphics. It is primarily for embedded devices with
1367 hardware support for OpenVG. The engine can be enabled by
1368 passing \c {-graphicssystem openvg} on the command line when
1369 the underlying system supports it.
1373 These operations are:
1377 \o Simple transformations, meaning translation and scaling, pluss
1378 0, 90, 180, 270 degree rotations.
1380 \o \c drawPixmap() in combination with simple transformations and
1381 opacity with non-smooth transformation mode
1382 (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1384 \o Rectangle fills with solid color, two-color linear gradients
1385 and simple transforms.
1387 \o Rectangular clipping with simple transformations and intersect
1390 \o Composition Modes \c QPainter::CompositionMode_Source and
1391 QPainter::CompositionMode_SourceOver
1393 \o Rounded rectangle filling using solid color and two-color
1394 linear gradients fills.
1396 \o 3x3 patched pixmaps, via qDrawBorderPixmap.
1400 This list gives an indication of which features to safely use in
1401 an application where performance is critical. For certain setups,
1402 other operations may be fast too, but before making extensive use
1403 of them, it is recommended to benchmark and verify them on the
1404 system where the software will run in the end. There are also
1405 cases where expensive operations are ok to use, for instance when
1406 the result is cached in a QPixmap.
1408 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
1409 {Drawing Utility Functions}
1413 \enum QPainter::RenderHint
1415 Renderhints are used to specify flags to QPainter that may or
1416 may not be respected by any given engine.
1418 \value Antialiasing Indicates that the engine should antialias
1419 edges of primitives if possible.
1421 \value TextAntialiasing Indicates that the engine should antialias
1422 text if possible. To forcibly disable antialiasing for text, do not
1423 use this hint. Instead, set QFont::NoAntialias on your font's style
1426 \value SmoothPixmapTransform Indicates that the engine should use
1427 a smooth pixmap transformation algorithm (such as bilinear) rather
1428 than nearest neighbor.
1430 \value HighQualityAntialiasing An OpenGL-specific rendering hint
1431 indicating that the engine should use fragment programs and offscreen
1432 rendering for antialiasing.
1434 \value NonCosmeticDefaultPen The engine should interpret pens with a width
1435 of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
1436 pen with a width of 1.
1438 \sa renderHints(), setRenderHint(), {QPainter#Rendering
1439 Quality}{Rendering Quality}, {Concentric Circles Example}
1444 Constructs a painter.
1449 QPainter::QPainter()
1450 : d_ptr(new QPainterPrivate(this))
1455 \fn QPainter::QPainter(QPaintDevice *device)
1457 Constructs a painter that begins painting the paint \a device
1460 This constructor is convenient for short-lived painters, e.g. in a
1461 QWidget::paintEvent() and should be used only once. The
1462 constructor calls begin() for you and the QPainter destructor
1463 automatically calls end().
1465 Here's an example using begin() and end():
1466 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 1
1468 The same example using this constructor:
1469 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 2
1471 Since the constructor cannot provide feedback when the initialization
1472 of the painter failed you should rather use begin() and end() to paint
1473 on external devices, e.g. printers.
1478 QPainter::QPainter(QPaintDevice *pd)
1482 if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1483 d_ptr.reset(new QPainterPrivate(this));
1490 Destroys the painter.
1492 QPainter::~QPainter()
1494 d_ptr->inDestructor = true;
1498 else if (d_ptr->refcount > 1)
1499 d_ptr->detachPainterPrivate(this);
1501 // don't throw anything in the destructor.
1504 // Make sure we haven't messed things up.
1505 Q_ASSERT(d_ptr->inDestructor);
1506 d_ptr->inDestructor = false;
1507 Q_ASSERT(d_ptr->refcount == 1);
1509 free(d_ptr->d_ptrs);
1514 Returns the paint device on which this painter is currently
1515 painting, or 0 if the painter is not active.
1520 QPaintDevice *QPainter::device() const
1522 Q_D(const QPainter);
1523 if (isActive() && d->engine->d_func()->currentClipDevice)
1524 return d->engine->d_func()->currentClipDevice;
1525 return d->original_device;
1529 Returns true if begin() has been called and end() has not yet been
1530 called; otherwise returns false.
1532 \sa begin(), QPaintDevice::paintingActive()
1535 bool QPainter::isActive() const
1537 Q_D(const QPainter);
1542 Initializes the painters pen, background and font to the same as
1543 the given \a paint device.
1547 \sa begin(), {QPainter#Settings}{Settings}
1549 void QPainter::initFrom(const QPaintDevice *device)
1551 Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0");
1554 qWarning("QPainter::initFrom: Painter not active, aborted");
1561 d->extended->penChanged();
1562 } else if (d->engine) {
1563 d->engine->setDirty(QPaintEngine::DirtyPen);
1564 d->engine->setDirty(QPaintEngine::DirtyBrush);
1565 d->engine->setDirty(QPaintEngine::DirtyFont);
1571 Saves the current painter state (pushes the state onto a stack). A
1572 save() must be followed by a corresponding restore(); the end()
1573 function unwinds the stack.
1578 void QPainter::save()
1580 #ifdef QT_DEBUG_DRAW
1581 if (qt_show_painter_debug_output)
1582 printf("QPainter::save()\n");
1586 qWarning("QPainter::save: Painter not active");
1591 d->state = d->extended->createState(d->states.back());
1592 d->extended->setState(d->state);
1594 d->updateState(d->state);
1595 d->state = new QPainterState(d->states.back());
1596 d->engine->state = d->state;
1598 d->states.push_back(d->state);
1602 Restores the current painter state (pops a saved state off the
1608 void QPainter::restore()
1610 #ifdef QT_DEBUG_DRAW
1611 if (qt_show_painter_debug_output)
1612 printf("QPainter::restore()\n");
1615 if (d->states.size()<=1) {
1616 qWarning("QPainter::restore: Unbalanced save/restore");
1618 } else if (!d->engine) {
1619 qWarning("QPainter::restore: Painter not active");
1623 QPainterState *tmp = d->state;
1624 d->states.pop_back();
1625 d->state = d->states.back();
1629 d->checkEmulation();
1630 d->extended->setState(d->state);
1635 // trigger clip update if the clip path/region has changed since
1637 if (!d->state->clipInfo.isEmpty()
1638 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1639 // reuse the tmp state to avoid any extra allocs...
1640 tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1641 tmp->clipOperation = Qt::NoClip;
1642 tmp->clipPath = QPainterPath();
1643 d->engine->updateState(*tmp);
1644 // replay the list of clip states,
1645 for (int i=0; i<d->state->clipInfo.size(); ++i) {
1646 const QPainterClipInfo &info = d->state->clipInfo.at(i);
1647 tmp->matrix = info.matrix;
1648 tmp->matrix *= d->state->redirectionMatrix;
1649 tmp->clipOperation = info.operation;
1650 if (info.clipType == QPainterClipInfo::RectClip) {
1651 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1652 tmp->clipRegion = info.rect;
1653 } else if (info.clipType == QPainterClipInfo::RegionClip) {
1654 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1655 tmp->clipRegion = info.region;
1656 } else { // clipType == QPainterClipInfo::PathClip
1657 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1658 tmp->clipPath = info.path;
1660 d->engine->updateState(*tmp);
1664 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1665 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1666 tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1667 tmp->changeFlags |= QPaintEngine::DirtyTransform;
1670 d->updateState(d->state);
1677 \fn bool QPainter::begin(QPaintDevice *device)
1679 Begins painting the paint \a device and returns true if
1680 successful; otherwise returns false.
1682 Notice that all painter settings (setPen(), setBrush() etc.) are reset
1683 to default values when begin() is called.
1685 The errors that can occur are serious problems, such as these:
1687 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 3
1689 Note that most of the time, you can use one of the constructors
1690 instead of begin(), and that end() is automatically done at
1693 \warning A paint device can only be painted by one painter at a
1696 \warning Painting on a QImage with the format
1697 QImage::Format_Indexed8 is not supported.
1699 \sa end(), QPainter()
1702 static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1711 bool QPainter::begin(QPaintDevice *pd)
1715 if (pd->painters > 0) {
1716 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1720 if (d_ptr->engine) {
1721 qWarning("QPainter::begin: Painter already active");
1725 if (QPainterPrivate::attachPainterPrivate(this, pd))
1730 d->helper_device = pd;
1731 d->original_device = pd;
1733 QPoint redirectionOffset;
1734 QPaintDevice *rpd = pd->redirected(&redirectionOffset);
1738 #ifdef QT_DEBUG_DRAW
1739 if (qt_show_painter_debug_output)
1740 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1743 if (pd->devType() == QInternal::Pixmap)
1744 static_cast<QPixmap *>(pd)->detach();
1745 else if (pd->devType() == QInternal::Image)
1746 static_cast<QImage *>(pd)->detach();
1748 d->engine = pd->paintEngine();
1751 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1757 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1758 if (d->emulationEngine)
1759 d->emulationEngine->real_engine = d->extended;
1761 // Setup new state...
1762 Q_ASSERT(!d->state);
1763 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1764 d->state->painter = this;
1765 d->states.push_back(d->state);
1767 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1768 d->state->brushOrigin = QPointF();
1770 // Slip a painter state into the engine before we do any other operations
1772 d->extended->setState(d->state);
1774 d->engine->state = d->state;
1776 switch (pd->devType()) {
1778 // is this needed any more??
1779 case QInternal::Widget:
1781 const QWidget *widget = static_cast<const QWidget *>(pd);
1784 const bool paintOutsidePaintEvent = widget->testAttribute(Qt::WA_PaintOutsidePaintEvent);
1785 const bool inPaintEvent = widget->testAttribute(Qt::WA_WState_InPaintEvent);
1787 // Adjust offset for alien widgets painting outside the paint event.
1788 if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
1789 && widget->testAttribute(Qt::WA_WState_Created)) {
1790 const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
1791 d->state->redirectionMatrix.translate(offset.x(), offset.y());
1796 case QInternal::Pixmap:
1798 QPixmap *pm = static_cast<QPixmap *>(pd);
1801 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1802 qt_cleanup_painter_state(d);
1806 if (pm->depth() == 1) {
1807 d->state->pen = QPen(Qt::color1);
1808 d->state->brush = QBrush(Qt::color0);
1812 case QInternal::Image:
1814 QImage *img = static_cast<QImage *>(pd);
1816 if (img->isNull()) {
1817 qWarning("QPainter::begin: Cannot paint on a null image");
1818 qt_cleanup_painter_state(d);
1820 } else if (img->format() == QImage::Format_Indexed8) {
1821 // Painting on indexed8 images is not supported.
1822 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1823 qt_cleanup_painter_state(d);
1826 if (img->depth() == 1) {
1827 d->state->pen = QPen(Qt::color1);
1828 d->state->brush = QBrush(Qt::color0);
1835 if (d->state->ww == 0) // For compat with 3.x painter defaults
1836 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1838 d->engine->setPaintDevice(pd);
1840 bool begun = d->engine->begin(pd);
1842 qWarning("QPainter::begin(): Returned false");
1843 if (d->engine->isActive()) {
1846 qt_cleanup_painter_state(d);
1850 d->engine->setActive(begun);
1853 // Copy painter properties from original paint device,
1854 // required for QPixmap::grabWidget()
1855 if (d->original_device->devType() == QInternal::Widget) {
1856 initFrom(d->original_device);
1858 d->state->layoutDirection = Qt::LayoutDirectionAuto;
1859 // make sure we have a font compatible with the paintdevice
1860 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1863 QRect systemRect = d->engine->systemRect();
1864 if (!systemRect.isEmpty()) {
1865 d->state->ww = d->state->vw = systemRect.width();
1866 d->state->wh = d->state->vh = systemRect.height();
1868 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1869 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1872 const QPoint coordinateOffset = d->engine->coordinateOffset();
1873 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1875 Q_ASSERT(d->engine->isActive());
1877 if (!d->state->redirectionMatrix.isIdentity())
1880 Q_ASSERT(d->engine->isActive());
1881 d->state->renderHints = QPainter::TextAntialiasing;
1882 ++d->device->painters;
1884 d->state->emulationSpecifier = 0;
1890 Ends painting. Any resources used while painting are released. You
1891 don't normally need to call this since it is called by the
1894 Returns true if the painter is no longer active; otherwise returns false.
1896 \sa begin(), isActive()
1899 bool QPainter::end()
1901 #ifdef QT_DEBUG_DRAW
1902 if (qt_show_painter_debug_output)
1903 printf("QPainter::end()\n");
1908 qWarning("QPainter::end: Painter not active, aborted");
1909 qt_cleanup_painter_state(d);
1913 if (d->refcount > 1) {
1914 d->detachPainterPrivate(this);
1920 if (d->engine->isActive()) {
1921 ended = d->engine->end();
1924 --d->device->painters;
1925 if (d->device->painters == 0) {
1926 d->engine->setPaintDevice(0);
1927 d->engine->setActive(false);
1931 if (d->states.size() > 1) {
1932 qWarning("QPainter::end: Painter ended with %d saved states",
1936 if (d->engine->autoDestruct()) {
1940 if (d->emulationEngine) {
1941 delete d->emulationEngine;
1942 d->emulationEngine = 0;
1949 qt_cleanup_painter_state(d);
1956 Returns the paint engine that the painter is currently operating
1957 on if the painter is active; otherwise 0.
1961 QPaintEngine *QPainter::paintEngine() const
1963 Q_D(const QPainter);
1970 Flushes the painting pipeline and prepares for the user issuing commands
1971 directly to the underlying graphics context. Must be followed by a call to
1972 endNativePainting().
1974 Note that only the states the underlying paint engine changes will be reset
1975 to their respective default states. The states we reset may change from
1976 release to release. The following states are currently reset in the OpenGL
1980 \i blending is disabled
1981 \i the depth, stencil and scissor tests are disabled
1982 \i the active texture unit is reset to 0
1983 \i the depth mask, depth function and the clear depth are reset to their
1985 \i the stencil mask, stencil operation and stencil function are reset to
1986 their default values
1987 \i the current color is reset to solid white
1990 If, for example, the OpenGL polygon mode is changed by the user inside a
1991 beginNativePaint()/endNativePainting() block, it will not be reset to the
1992 default state by endNativePainting(). Here is an example that shows
1993 intermixing of painter commands and raw OpenGL commands:
1995 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
1997 \sa endNativePainting()
1999 void QPainter::beginNativePainting()
2003 qWarning("QPainter::beginNativePainting: Painter not active");
2008 d->extended->beginNativePainting();
2014 Restores the painter after manually issuing native painting commands. Lets
2015 the painter restore any native state that it relies on before calling any
2016 other painter commands.
2018 \sa beginNativePainting()
2020 void QPainter::endNativePainting()
2022 Q_D(const QPainter);
2024 qWarning("QPainter::beginNativePainting: Painter not active");
2029 d->extended->endNativePainting();
2031 d->engine->syncState();
2035 Returns the font metrics for the painter if the painter is
2036 active. Otherwise, the return value is undefined.
2038 \sa font(), isActive(), {QPainter#Settings}{Settings}
2041 QFontMetrics QPainter::fontMetrics() const
2043 Q_D(const QPainter);
2045 qWarning("QPainter::fontMetrics: Painter not active");
2046 return QFontMetrics(QFont());
2048 return QFontMetrics(d->state->font);
2053 Returns the font info for the painter if the painter is
2054 active. Otherwise, the return value is undefined.
2056 \sa font(), isActive(), {QPainter#Settings}{Settings}
2059 QFontInfo QPainter::fontInfo() const
2061 Q_D(const QPainter);
2063 qWarning("QPainter::fontInfo: Painter not active");
2064 return QFontInfo(QFont());
2066 return QFontInfo(d->state->font);
2072 Returns the opacity of the painter. The default value is
2076 qreal QPainter::opacity() const
2078 Q_D(const QPainter);
2080 qWarning("QPainter::opacity: Painter not active");
2083 return d->state->opacity;
2089 Sets the opacity of the painter to \a opacity. The value should
2090 be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2091 1.0 is fully opaque.
2093 Opacity set on the painter will apply to all drawing operations
2097 void QPainter::setOpacity(qreal opacity)
2102 qWarning("QPainter::setOpacity: Painter not active");
2106 opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2108 if (opacity == d->state->opacity)
2111 d->state->opacity = opacity;
2114 d->extended->opacityChanged();
2116 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2121 Returns the currently set brush origin.
2123 \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2126 QPoint QPainter::brushOrigin() const
2128 Q_D(const QPainter);
2130 qWarning("QPainter::brushOrigin: Painter not active");
2133 return QPointF(d->state->brushOrigin).toPoint();
2137 \fn void QPainter::setBrushOrigin(const QPointF &position)
2139 Sets the brush origin to \a position.
2141 The brush origin specifies the (0, 0) coordinate of the painter's
2144 Note that while the brushOrigin() was necessary to adopt the
2145 parent's background for a widget in Qt 3, this is no longer the
2146 case since the Qt 4 painter doesn't paint the background unless
2147 you explicitly tell it to do so by setting the widget's \l
2148 {QWidget::autoFillBackground}{autoFillBackground} property to
2151 \sa brushOrigin(), {QPainter#Settings}{Settings}
2154 void QPainter::setBrushOrigin(const QPointF &p)
2157 #ifdef QT_DEBUG_DRAW
2158 if (qt_show_painter_debug_output)
2159 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2163 qWarning("QPainter::setBrushOrigin: Painter not active");
2167 d->state->brushOrigin = p;
2170 d->extended->brushOriginChanged();
2174 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2178 \fn void QPainter::setBrushOrigin(const QPoint &position)
2181 Sets the brush's origin to the given \a position.
2185 \fn void QPainter::setBrushOrigin(int x, int y)
2189 Sets the brush's origin to point (\a x, \a y).
2193 \enum QPainter::CompositionMode
2195 Defines the modes supported for digital image compositing.
2196 Composition modes are used to specify how the pixels in one image,
2197 the source, are merged with the pixel in another image, the
2200 Please note that the bitwise raster operation modes, denoted with
2201 a RasterOp prefix, are only natively supported in the X11 and
2202 raster paint engines. This means that the only way to utilize
2203 these modes on the Mac is via a QImage. The RasterOp denoted blend
2204 modes are \e not supported for pens and brushes with alpha
2205 components. Also, turning on the QPainter::Antialiasing render
2206 hint will effectively disable the RasterOp modes.
2209 \image qpainter-compositionmode1.png
2210 \image qpainter-compositionmode2.png
2212 The most common type is SourceOver (often referred to as just
2213 alpha blending) where the source pixel is blended on top of the
2214 destination pixel in such a way that the alpha component of the
2215 source defines the translucency of the pixel.
2217 When the paint device is a QImage, the image format must be set to
2218 \l {QImage::Format}{Format_ARGB32Premultiplied} or
2219 \l {QImage::Format}{Format_ARGB32} for the composition modes to have
2220 any effect. For performance the premultiplied version is the preferred
2223 When a composition mode is set it applies to all painting
2224 operator, pens, brushes, gradients and pixmap/image drawing.
2226 \value CompositionMode_SourceOver This is the default mode. The
2227 alpha of the source is used to blend the pixel on top of the
2230 \value CompositionMode_DestinationOver The alpha of the
2231 destination is used to blend it on top of the source pixels. This
2232 mode is the inverse of CompositionMode_SourceOver.
2234 \value CompositionMode_Clear The pixels in the destination are
2235 cleared (set to fully transparent) independent of the source.
2237 \value CompositionMode_Source The output is the source
2238 pixel. (This means a basic copy operation and is identical to
2239 SourceOver when the source pixel is opaque).
2241 \value CompositionMode_Destination The output is the destination
2242 pixel. This means that the blending has no effect. This mode is
2243 the inverse of CompositionMode_Source.
2245 \value CompositionMode_SourceIn The output is the source, where
2246 the alpha is reduced by that of the destination.
2248 \value CompositionMode_DestinationIn The output is the
2249 destination, where the alpha is reduced by that of the
2250 source. This mode is the inverse of CompositionMode_SourceIn.
2252 \value CompositionMode_SourceOut The output is the source, where
2253 the alpha is reduced by the inverse of destination.
2255 \value CompositionMode_DestinationOut The output is the
2256 destination, where the alpha is reduced by the inverse of the
2257 source. This mode is the inverse of CompositionMode_SourceOut.
2259 \value CompositionMode_SourceAtop The source pixel is blended on
2260 top of the destination, with the alpha of the source pixel reduced
2261 by the alpha of the destination pixel.
2263 \value CompositionMode_DestinationAtop The destination pixel is
2264 blended on top of the source, with the alpha of the destination
2265 pixel is reduced by the alpha of the destination pixel. This mode
2266 is the inverse of CompositionMode_SourceAtop.
2268 \value CompositionMode_Xor The source, whose alpha is reduced with
2269 the inverse of the destination alpha, is merged with the
2270 destination, whose alpha is reduced by the inverse of the source
2271 alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2273 \value CompositionMode_Plus Both the alpha and color of the source
2274 and destination pixels are added together.
2276 \value CompositionMode_Multiply The output is the source color
2277 multiplied by the destination. Multiplying a color with white
2278 leaves the color unchanged, while multiplying a color
2279 with black produces black.
2281 \value CompositionMode_Screen The source and destination colors
2282 are inverted and then multiplied. Screening a color with white
2283 produces white, whereas screening a color with black leaves the
2286 \value CompositionMode_Overlay Multiplies or screens the colors
2287 depending on the destination color. The destination color is mixed
2288 with the source color to reflect the lightness or darkness of the
2291 \value CompositionMode_Darken The darker of the source and
2292 destination colors is selected.
2294 \value CompositionMode_Lighten The lighter of the source and
2295 destination colors is selected.
2297 \value CompositionMode_ColorDodge The destination color is
2298 brightened to reflect the source color. A black source color
2299 leaves the destination color unchanged.
2301 \value CompositionMode_ColorBurn The destination color is darkened
2302 to reflect the source color. A white source color leaves the
2303 destination color unchanged.
2305 \value CompositionMode_HardLight Multiplies or screens the colors
2306 depending on the source color. A light source color will lighten
2307 the destination color, whereas a dark source color will darken the
2310 \value CompositionMode_SoftLight Darkens or lightens the colors
2311 depending on the source color. Similar to
2312 CompositionMode_HardLight.
2314 \value CompositionMode_Difference Subtracts the darker of the
2315 colors from the lighter. Painting with white inverts the
2316 destination color, whereas painting with black leaves the
2317 destination color unchanged.
2319 \value CompositionMode_Exclusion Similar to
2320 CompositionMode_Difference, but with a lower contrast. Painting
2321 with white inverts the destination color, whereas painting with
2322 black leaves the destination color unchanged.
2324 \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2325 the source and destination pixels (src OR dst).
2327 \value RasterOp_SourceAndDestination Does a bitwise AND operation
2328 on the source and destination pixels (src AND dst).
2330 \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2331 on the source and destination pixels (src XOR dst).
2333 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2334 operation on the source and destination pixels ((NOT src) AND (NOT
2337 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2338 operation on the source and destination pixels ((NOT src) OR (NOT
2341 \value RasterOp_NotSourceXorDestination Does a bitwise operation
2342 where the source pixels are inverted and then XOR'ed with the
2343 destination ((NOT src) XOR dst).
2345 \value RasterOp_NotSource Does a bitwise operation where the
2346 source pixels are inverted (NOT src).
2348 \value RasterOp_NotSourceAndDestination Does a bitwise operation
2349 where the source is inverted and then AND'ed with the destination
2350 ((NOT src) AND dst).
2352 \value RasterOp_SourceAndNotDestination Does a bitwise operation
2353 where the source is AND'ed with the inverted destination pixels
2354 (src AND (NOT dst)).
2356 \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2357 Modes}{Composition Modes}, {Image Composition Example}
2361 Sets the composition mode to the given \a mode.
2363 \warning Only a QPainter operating on a QImage fully supports all
2364 composition modes. The RasterOp modes are supported for X11 as
2365 described in compositionMode().
2367 \sa compositionMode()
2369 void QPainter::setCompositionMode(CompositionMode mode)
2373 qWarning("QPainter::setCompositionMode: Painter not active");
2376 if (d->state->composition_mode == mode)
2379 d->state->composition_mode = mode;
2380 d->extended->compositionModeChanged();
2384 if (mode >= QPainter::RasterOp_SourceOrDestination) {
2385 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2386 qWarning("QPainter::setCompositionMode: "
2387 "Raster operation modes not supported on device");
2390 } else if (mode >= QPainter::CompositionMode_Plus) {
2391 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2392 qWarning("QPainter::setCompositionMode: "
2393 "Blend modes not supported on device");
2396 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2397 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2398 qWarning("QPainter::setCompositionMode: "
2399 "PorterDuff modes not supported on device");
2404 d->state->composition_mode = mode;
2405 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2409 Returns the current composition mode.
2411 \sa CompositionMode, setCompositionMode()
2413 QPainter::CompositionMode QPainter::compositionMode() const
2415 Q_D(const QPainter);
2417 qWarning("QPainter::compositionMode: Painter not active");
2418 return QPainter::CompositionMode_SourceOver;
2420 return d->state->composition_mode;
2424 Returns the current background brush.
2426 \sa setBackground(), {QPainter#Settings}{Settings}
2429 const QBrush &QPainter::background() const
2431 Q_D(const QPainter);
2433 qWarning("QPainter::background: Painter not active");
2434 return d->fakeState()->brush;
2436 return d->state->bgBrush;
2441 Returns true if clipping has been set; otherwise returns false.
2443 \sa setClipping(), {QPainter#Clipping}{Clipping}
2446 bool QPainter::hasClipping() const
2448 Q_D(const QPainter);
2450 qWarning("QPainter::hasClipping: Painter not active");
2453 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2458 Enables clipping if \a enable is true, or disables clipping if \a
2461 \sa hasClipping(), {QPainter#Clipping}{Clipping}
2464 void QPainter::setClipping(bool enable)
2467 #ifdef QT_DEBUG_DRAW
2468 if (qt_show_painter_debug_output)
2469 printf("QPainter::setClipping(), enable=%s, was=%s\n",
2470 enable ? "on" : "off",
2471 hasClipping() ? "on" : "off");
2474 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2478 if (hasClipping() == enable)
2481 // we can't enable clipping if we don't have a clip
2483 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2485 d->state->clipEnabled = enable;
2488 d->extended->clipEnabledChanged();
2492 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2493 d->updateState(d->state);
2498 Returns the currently set clip region. Note that the clip region
2499 is given in logical coordinates.
2501 \warning QPainter does not store the combined clip explicitly as
2502 this is handled by the underlying QPaintEngine, so the path is
2503 recreated on demand and transformed to the current logical
2504 coordinate system. This is potentially an expensive operation.
2506 \sa setClipRegion(), clipPath(), setClipping()
2509 QRegion QPainter::clipRegion() const
2511 Q_D(const QPainter);
2513 qWarning("QPainter::clipRegion: Painter not active");
2518 bool lastWasNothing = true;
2521 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2523 // ### Falcon: Use QPainterPath
2524 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2525 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2526 switch (info.clipType) {
2528 case QPainterClipInfo::RegionClip: {
2529 QTransform matrix = (info.matrix * d->invMatrix);
2530 if (lastWasNothing) {
2531 region = info.region * matrix;
2532 lastWasNothing = false;
2535 if (info.operation == Qt::IntersectClip)
2536 region &= info.region * matrix;
2537 else if (info.operation == Qt::UniteClip)
2538 region |= info.region * matrix;
2539 else if (info.operation == Qt::NoClip) {
2540 lastWasNothing = true;
2543 region = info.region * matrix;
2547 case QPainterClipInfo::PathClip: {
2548 QTransform matrix = (info.matrix * d->invMatrix);
2549 if (lastWasNothing) {
2550 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2551 info.path.fillRule());
2552 lastWasNothing = false;
2555 if (info.operation == Qt::IntersectClip) {
2556 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2557 info.path.fillRule());
2558 } else if (info.operation == Qt::UniteClip) {
2559 region |= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2560 info.path.fillRule());
2561 } else if (info.operation == Qt::NoClip) {
2562 lastWasNothing = true;
2565 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2566 info.path.fillRule());
2571 case QPainterClipInfo::RectClip: {
2572 QTransform matrix = (info.matrix * d->invMatrix);
2573 if (lastWasNothing) {
2574 region = QRegion(info.rect) * matrix;
2575 lastWasNothing = false;
2578 if (info.operation == Qt::IntersectClip) {
2579 // Use rect intersection if possible.
2580 if (matrix.type() <= QTransform::TxScale)
2581 region &= matrix.mapRect(info.rect);
2583 region &= matrix.map(QRegion(info.rect));
2584 } else if (info.operation == Qt::UniteClip) {
2585 region |= QRegion(info.rect) * matrix;
2586 } else if (info.operation == Qt::NoClip) {
2587 lastWasNothing = true;
2590 region = QRegion(info.rect) * matrix;
2595 case QPainterClipInfo::RectFClip: {
2596 QTransform matrix = (info.matrix * d->invMatrix);
2597 if (lastWasNothing) {
2598 region = QRegion(info.rectf.toRect()) * matrix;
2599 lastWasNothing = false;
2602 if (info.operation == Qt::IntersectClip) {
2603 // Use rect intersection if possible.
2604 if (matrix.type() <= QTransform::TxScale)
2605 region &= matrix.mapRect(info.rectf.toRect());
2607 region &= matrix.map(QRegion(info.rectf.toRect()));
2608 } else if (info.operation == Qt::UniteClip) {
2609 region |= QRegion(info.rectf.toRect()) * matrix;
2610 } else if (info.operation == Qt::NoClip) {
2611 lastWasNothing = true;
2614 region = QRegion(info.rectf.toRect()) * matrix;
2624 extern QPainterPath qt_regionToPath(const QRegion ®ion);
2627 Returns the currently clip as a path. Note that the clip path is
2628 given in logical coordinates.
2630 \warning QPainter does not store the combined clip explicitly as
2631 this is handled by the underlying QPaintEngine, so the path is
2632 recreated on demand and transformed to the current logical
2633 coordinate system. This is potentially an expensive operation.
2635 \sa setClipPath(), clipRegion(), setClipping()
2637 QPainterPath QPainter::clipPath() const
2639 Q_D(const QPainter);
2641 // ### Since we do not support path intersections and path unions yet,
2642 // we just use clipRegion() here...
2644 qWarning("QPainter::clipPath: Painter not active");
2645 return QPainterPath();
2648 // No clip, return empty
2649 if (d->state->clipInfo.size() == 0) {
2650 return QPainterPath();
2653 // Update inverse matrix, used below.
2655 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2657 // For the simple case avoid conversion.
2658 if (d->state->clipInfo.size() == 1
2659 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2660 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2661 return d->state->clipInfo.at(0).path * matrix;
2663 } else if (d->state->clipInfo.size() == 1
2664 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2665 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2667 path.addRect(d->state->clipInfo.at(0).rect);
2668 return path * matrix;
2670 // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2671 return qt_regionToPath(clipRegion());
2677 Returns the bounding rectangle of the current clip if there is a clip;
2678 otherwise returns an empty rectangle. Note that the clip region is
2679 given in logical coordinates.
2681 The bounding rectangle is not guaranteed to be tight.
2683 \sa setClipRect(), setClipPath(), setClipRegion()
2688 QRectF QPainter::clipBoundingRect() const
2690 Q_D(const QPainter);
2693 qWarning("QPainter::clipBoundingRect: Painter not active");
2697 // Accumulate the bounding box in device space. This is not 100%
2698 // precise, but it fits within the guarantee and it is resonably
2701 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2703 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2705 if (info.clipType == QPainterClipInfo::RectClip)
2707 else if (info.clipType == QPainterClipInfo::RectFClip)
2709 else if (info.clipType == QPainterClipInfo::RegionClip)
2710 r = info.region.boundingRect();
2712 r = info.path.boundingRect();
2714 r = info.matrix.mapRect(r);
2718 else if (info.operation == Qt::IntersectClip)
2720 else if (info.operation == Qt::UniteClip)
2725 // Map the rectangle back into logical space using the inverse
2728 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2730 return d->invMatrix.mapRect(bounds);
2734 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2736 Enables clipping, and sets the clip region to the given \a
2737 rectangle using the given clip \a operation. The default operation
2738 is to replace the current clip rectangle.
2740 Note that the clip rectangle is specified in logical (painter)
2743 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2745 void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2750 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2751 op = Qt::ReplaceClip;
2754 qWarning("QPainter::setClipRect: Painter not active");
2757 qreal right = rect.x() + rect.width();
2758 qreal bottom = rect.y() + rect.height();
2759 qreal pts[] = { rect.x(), rect.y(),
2763 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2764 d->state->clipEnabled = true;
2765 d->extended->clip(vp, op);
2766 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2767 d->state->clipInfo.clear();
2768 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2769 d->state->clipOperation = op;
2773 if (qreal(int(rect.top())) == rect.top()
2774 && qreal(int(rect.bottom())) == rect.bottom()
2775 && qreal(int(rect.left())) == rect.left()
2776 && qreal(int(rect.right())) == rect.right())
2778 setClipRect(rect.toRect(), op);
2782 if (rect.isEmpty()) {
2783 setClipRegion(QRegion(), op);
2789 setClipPath(path, op);
2793 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2796 Enables clipping, and sets the clip region to the given \a rectangle using the given
2799 void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2804 qWarning("QPainter::setClipRect: Painter not active");
2808 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2809 op = Qt::ReplaceClip;
2812 d->state->clipEnabled = true;
2813 d->extended->clip(rect, op);
2814 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2815 d->state->clipInfo.clear();
2816 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2817 d->state->clipOperation = op;
2821 d->state->clipRegion = rect;
2822 d->state->clipOperation = op;
2823 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2824 d->state->clipInfo.clear();
2825 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2826 d->state->clipEnabled = true;
2827 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2828 d->updateState(d->state);
2832 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2834 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2835 with the given \a width and \a height.
2839 \fn void QPainter::setClipRegion(const QRegion ®ion, Qt::ClipOperation operation)
2841 Sets the clip region to the given \a region using the specified clip
2842 \a operation. The default clip operation is to replace the current
2845 Note that the clip region is given in logical coordinates.
2847 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2849 void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2852 #ifdef QT_DEBUG_DRAW
2853 QRect rect = r.boundingRect();
2854 if (qt_show_painter_debug_output)
2855 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2856 r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2859 qWarning("QPainter::setClipRegion: Painter not active");
2863 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2864 op = Qt::ReplaceClip;
2867 d->state->clipEnabled = true;
2868 d->extended->clip(r, op);
2869 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2870 d->state->clipInfo.clear();
2871 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2872 d->state->clipOperation = op;
2876 d->state->clipRegion = r;
2877 d->state->clipOperation = op;
2878 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2879 d->state->clipInfo.clear();
2880 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2881 d->state->clipEnabled = true;
2882 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2883 d->updateState(d->state);
2890 Sets the transformation matrix to \a matrix and enables transformations.
2892 \note It is advisable to use setWorldTransform() instead of this function to
2893 preserve the properties of perspective transformations.
2895 If \a combine is true, then \a matrix is combined with the current
2896 transformation matrix; otherwise \a matrix replaces the current
2897 transformation matrix.
2899 If \a matrix is the identity matrix and \a combine is false, this
2900 function calls setWorldMatrixEnabled(false). (The identity matrix is the
2901 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2904 The following functions can transform the coordinate system without using
2913 They operate on the painter's worldMatrix() and are implemented like this:
2915 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 4
2917 Note that when using setWorldMatrix() function you should always have
2918 \a combine be true when you are drawing into a QPicture. Otherwise
2919 it may not be possible to replay the picture with additional
2920 transformations; using the translate(), scale(), etc. convenience
2923 For more information about the coordinate system, transformations
2924 and window-viewport conversion, see \l {Coordinate System}.
2926 \sa setWorldTransform(), QTransform
2929 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2931 setWorldTransform(QTransform(matrix), combine);
2938 Returns the world transformation matrix.
2940 It is advisable to use worldTransform() because worldMatrix() does not
2941 preserve the properties of perspective transformations.
2943 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2947 const QMatrix &QPainter::worldMatrix() const
2949 Q_D(const QPainter);
2951 qWarning("QPainter::worldMatrix: Painter not active");
2952 return d->fakeState()->transform.toAffine();
2954 return d->state->worldMatrix.toAffine();
2960 Use setWorldTransform() instead.
2962 \sa setWorldTransform()
2965 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
2967 setWorldTransform(QTransform(matrix), combine);
2973 Use worldTransform() instead.
2975 \sa worldTransform()
2978 const QMatrix &QPainter::matrix() const
2980 return worldMatrix();
2988 Returns the transformation matrix combining the current
2989 window/viewport and world transformation.
2991 It is advisable to use combinedTransform() instead of this
2992 function to preserve the properties of perspective transformations.
2994 \sa setWorldTransform(), setWindow(), setViewport()
2996 QMatrix QPainter::combinedMatrix() const
2998 return combinedTransform().toAffine();
3005 Returns the matrix that transforms from logical coordinates to
3006 device coordinates of the platform dependent paint device.
3008 \note It is advisable to use deviceTransform() instead of this
3009 function to preserve the properties of perspective transformations.
3011 This function is \e only needed when using platform painting
3012 commands on the platform dependent handle (Qt::HANDLE), and the
3013 platform does not do transformations nativly.
3015 The QPaintEngine::PaintEngineFeature enum can be queried to
3016 determine whether the platform performs the transformations or
3019 \sa worldMatrix(), QPaintEngine::hasFeature(),
3021 const QMatrix &QPainter::deviceMatrix() const
3023 Q_D(const QPainter);
3025 qWarning("QPainter::deviceMatrix: Painter not active");
3026 return d->fakeState()->transform.toAffine();
3028 return d->state->matrix.toAffine();
3034 Resets any transformations that were made using translate(), scale(),
3035 shear(), rotate(), setWorldMatrix(), setViewport() and
3038 It is advisable to use resetTransform() instead of this function
3039 to preserve the properties of perspective transformations.
3041 \sa {QPainter#Coordinate Transformations}{Coordinate
3045 void QPainter::resetMatrix()
3054 Enables transformations if \a enable is true, or disables
3055 transformations if \a enable is false. The world transformation
3056 matrix is not changed.
3058 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3059 Transformations}{Coordinate Transformations}
3062 void QPainter::setWorldMatrixEnabled(bool enable)
3065 #ifdef QT_DEBUG_DRAW
3066 if (qt_show_painter_debug_output)
3067 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3071 qWarning("QPainter::setMatrixEnabled: Painter not active");
3074 if (enable == d->state->WxF)
3077 d->state->WxF = enable;
3084 Returns true if world transformation is enabled; otherwise returns
3087 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3090 bool QPainter::worldMatrixEnabled() const
3092 Q_D(const QPainter);
3094 qWarning("QPainter::worldMatrixEnabled: Painter not active");
3097 return d->state->WxF;
3103 Use setWorldMatrixEnabled() instead.
3105 \sa setWorldMatrixEnabled()
3108 void QPainter::setMatrixEnabled(bool enable)
3110 setWorldMatrixEnabled(enable);
3116 Use worldMatrixEnabled() instead
3118 \sa worldMatrixEnabled()
3121 bool QPainter::matrixEnabled() const
3123 return worldMatrixEnabled();
3127 Scales the coordinate system by (\a{sx}, \a{sy}).
3129 \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate
3133 void QPainter::scale(qreal sx, qreal sy)
3135 #ifdef QT_DEBUG_DRAW
3136 if (qt_show_painter_debug_output)
3137 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3141 qWarning("QPainter::scale: Painter not active");
3145 d->state->worldMatrix.scale(sx,sy);
3146 d->state->WxF = true;
3151 Shears the coordinate system by (\a{sh}, \a{sv}).
3153 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3157 void QPainter::shear(qreal sh, qreal sv)
3159 #ifdef QT_DEBUG_DRAW
3160 if (qt_show_painter_debug_output)
3161 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3165 qWarning("QPainter::shear: Painter not active");
3169 d->state->worldMatrix.shear(sh, sv);
3170 d->state->WxF = true;
3175 \fn void QPainter::rotate(qreal angle)
3177 Rotates the coordinate system the given \a angle clockwise.
3179 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3183 void QPainter::rotate(qreal a)
3185 #ifdef QT_DEBUG_DRAW
3186 if (qt_show_painter_debug_output)
3187 printf("QPainter::rotate(), angle=%f\n", a);
3191 qWarning("QPainter::rotate: Painter not active");
3195 d->state->worldMatrix.rotate(a);
3196 d->state->WxF = true;
3201 Translates the coordinate system by the given \a offset; i.e. the
3202 given \a offset is added to points.
3204 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3207 void QPainter::translate(const QPointF &offset)
3209 qreal dx = offset.x();
3210 qreal dy = offset.y();
3211 #ifdef QT_DEBUG_DRAW
3212 if (qt_show_painter_debug_output)
3213 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3217 qWarning("QPainter::translate: Painter not active");
3221 d->state->worldMatrix.translate(dx, dy);
3222 d->state->WxF = true;
3227 \fn void QPainter::translate(const QPoint &offset)
3230 Translates the coordinate system by the given \a offset.
3234 \fn void QPainter::translate(qreal dx, qreal dy)
3237 Translates the coordinate system by the vector (\a dx, \a dy).
3241 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3243 Enables clipping, and sets the clip path for the painter to the
3244 given \a path, with the clip \a operation.
3246 Note that the clip path is specified in logical (painter)
3249 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3252 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3254 #ifdef QT_DEBUG_DRAW
3255 if (qt_show_painter_debug_output) {
3256 QRectF b = path.boundingRect();
3257 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3258 path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3264 qWarning("QPainter::setClipPath: Painter not active");
3268 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
3269 op = Qt::ReplaceClip;
3272 d->state->clipEnabled = true;
3273 d->extended->clip(path, op);
3274 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3275 d->state->clipInfo.clear();
3276 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3277 d->state->clipOperation = op;
3281 d->state->clipPath = path;
3282 d->state->clipOperation = op;
3283 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3284 d->state->clipInfo.clear();
3285 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3286 d->state->clipEnabled = true;
3287 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3288 d->updateState(d->state);
3292 Draws the outline (strokes) the path \a path with the pen specified
3295 \sa fillPath(), {QPainter#Drawing}{Drawing}
3297 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3302 qWarning("QPainter::strokePath: Painter not active");
3310 const QGradient *g = qpen_brush(pen).gradient();
3311 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3312 d->extended->stroke(qtVectorPathForPath(path), pen);
3317 QBrush oldBrush = d->state->brush;
3318 QPen oldPen = d->state->pen;
3321 setBrush(Qt::NoBrush);
3331 Fills the given \a path using the given \a brush. The outline is
3334 Alternatively, you can specify a QColor instead of a QBrush; the
3335 QBrush constructor (taking a QColor argument) will automatically
3336 create a solid pattern brush.
3340 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3345 qWarning("QPainter::fillPath: Painter not active");
3353 const QGradient *g = brush.gradient();
3354 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3355 d->extended->fill(qtVectorPathForPath(path), brush);
3360 QBrush oldBrush = d->state->brush;
3361 QPen oldPen = d->state->pen;
3374 Draws the given painter \a path using the current pen for outline
3375 and the current brush for filling.
3379 \o \inlineimage qpainter-path.png
3381 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 5
3384 \sa {painting/painterpaths}{the Painter Paths
3385 example},{demos/deform}{the Vector Deformation demo}
3387 void QPainter::drawPath(const QPainterPath &path)
3389 #ifdef QT_DEBUG_DRAW
3390 QRectF pathBounds = path.boundingRect();
3391 if (qt_show_painter_debug_output)
3392 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3393 path.elementCount(),
3394 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3400 qWarning("QPainter::drawPath: Painter not active");
3405 d->extended->drawPath(path);
3408 d->updateState(d->state);
3410 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3411 d->engine->drawPath(path);
3413 d->draw_helper(path);
3418 \fn void QPainter::drawLine(const QLineF &line)
3420 Draws a line defined by \a line.
3424 \o \inlineimage qpainter-line.png
3426 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 6
3429 \sa drawLines(), drawPolyline(), {Coordinate System}
3433 \fn void QPainter::drawLine(const QLine &line)
3436 Draws a line defined by \a line.
3440 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3443 Draws a line from \a p1 to \a p2.
3447 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3450 Draws a line from \a p1 to \a p2.
3454 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3457 Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3458 current pen position to (\a x2, \a y2).
3462 \fn void QPainter::drawRect(const QRectF &rectangle)
3464 Draws the current \a rectangle with the current pen and brush.
3466 A filled rectangle has a size of \a{rectangle}.size(). A stroked
3467 rectangle has a size of \a{rectangle}.size() plus the pen width.
3471 \o \inlineimage qpainter-rectangle.png
3473 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 7
3476 \sa drawRects(), drawPolygon(), {Coordinate System}
3480 \fn void QPainter::drawRect(const QRect &rectangle)
3484 Draws the current \a rectangle with the current pen and brush.
3488 \fn void QPainter::drawRect(int x, int y, int width, int height)
3492 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3493 with the given \a width and \a height.
3497 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3499 Draws the first \a rectCount of the given \a rectangles using the
3500 current pen and brush.
3504 void QPainter::drawRects(const QRectF *rects, int rectCount)
3506 #ifdef QT_DEBUG_DRAW
3507 if (qt_show_painter_debug_output)
3508 printf("QPainter::drawRects(), count=%d\n", rectCount);
3513 qWarning("QPainter::drawRects: Painter not active");
3521 d->extended->drawRects(rects, rectCount);
3525 d->updateState(d->state);
3527 if (!d->state->emulationSpecifier) {
3528 d->engine->drawRects(rects, rectCount);
3532 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3533 && d->state->matrix.type() == QTransform::TxTranslate) {
3534 for (int i=0; i<rectCount; ++i) {
3535 QRectF r(rects[i].x() + d->state->matrix.dx(),
3536 rects[i].y() + d->state->matrix.dy(),
3539 d->engine->drawRects(&r, 1);
3542 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3543 for (int i=0; i<rectCount; ++i) {
3544 QPainterPath rectPath;
3545 rectPath.addRect(rects[i]);
3546 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3549 QPainterPath rectPath;
3550 for (int i=0; i<rectCount; ++i)
3551 rectPath.addRect(rects[i]);
3552 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3558 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3561 Draws the first \a rectCount of the given \a rectangles using the
3562 current pen and brush.
3564 void QPainter::drawRects(const QRect *rects, int rectCount)
3566 #ifdef QT_DEBUG_DRAW
3567 if (qt_show_painter_debug_output)
3568 printf("QPainter::drawRects(), count=%d\n", rectCount);
3573 qWarning("QPainter::drawRects: Painter not active");
3581 d->extended->drawRects(rects, rectCount);
3585 d->updateState(d->state);
3587 if (!d->state->emulationSpecifier) {
3588 d->engine->drawRects(rects, rectCount);
3592 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3593 && d->state->matrix.type() == QTransform::TxTranslate) {
3594 for (int i=0; i<rectCount; ++i) {
3595 QRectF r(rects[i].x() + d->state->matrix.dx(),
3596 rects[i].y() + d->state->matrix.dy(),
3600 d->engine->drawRects(&r, 1);
3603 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3604 for (int i=0; i<rectCount; ++i) {
3605 QPainterPath rectPath;
3606 rectPath.addRect(rects[i]);
3607 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3610 QPainterPath rectPath;
3611 for (int i=0; i<rectCount; ++i)
3612 rectPath.addRect(rects[i]);
3614 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3620 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3623 Draws the given \a rectangles using the current pen and brush.
3627 \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3631 Draws the given \a rectangles using the current pen and brush.
3635 \fn void QPainter::drawPoint(const QPointF &position)
3637 Draws a single point at the given \a position using the current
3640 \sa {Coordinate System}
3644 \fn void QPainter::drawPoint(const QPoint &position)
3647 Draws a single point at the given \a position using the current
3651 /*! \fn void QPainter::drawPoint(int x, int y)
3655 Draws a single point at position (\a x, \a y).
3659 Draws the first \a pointCount points in the array \a points using
3660 the current pen's color.
3662 \sa {Coordinate System}
3664 void QPainter::drawPoints(const QPointF *points, int pointCount)
3666 #ifdef QT_DEBUG_DRAW
3667 if (qt_show_painter_debug_output)
3668 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3673 qWarning("QPainter::drawPoints: Painter not active");
3677 if (pointCount <= 0)
3681 d->extended->drawPoints(points, pointCount);
3685 d->updateState(d->state);
3687 if (!d->state->emulationSpecifier) {
3688 d->engine->drawPoints(points, pointCount);
3692 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3693 && d->state->matrix.type() == QTransform::TxTranslate) {
3694 // ### use drawPoints function
3695 for (int i=0; i<pointCount; ++i) {
3696 QPointF pt(points[i].x() + d->state->matrix.dx(),
3697 points[i].y() + d->state->matrix.dy());
3698 d->engine->drawPoints(&pt, 1);
3701 QPen pen = d->state->pen;
3702 bool flat_pen = pen.capStyle() == Qt::FlatCap;
3705 pen.setCapStyle(Qt::SquareCap);
3709 for (int i=0; i<pointCount; ++i) {
3710 path.moveTo(points[i].x(), points[i].y());
3711 path.lineTo(points[i].x() + 0.0001, points[i].y());
3713 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3722 Draws the first \a pointCount points in the array \a points using
3723 the current pen's color.
3726 void QPainter::drawPoints(const QPoint *points, int pointCount)
3728 #ifdef QT_DEBUG_DRAW
3729 if (qt_show_painter_debug_output)
3730 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3735 qWarning("QPainter::drawPoints: Painter not active");
3739 if (pointCount <= 0)
3743 d->extended->drawPoints(points, pointCount);
3747 d->updateState(d->state);
3749 if (!d->state->emulationSpecifier) {
3750 d->engine->drawPoints(points, pointCount);
3754 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3755 && d->state->matrix.type() == QTransform::TxTranslate) {
3756 // ### use drawPoints function
3757 for (int i=0; i<pointCount; ++i) {
3758 QPointF pt(points[i].x() + d->state->matrix.dx(),
3759 points[i].y() + d->state->matrix.dy());
3760 d->engine->drawPoints(&pt, 1);
3763 QPen pen = d->state->pen;
3764 bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3767 pen.setCapStyle(Qt::SquareCap);
3771 for (int i=0; i<pointCount; ++i) {
3772 path.moveTo(points[i].x(), points[i].y());
3773 path.lineTo(points[i].x() + 0.0001, points[i].y());
3775 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3782 \fn void QPainter::drawPoints(const QPolygonF &points)
3786 Draws the points in the vector \a points.
3790 \fn void QPainter::drawPoints(const QPolygon &points)
3794 Draws the points in the vector \a points.
3798 \fn void QPainter::drawPoints(const QPolygon &polygon, int index,
3804 Draws \a count points in the vector \a polygon starting on \a index
3805 using the current pen.
3807 Use drawPoints() combined with QPolygon::constData() instead.
3810 QPainter painter(this);
3811 painter.drawPoints(polygon, index, count);
3813 int pointCount = (count == -1) ? polygon.size() - index : count;
3815 QPainter painter(this);
3816 painter.drawPoints(polygon.constData() + index, pointCount);
3821 Sets the background mode of the painter to the given \a mode
3823 Qt::TransparentMode (the default) draws stippled lines and text
3824 without setting the background pixels. Qt::OpaqueMode fills these
3825 space with the current background color.
3827 Note that in order to draw a bitmap or pixmap transparently, you
3828 must use QPixmap::setMask().
3830 \sa backgroundMode(), setBackground(),
3831 {QPainter#Settings}{Settings}
3834 void QPainter::setBackgroundMode(Qt::BGMode mode)
3836 #ifdef QT_DEBUG_DRAW
3837 if (qt_show_painter_debug_output)
3838 printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3843 qWarning("QPainter::setBackgroundMode: Painter not active");
3846 if (d->state->bgMode == mode)
3849 d->state->bgMode = mode;
3851 d->checkEmulation();
3853 d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3858 Returns the current background mode.
3860 \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3862 Qt::BGMode QPainter::backgroundMode() const
3864 Q_D(const QPainter);
3866 qWarning("QPainter::backgroundMode: Painter not active");
3867 return Qt::TransparentMode;
3869 return d->state->bgMode;
3876 Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3880 void QPainter::setPen(const QColor &color)
3882 #ifdef QT_DEBUG_DRAW
3883 if (qt_show_painter_debug_output)
3884 printf("QPainter::setPen(), color=%04x\n", color.rgb());
3888 qWarning("QPainter::setPen: Painter not active");
3892 if (d->state->pen.style() == Qt::SolidLine
3893 && d->state->pen.widthF() == 0
3894 && d->state->pen.isSolid()
3895 && d->state->pen.color() == color)
3898 QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
3900 d->state->pen = pen;
3902 d->extended->penChanged();
3904 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3908 Sets the painter's pen to be the given \a pen.
3910 The \a pen defines how to draw lines and outlines, and it also
3911 defines the text color.
3913 \sa pen(), {QPainter#Settings}{Settings}
3916 void QPainter::setPen(const QPen &pen)
3919 #ifdef QT_DEBUG_DRAW
3920 if (qt_show_painter_debug_output)
3921 printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3922 pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3926 qWarning("QPainter::setPen: Painter not active");
3930 if (d->state->pen == pen)
3933 d->state->pen = pen;
3936 d->checkEmulation();
3937 d->extended->penChanged();
3941 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3947 Sets the painter's pen to have the given \a style, width 0 and
3951 void QPainter::setPen(Qt::PenStyle style)
3955 qWarning("QPainter::setPen: Painter not active");
3959 if (d->state->pen.style() == style
3960 && (style == Qt::NoPen || (d->state->pen.widthF() == 0
3961 && d->state->pen.isSolid()
3962 && d->state->pen.color() == QColor(Qt::black))))
3965 // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
3966 // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
3967 d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
3970 d->extended->penChanged();
3972 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3977 Returns the painter's current pen.
3979 \sa setPen(), {QPainter#Settings}{Settings}
3982 const QPen &QPainter::pen() const
3984 Q_D(const QPainter);
3986 qWarning("QPainter::pen: Painter not active");
3987 return d->fakeState()->pen;
3989 return d->state->pen;
3994 Sets the painter's brush to the given \a brush.
3996 The painter's brush defines how shapes are filled.
3998 \sa brush(), {QPainter#Settings}{Settings}
4001 void QPainter::setBrush(const QBrush &brush)
4003 #ifdef QT_DEBUG_DRAW
4004 if (qt_show_painter_debug_output)
4005 printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
4009 qWarning("QPainter::setBrush: Painter not active");
4013 if (d->state->brush.d == brush.d)
4017 d->state->brush = brush;
4018 d->checkEmulation();
4019 d->extended->brushChanged();
4023 d->state->brush = brush;
4024 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4031 Sets the painter's brush to black color and the specified \a
4035 void QPainter::setBrush(Qt::BrushStyle style)
4039 qWarning("QPainter::setBrush: Painter not active");
4042 if (d->state->brush.style() == style &&
4043 (style == Qt::NoBrush
4044 || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
4046 d->state->brush = QBrush(Qt::black, style);
4048 d->extended->brushChanged();
4050 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4054 Returns the painter's current brush.
4056 \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
4059 const QBrush &QPainter::brush() const
4061 Q_D(const QPainter);
4063 qWarning("QPainter::brush: Painter not active");
4064 return d->fakeState()->brush;
4066 return d->state->brush;
4070 \fn void QPainter::setBackground(const QBrush &brush)
4072 Sets the background brush of the painter to the given \a brush.
4074 The background brush is the brush that is filled in when drawing
4075 opaque text, stippled lines and bitmaps. The background brush has
4076 no effect in transparent background mode (which is the default).
4078 \sa background(), setBackgroundMode(),
4079 {QPainter#Settings}{Settings}
4082 void QPainter::setBackground(const QBrush &bg)
4084 #ifdef QT_DEBUG_DRAW
4085 if (qt_show_painter_debug_output)
4086 printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4091 qWarning("QPainter::setBackground: Painter not active");
4094 d->state->bgBrush = bg;
4096 d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4100 Sets the painter's font to the given \a font.
4102 This font is used by subsequent drawText() functions. The text
4103 color is the same as the pen color.
4105 If you set a font that isn't available, Qt finds a close match.
4106 font() will return what you set using setFont() and fontInfo() returns the
4107 font actually being used (which may be the same).
4109 \sa font(), drawText(), {QPainter#Settings}{Settings}
4112 void QPainter::setFont(const QFont &font)
4116 #ifdef QT_DEBUG_DRAW
4117 if (qt_show_painter_debug_output)
4118 printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4122 qWarning("QPainter::setFont: Painter not active");
4126 d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4128 d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4132 Returns the currently set font used for drawing text.
4134 \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4136 const QFont &QPainter::font() const
4138 Q_D(const QPainter);
4140 qWarning("QPainter::font: Painter not active");
4141 return d->fakeState()->font;
4143 return d->state->font;
4149 Draws the given rectangle \a rect with rounded corners.
4151 The \a xRadius and \a yRadius arguments specify the radii
4152 of the ellipses defining the corners of the rounded rectangle.
4153 When \a mode is Qt::RelativeSize, \a xRadius and
4154 \a yRadius are specified in percentage of half the rectangle's
4155 width and height respectively, and should be in the range
4158 A filled rectangle has a size of rect.size(). A stroked rectangle
4159 has a size of rect.size() plus the pen width.
4163 \o \inlineimage qpainter-roundrect.png
4165 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 8
4168 \sa drawRect(), QPen
4170 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4172 #ifdef QT_DEBUG_DRAW
4173 if (qt_show_painter_debug_output)
4174 printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4181 if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
4187 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4192 path.addRoundedRect(rect, xRadius, yRadius, mode);
4197 \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4198 Qt::SizeMode mode = Qt::AbsoluteSize);
4202 Draws the given rectangle \a rect with rounded corners.
4206 \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4207 Qt::SizeMode mode = Qt::AbsoluteSize);
4211 Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4217 Draws a rectangle \a r with rounded corners.
4219 The \a xRnd and \a yRnd arguments specify how rounded the corners
4220 should be. 0 is angled corners, 99 is maximum roundedness.
4222 A filled rectangle has a size of r.size(). A stroked rectangle
4223 has a size of r.size() plus the pen width.
4225 \sa drawRoundedRect()
4227 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4229 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4234 \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4239 Draws the rectangle \a r with rounded corners.
4245 \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4249 Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4253 \fn void QPainter::drawEllipse(const QRectF &rectangle)
4255 Draws the ellipse defined by the given \a rectangle.
4257 A filled ellipse has a size of \a{rectangle}.\l
4258 {QRect::size()}{size()}. A stroked ellipse has a size of
4259 \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4263 \o \inlineimage qpainter-ellipse.png
4265 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 9
4268 \sa drawPie(), {Coordinate System}
4270 void QPainter::drawEllipse(const QRectF &r)
4272 #ifdef QT_DEBUG_DRAW
4273 if (qt_show_painter_debug_output)
4274 printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4281 QRectF rect(r.normalized());
4284 d->extended->drawEllipse(rect);
4288 d->updateState(d->state);
4289 if (d->state->emulationSpecifier) {
4290 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4291 && d->state->matrix.type() == QTransform::TxTranslate) {
4292 rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4295 path.addEllipse(rect);
4296 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4301 d->engine->drawEllipse(rect);
4305 \fn QPainter::drawEllipse(const QRect &rectangle)
4309 Draws the ellipse defined by the given \a rectangle.
4311 void QPainter::drawEllipse(const QRect &r)
4313 #ifdef QT_DEBUG_DRAW
4314 if (qt_show_painter_debug_output)
4315 printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4322 QRect rect(r.normalized());
4325 d->extended->drawEllipse(rect);
4329 d->updateState(d->state);
4331 if (d->state->emulationSpecifier) {
4332 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4333 && d->state->matrix.type() == QTransform::TxTranslate) {
4334 rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4337 path.addEllipse(rect);
4338 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4343 d->engine->drawEllipse(rect);
4347 \fn QPainter::drawEllipse(int x, int y, int width, int height)
4351 Draws the ellipse defined by the rectangle beginning at (\a{x},
4352 \a{y}) with the given \a width and \a height.
4358 \fn QPainter::drawEllipse(const QPointF ¢er, qreal rx, qreal ry)
4362 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4368 \fn QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)
4372 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4376 \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4378 Draws the arc defined by the given \a rectangle, \a startAngle and
4381 The \a startAngle and \a spanAngle must be specified in 1/16th of
4382 a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4383 values for the angles mean counter-clockwise while negative values
4384 mean the clockwise direction. Zero degrees is at the 3 o'clock
4389 \o \inlineimage qpainter-arc.png
4391 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 10
4394 \sa drawPie(), drawChord(), {Coordinate System}
4397 void QPainter::drawArc(const QRectF &r, int a, int alen)
4399 #ifdef QT_DEBUG_DRAW
4400 if (qt_show_painter_debug_output)
4401 printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4402 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4409 QRectF rect = r.normalized();
4412 path.arcMoveTo(rect, a/16.0);
4413 path.arcTo(rect, a/16.0, alen/16.0);
4414 strokePath(path, d->state->pen);
4417 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4422 Draws the arc defined by the given \a rectangle, \a startAngle and
4427 \fn void QPainter::drawArc(int x, int y, int width, int height,
4428 int startAngle, int spanAngle)
4432 Draws the arc defined by the rectangle beginning at (\a x, \a y)
4433 with the specified \a width and \a height, and the given \a
4434 startAngle and \a spanAngle.
4438 \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4440 Draws a pie defined by the given \a rectangle, \a startAngle and
4443 The pie is filled with the current brush().
4445 The startAngle and spanAngle must be specified in 1/16th of a
4446 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4447 for the angles mean counter-clockwise while negative values mean
4448 the clockwise direction. Zero degrees is at the 3 o'clock
4453 \o \inlineimage qpainter-pie.png
4455 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 11
4458 \sa drawEllipse(), drawChord(), {Coordinate System}
4460 void QPainter::drawPie(const QRectF &r, int a, int alen)
4462 #ifdef QT_DEBUG_DRAW
4463 if (qt_show_painter_debug_output)
4464 printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4465 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4476 if (a < 0) a += (360*16);
4479 QRectF rect = r.normalized();
4482 path.moveTo(rect.center());
4483 path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4484 path.closeSubpath();
4490 \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4493 Draws a pie defined by the given \a rectangle, \a startAngle and
4498 \fn void QPainter::drawPie(int x, int y, int width, int height, int
4499 startAngle, int spanAngle)
4503 Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4504 the specified \a width and \a height, and the given \a startAngle and
4509 \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4511 Draws the chord defined by the given \a rectangle, \a startAngle and
4512 \a spanAngle. The chord is filled with the current brush().
4514 The startAngle and spanAngle must be specified in 1/16th of a
4515 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4516 for the angles mean counter-clockwise while negative values mean
4517 the clockwise direction. Zero degrees is at the 3 o'clock
4522 \o \inlineimage qpainter-chord.png
4524 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 12
4527 \sa drawArc(), drawPie(), {Coordinate System}
4529 void QPainter::drawChord(const QRectF &r, int a, int alen)
4531 #ifdef QT_DEBUG_DRAW
4532 if (qt_show_painter_debug_output)
4533 printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4534 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4541 QRectF rect = r.normalized();
4544 path.arcMoveTo(rect, a/16.0);
4545 path.arcTo(rect, a/16.0, alen/16.0);
4546 path.closeSubpath();
4550 \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4554 Draws the chord defined by the given \a rectangle, \a startAngle and
4559 \fn void QPainter::drawChord(int x, int y, int width, int height, int
4560 startAngle, int spanAngle)
4564 Draws the chord defined by the rectangle beginning at (\a x, \a y)
4565 with the specified \a width and \a height, and the given \a
4566 startAngle and \a spanAngle.
4571 Draws the first \a lineCount lines in the array \a lines
4572 using the current pen.
4574 \sa drawLine(), drawPolyline()
4576 void QPainter::drawLines(const QLineF *lines, int lineCount)
4578 #ifdef QT_DEBUG_DRAW
4579 if (qt_show_painter_debug_output)
4580 printf("QPainter::drawLines(), line count=%d\n", lineCount);
4585 if (!d->engine || lineCount < 1)
4589 d->extended->drawLines(lines, lineCount);
4593 d->updateState(d->state);
4595 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4597 if (lineEmulation) {
4598 if (lineEmulation == QPaintEngine::PrimitiveTransform
4599 && d->state->matrix.type() == QTransform::TxTranslate) {
4600 for (int i = 0; i < lineCount; ++i) {
4601 QLineF line = lines[i];
4602 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4603 d->engine->drawLines(&line, 1);
4606 QPainterPath linePath;
4607 for (int i = 0; i < lineCount; ++i) {
4608 linePath.moveTo(lines[i].p1());
4609 linePath.lineTo(lines[i].p2());
4611 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4615 d->engine->drawLines(lines, lineCount);
4619 \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4622 Draws the first \a lineCount lines in the array \a lines
4623 using the current pen.
4625 void QPainter::drawLines(const QLine *lines, int lineCount)
4627 #ifdef QT_DEBUG_DRAW
4628 if (qt_show_painter_debug_output)
4629 printf("QPainter::drawLine(), line count=%d\n", lineCount);
4634 if (!d->engine || lineCount < 1)
4638 d->extended->drawLines(lines, lineCount);
4642 d->updateState(d->state);
4644 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4646 if (lineEmulation) {
4647 if (lineEmulation == QPaintEngine::PrimitiveTransform
4648 && d->state->matrix.type() == QTransform::TxTranslate) {
4649 for (int i = 0; i < lineCount; ++i) {
4650 QLineF line = lines[i];
4651 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4652 d->engine->drawLines(&line, 1);
4655 QPainterPath linePath;
4656 for (int i = 0; i < lineCount; ++i) {
4657 linePath.moveTo(lines[i].p1());
4658 linePath.lineTo(lines[i].p2());
4660 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4664 d->engine->drawLines(lines, lineCount);
4670 Draws the first \a lineCount lines in the array \a pointPairs
4671 using the current pen. The lines are specified as pairs of points
4672 so the number of entries in \a pointPairs must be at least \a
4675 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4677 Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4679 drawLines((QLineF*)pointPairs, lineCount);
4685 Draws the first \a lineCount lines in the array \a pointPairs
4686 using the current pen.
4688 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4690 Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4692 drawLines((QLine*)pointPairs, lineCount);
4697 \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4700 Draws a line for each pair of points in the vector \a pointPairs
4701 using the current pen. If there is an odd number of points in the
4702 array, the last point will be ignored.
4706 \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4709 Draws a line for each pair of points in the vector \a pointPairs
4710 using the current pen.
4714 \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4717 Draws the set of lines defined by the list \a lines using the
4718 current pen and brush.
4722 \fn void QPainter::drawLines(const QVector<QLine> &lines)
4725 Draws the set of lines defined by the list \a lines using the
4726 current pen and brush.
4730 Draws the polyline defined by the first \a pointCount points in \a
4731 points using the current pen.
4733 Note that unlike the drawPolygon() function the last point is \e
4734 not connected to the first, neither is the polyline filled.
4739 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 13
4742 \sa drawLines(), drawPolygon(), {Coordinate System}
4744 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4746 #ifdef QT_DEBUG_DRAW
4747 if (qt_show_painter_debug_output)
4748 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4752 if (!d->engine || pointCount < 2)
4756 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4760 d->updateState(d->state);
4762 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4764 if (lineEmulation) {
4766 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4767 // && d->state->matrix.type() == QTransform::TxTranslate) {
4769 QPainterPath polylinePath(points[0]);
4770 for (int i=1; i<pointCount; ++i)
4771 polylinePath.lineTo(points[i]);
4772 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4775 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4782 Draws the polyline defined by the first \a pointCount points in \a
4783 points using the current pen.
4785 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4787 #ifdef QT_DEBUG_DRAW
4788 if (qt_show_painter_debug_output)
4789 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4793 if (!d->engine || pointCount < 2)
4797 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4801 d->updateState(d->state);
4803 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4805 if (lineEmulation) {
4807 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4808 // && d->state->matrix.type() == QTransform::TxTranslate) {
4810 QPainterPath polylinePath(points[0]);
4811 for (int i=1; i<pointCount; ++i)
4812 polylinePath.lineTo(points[i]);
4813 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4816 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4821 \fn void QPainter::drawPolyline(const QPolygon &polygon, int index, int
4827 Draws the polyline defined by the \a count lines of the given \a
4828 polygon starting at \a index (\a index defaults to 0).
4830 Use drawPolyline() combined with QPolygon::constData() instead.
4833 QPainter painter(this);
4834 painter.drawPolyline(polygon, index, count);
4836 int pointCount = (count == -1) ? polygon.size() - index : count;
4838 QPainter painter(this);
4839 painter.drawPolyline(polygon.constData() + index, pointCount);
4844 \fn void QPainter::drawPolyline(const QPolygonF &points)
4848 Draws the polyline defined by the given \a points using the
4853 \fn void QPainter::drawPolyline(const QPolygon &points)
4857 Draws the polyline defined by the given \a points using the
4862 Draws the polygon defined by the first \a pointCount points in the
4863 array \a points using the current pen and brush.
4867 \o \inlineimage qpainter-polygon.png
4869 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 14
4872 The first point is implicitly connected to the last point, and the
4873 polygon is filled with the current brush().
4875 If \a fillRule is Qt::WindingFill, the polygon is filled using the
4876 winding fill algorithm. If \a fillRule is Qt::OddEvenFill, the
4877 polygon is filled using the odd-even fill algorithm. See
4878 \l{Qt::FillRule} for a more detailed description of these fill
4881 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
4883 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
4885 #ifdef QT_DEBUG_DRAW
4886 if (qt_show_painter_debug_output)
4887 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4892 if (!d->engine || pointCount < 2)
4896 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4900 d->updateState(d->state);
4902 uint emulationSpecifier = d->state->emulationSpecifier;
4904 if (emulationSpecifier) {
4905 QPainterPath polygonPath(points[0]);
4906 for (int i=1; i<pointCount; ++i)
4907 polygonPath.lineTo(points[i]);
4908 polygonPath.closeSubpath();
4909 polygonPath.setFillRule(fillRule);
4910 d->draw_helper(polygonPath);
4914 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4919 Draws the polygon defined by the first \a pointCount points in the
4922 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
4924 #ifdef QT_DEBUG_DRAW
4925 if (qt_show_painter_debug_output)
4926 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4931 if (!d->engine || pointCount < 2)
4935 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4939 d->updateState(d->state);
4941 uint emulationSpecifier = d->state->emulationSpecifier;
4943 if (emulationSpecifier) {
4944 QPainterPath polygonPath(points[0]);
4945 for (int i=1; i<pointCount; ++i)
4946 polygonPath.lineTo(points[i]);
4947 polygonPath.closeSubpath();
4948 polygonPath.setFillRule(fillRule);
4949 d->draw_helper(polygonPath);
4953 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4956 /*! \fn void QPainter::drawPolygon(const QPolygonF &polygon, bool winding, int index = 0,
4961 Use drawPolygon() combined with QPolygonF::constData() instead.
4964 QPainter painter(this);
4965 painter.drawPolygon(polygon, winding, index, count);
4967 int pointCount = (count == -1) ? polygon.size() - index : count;
4968 int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
4970 QPainter painter(this);
4971 painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
4975 /*! \fn void QPainter::drawPolygon(const QPolygon &polygon, bool winding,
4976 int index = 0, int count = -1)
4981 Use drawPolygon() combined with QPolygon::constData() instead.
4984 QPainter painter(this);
4985 painter.drawPolygon(polygon, winding, index, count);
4987 int pointCount = (count == -1) ? polygon.size() - index : count;
4988 int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
4990 QPainter painter(this);
4991 painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
4995 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
4999 Draws the polygon defined by the given \a points using the fill
5003 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
5007 Draws the polygon defined by the given \a points using the fill
5012 \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
5014 Draws the convex polygon defined by the first \a pointCount points
5015 in the array \a points using the current pen.
5019 \o \inlineimage qpainter-polygon.png
5021 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 15
5024 The first point is implicitly connected to the last point, and the
5025 polygon is filled with the current brush(). If the supplied
5026 polygon is not convex, i.e. it contains at least one angle larger
5027 than 180 degrees, the results are undefined.
5029 On some platforms (e.g. X11), the drawConvexPolygon() function can
5030 be faster than the drawPolygon() function.
5032 \sa drawPolygon(), drawPolyline(), {Coordinate System}
5036 \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
5039 Draws the convex polygon defined by the first \a pointCount points
5040 in the array \a points using the current pen.
5044 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
5048 Draws the convex polygon defined by \a polygon using the current
5053 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
5056 Draws the convex polygon defined by \a polygon using the current
5061 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon, int
5067 Use drawConvexPolygon() combined with QPolygonF::constData()
5071 QPainter painter(this);
5072 painter.drawConvexPolygon(polygon, index, count);
5074 int pointCount = (count == -1) ? polygon.size() - index : count;
5076 QPainter painter(this);
5077 painter.drawConvexPolygon(polygon.constData() + index, pointCount);
5082 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon, int
5088 Use drawConvexPolygon() combined with QPolygon::constData()
5092 QPainter painter(this);
5093 painter.drawConvexPolygon(polygon, index, count);
5095 int pointCount = (count == -1) ? polygon.size() - index : count;
5097 QPainter painter(this);
5098 painter.drawConvexPolygon(polygon.constData() + index, pointCount);
5102 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
5104 #ifdef QT_DEBUG_DRAW
5105 if (qt_show_painter_debug_output)
5106 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5111 if (!d->engine || pointCount < 2)
5115 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5119 d->updateState(d->state);
5121 uint emulationSpecifier = d->state->emulationSpecifier;
5123 if (emulationSpecifier) {
5124 QPainterPath polygonPath(points[0]);
5125 for (int i=1; i<pointCount; ++i)
5126 polygonPath.lineTo(points[i]);
5127 polygonPath.closeSubpath();
5128 polygonPath.setFillRule(Qt::WindingFill);
5129 d->draw_helper(polygonPath);
5133 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5136 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
5138 #ifdef QT_DEBUG_DRAW
5139 if (qt_show_painter_debug_output)
5140 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5145 if (!d->engine || pointCount < 2)
5149 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5153 d->updateState(d->state);
5155 uint emulationSpecifier = d->state->emulationSpecifier;
5157 if (emulationSpecifier) {
5158 QPainterPath polygonPath(points[0]);
5159 for (int i=1; i<pointCount; ++i)
5160 polygonPath.lineTo(points[i]);
5161 polygonPath.closeSubpath();
5162 polygonPath.setFillRule(Qt::WindingFill);
5163 d->draw_helper(polygonPath);
5167 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5170 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5172 return m.inverted().map(QPointF(m.map(p).toPoint()));
5176 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5178 Draws the rectangular portion \a source of the given \a pixmap
5179 into the given \a target in the paint device.
5181 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5186 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 16
5189 If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5190 using the pens color. If backgroundMode is Qt::OpaqueMode, the
5191 "unset" bits are drawn using the color of the background brush; if
5192 backgroundMode is Qt::TransparentMode, the "unset" bits are
5193 transparent. Drawing bitmaps with gradient or texture colors is
5198 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5200 #if defined QT_DEBUG_DRAW
5201 if (qt_show_painter_debug_output)
5202 printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5204 pm.width(), pm.height());
5209 if (!d->engine || pm.isNull())
5213 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5217 d->extended->drawPixmap(p, pm);
5225 int h = pm.height();
5230 // Emulate opaque background for bitmaps
5231 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5232 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5235 d->updateState(d->state);
5237 if ((d->state->matrix.type() > QTransform::TxTranslate
5238 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5239 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5240 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5243 // If there is no rotation involved we have to make sure we use the
5244 // antialiased and not the aliased coordinate system by rounding the coordinates.
5245 if (d->state->matrix.type() <= QTransform::TxScale) {
5246 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5251 setBackgroundMode(Qt::TransparentMode);
5252 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5253 QBrush brush(d->state->pen.color(), pm);
5256 setBrushOrigin(QPointF(0, 0));
5258 drawRect(pm.rect());
5261 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5262 x += d->state->matrix.dx();
5263 y += d->state->matrix.dy();
5265 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5269 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5271 #if defined QT_DEBUG_DRAW
5272 if (qt_show_painter_debug_output)
5273 printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5274 r.x(), r.y(), r.width(), r.height(),
5275 pm.width(), pm.height(),
5276 sr.x(), sr.y(), sr.width(), sr.height());
5280 if (!d->engine || pm.isNull())
5283 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5288 qreal w = r.width();
5289 qreal h = r.height();
5292 qreal sw = sr.width();
5293 qreal sh = sr.height();
5295 // Sanity-check clipping
5297 sw = pm.width() - sx;
5300 sh = pm.height() - sy;
5308 qreal w_ratio = sx * w/sw;
5316 qreal h_ratio = sy * h/sh;
5323 if (sw + sx > pm.width()) {
5324 qreal delta = sw - (pm.width() - sx);
5325 qreal w_ratio = delta * w/sw;
5330 if (sh + sy > pm.height()) {
5331 qreal delta = sh - (pm.height() - sy);
5332 qreal h_ratio = delta * h/sh;
5337 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5341 d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5345 // Emulate opaque background for bitmaps
5346 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5347 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5349 d->updateState(d->state);
5351 if ((d->state->matrix.type() > QTransform::TxTranslate
5352 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5353 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5354 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5355 || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5358 // If there is no rotation involved we have to make sure we use the
5359 // antialiased and not the aliased coordinate system by rounding the coordinates.
5360 if (d->state->matrix.type() <= QTransform::TxScale) {
5361 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5366 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5374 scale(w / sw, h / sh);
5375 setBackgroundMode(Qt::TransparentMode);
5376 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5379 if (sw == pm.width() && sh == pm.height())
5380 brush = QBrush(d->state->pen.color(), pm);
5382 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5387 drawRect(QRectF(0, 0, sw, sh));
5390 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5391 x += d->state->matrix.dx();
5392 y += d->state->matrix.dy();
5394 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5400 \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5401 const QRect &source)
5404 Draws the rectangular portion \a source of the given \a pixmap
5405 into the given \a target in the paint device.
5407 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5411 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5412 const QRectF &source)
5415 Draws the rectangular portion \a source of the given \a pixmap
5416 with its origin at the given \a point.
5420 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5421 const QRect &source)
5425 Draws the rectangular portion \a source of the given \a pixmap
5426 with its origin at the given \a point.
5430 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5433 Draws the given \a pixmap with its origin at the given \a point.
5437 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5440 Draws the given \a pixmap with its origin at the given \a point.
5444 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5448 Draws the given \a pixmap at position (\a{x}, \a{y}).
5452 \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5455 Draws the given \a pixmap into the given \a rectangle.
5457 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5461 \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5462 const QPixmap &pixmap)
5466 Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5467 with the given \a width and \a height.
5471 \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5472 int sx, int sy, int sw, int sh)
5476 Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5477 width \a sw and height \a sh, of the given \a pixmap , at the
5478 point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5479 If sw or sh are equal to zero the width/height of the pixmap
5480 is used and adjusted by the offset sx/sy;
5484 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5485 int sx, int sy, int sw, int sh)
5489 Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5490 pixmap into the paint device.
5492 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5493 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5494 pixmap that is to be drawn. The default is (0, 0).
5496 (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5497 The default, (0, 0) (and negative) means all the way to the
5498 bottom-right of the pixmap.
5501 void QPainter::drawImage(const QPointF &p, const QImage &image)
5505 if (!d->engine || image.isNull())
5509 d->extended->drawImage(p, image);
5516 int w = image.width();
5517 int h = image.height();
5519 d->updateState(d->state);
5521 if (((d->state->matrix.type() > QTransform::TxTranslate)
5522 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5523 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5524 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5527 // If there is no rotation involved we have to make sure we use the
5528 // antialiased and not the aliased coordinate system by rounding the coordinates.
5529 if (d->state->matrix.type() <= QTransform::TxScale) {
5530 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5535 setBackgroundMode(Qt::TransparentMode);
5536 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5537 QBrush brush(image);
5540 setBrushOrigin(QPointF(0, 0));
5542 drawRect(image.rect());
5547 if (d->state->matrix.type() == QTransform::TxTranslate
5548 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5549 x += d->state->matrix.dx();
5550 y += d->state->matrix.dy();
5553 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5556 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5557 Qt::ImageConversionFlags flags)
5561 if (!d->engine || image.isNull())
5564 qreal x = targetRect.x();
5565 qreal y = targetRect.y();
5566 qreal w = targetRect.width();
5567 qreal h = targetRect.height();
5568 qreal sx = sourceRect.x();
5569 qreal sy = sourceRect.y();
5570 qreal sw = sourceRect.width();
5571 qreal sh = sourceRect.height();
5573 // Sanity-check clipping
5575 sw = image.width() - sx;
5578 sh = image.height() - sy;
5586 qreal w_ratio = sx * w/sw;
5594 qreal h_ratio = sy * h/sh;
5601 if (sw + sx > image.width()) {
5602 qreal delta = sw - (image.width() - sx);
5603 qreal w_ratio = delta * w/sw;
5608 if (sh + sy > image.height()) {
5609 qreal delta = sh - (image.height() - sy);
5610 qreal h_ratio = delta * h/sh;
5615 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5619 d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5623 d->updateState(d->state);
5625 if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5626 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5627 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5628 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5631 // If there is no rotation involved we have to make sure we use the
5632 // antialiased and not the aliased coordinate system by rounding the coordinates.
5633 if (d->state->matrix.type() <= QTransform::TxScale) {
5634 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5639 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5646 scale(w / sw, h / sh);
5647 setBackgroundMode(Qt::TransparentMode);
5648 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5649 QBrush brush(image);
5652 setBrushOrigin(QPointF(-sx, -sy));
5654 drawRect(QRectF(0, 0, sw, sh));
5659 if (d->state->matrix.type() == QTransform::TxTranslate
5660 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5661 x += d->state->matrix.dx();
5662 y += d->state->matrix.dy();
5665 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5669 Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5670 edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5671 selected on \a glyphs and at offsets given by the positions in \a glyphs.
5675 \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes()
5677 #if !defined(QT_NO_RAWFONT)
5678 void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
5682 QRawFont font = glyphRun.rawFont();
5683 if (!font.isValid())
5686 QVector<quint32> glyphIndexes = glyphRun.glyphIndexes();
5687 QVector<QPointF> glyphPositions = glyphRun.positions();
5689 int count = qMin(glyphIndexes.size(), glyphPositions.size());
5690 QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5692 bool paintEngineSupportsTransformations =
5694 ? qt_paintengine_supports_transformations(d->extended->type())
5695 : qt_paintengine_supports_transformations(d->engine->type());
5697 // If the matrix is not affine, the paint engine will fall back to
5698 // drawing the glyphs as paths, which in turn means we should not
5699 // preprocess the glyph positions
5700 if (!d->state->matrix.isAffine())
5701 paintEngineSupportsTransformations = true;
5703 for (int i=0; i<count; ++i) {
5704 QPointF processedPosition = position + glyphPositions.at(i);
5705 if (!paintEngineSupportsTransformations)
5706 processedPosition = d->state->transform().map(processedPosition);
5707 fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5710 d->drawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count, font, glyphRun.overline(),
5711 glyphRun.underline(), glyphRun.strikeOut());
5714 void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, int glyphCount,
5715 const QRawFont &font, bool overline, bool underline,
5722 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5723 QFontEngine *fontEngine = fontD->fontEngine;
5728 for (int i=0; i<glyphCount; ++i) {
5729 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5730 if (i == 0 || leftMost > positions[i].x)
5731 leftMost = positions[i].x;
5733 // We don't support glyphs that do not share a common baseline. If this turns out to
5734 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5735 // and do a drawTextItemDecorations call per cluster.
5736 if (i == 0 || baseLine < positions[i].y)
5737 baseLine = positions[i].y;
5739 // We use the advance rather than the actual bounds to match the algorithm in drawText()
5740 if (i == 0 || rightMost < positions[i].x + gm.xoff)
5741 rightMost = positions[i].x + gm.xoff;
5744 QFixed width = rightMost - leftMost;
5746 if (extended != 0 && state->matrix.isAffine()) {
5747 QStaticTextItem staticTextItem;
5748 staticTextItem.color = state->pen.color();
5749 staticTextItem.font = state->font;
5750 staticTextItem.setFontEngine(fontEngine);
5751 staticTextItem.numGlyphs = glyphCount;
5752 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5753 staticTextItem.glyphPositions = positions;
5755 extended->drawStaticTextItem(&staticTextItem);
5757 QTextItemInt textItem;
5758 textItem.fontEngine = fontEngine;
5760 QVarLengthArray<QFixed, 128> advances(glyphCount);
5761 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5762 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5763 qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5764 qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
5765 qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5767 textItem.glyphs.numGlyphs = glyphCount;
5768 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5769 textItem.glyphs.offsets = positions;
5770 textItem.glyphs.advances_x = advances.data();
5771 textItem.glyphs.advances_y = advances.data();
5772 textItem.glyphs.justifications = glyphJustifications.data();
5773 textItem.glyphs.attributes = glyphAttributes.data();
5775 engine->drawTextItem(QPointF(0, 0), textItem);
5778 QTextItemInt::RenderFlags flags;
5780 flags |= QTextItemInt::Underline;
5782 flags |= QTextItemInt::Overline;
5784 flags |= QTextItemInt::StrikeOut;
5786 drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5789 ? QTextCharFormat::SingleUnderline
5790 : QTextCharFormat::NoUnderline),
5791 flags, width.toReal(), QTextCharFormat());
5793 #endif // QT_NO_RAWFONT
5797 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5801 Draws the \a staticText at the \a topLeftPosition.
5803 \note The y-position is used as the top of the font.
5808 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5812 Draws the \a staticText at coordinates \a left and \a top.
5814 \note The y-position is used as the top of the font.
5818 \fn void QPainter::drawText(const QPointF &position, const QString &text)
5820 Draws the given \a text with the currently defined text direction,
5821 beginning at the given \a position.
5823 This function does not handle the newline character (\n), as it cannot
5824 break text into multiple lines, and it cannot display the newline character.
5825 Use the QPainter::drawText() overload that takes a rectangle instead
5826 if you want to draw multiple lines of text with the newline character, or
5827 if you want the text to be wrapped.
5829 By default, QPainter draws text anti-aliased.
5831 \note The y-position is used as the baseline of the font.
5834 void QPainter::drawText(const QPointF &p, const QString &str)
5836 drawText(p, str, 0, 0);
5842 Draws the given \a staticText at the given \a topLeftPosition.
5844 The text will be drawn using the font and the transformation set on the painter. If the
5845 font and/or transformation set on the painter are different from the ones used to initialize
5846 the layout of the QStaticText, then the layout will have to be recalculated. Use
5847 QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5848 it will later be drawn.
5850 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5851 last drawn, then there will be a slight overhead when translating the text to its new position.
5853 \note If the painter's transformation is not affine, then \a staticText will be drawn using
5854 regular calls to drawText(), losing any potential for performance improvement.
5856 \note The y-position is used as the top of the font.
5860 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5863 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5866 QStaticTextPrivate *staticText_d =
5867 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5869 if (font() != staticText_d->font) {
5870 staticText_d->font = font();
5871 staticText_d->needsRelayout = true;
5874 // If we don't have an extended paint engine, or if the painter is projected,
5875 // we go through standard code path
5876 if (d->extended == 0 || !d->state->matrix.isAffine()) {
5877 staticText_d->paintText(topLeftPosition, this);
5881 bool paintEngineSupportsTransformations = qt_paintengine_supports_transformations(d->extended->type());
5882 if (paintEngineSupportsTransformations && !staticText_d->untransformedCoordinates) {
5883 staticText_d->untransformedCoordinates = true;
5884 staticText_d->needsRelayout = true;
5885 } else if (!paintEngineSupportsTransformations && staticText_d->untransformedCoordinates) {
5886 staticText_d->untransformedCoordinates = false;
5887 staticText_d->needsRelayout = true;
5890 // Don't recalculate entire layout because of translation, rather add the dx and dy
5891 // into the position to move each text item the correct distance.
5892 QPointF transformedPosition = topLeftPosition;
5893 if (!staticText_d->untransformedCoordinates)
5894 transformedPosition = transformedPosition * d->state->matrix;
5895 QTransform oldMatrix;
5897 // The translation has been applied to transformedPosition. Remove translation
5898 // component from matrix.
5899 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
5900 qreal m11 = d->state->matrix.m11();
5901 qreal m12 = d->state->matrix.m12();
5902 qreal m13 = d->state->matrix.m13();
5903 qreal m21 = d->state->matrix.m21();
5904 qreal m22 = d->state->matrix.m22();
5905 qreal m23 = d->state->matrix.m23();
5906 qreal m33 = d->state->matrix.m33();
5908 oldMatrix = d->state->matrix;
5909 d->state->matrix.setMatrix(m11, m12, m13,
5914 // If the transform is not identical to the text transform,
5915 // we have to relayout the text (for other transformations than plain translation)
5916 bool staticTextNeedsReinit = staticText_d->needsRelayout;
5917 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
5918 staticText_d->matrix = d->state->matrix;
5919 staticTextNeedsReinit = true;
5922 // Recreate the layout of the static text because the matrix or font has changed
5923 if (staticTextNeedsReinit)
5924 staticText_d->init();
5926 if (transformedPosition != staticText_d->position) { // Translate to actual position
5927 QFixed fx = QFixed::fromReal(transformedPosition.x());
5928 QFixed fy = QFixed::fromReal(transformedPosition.y());
5929 QFixed oldX = QFixed::fromReal(staticText_d->position.x());
5930 QFixed oldY = QFixed::fromReal(staticText_d->position.y());
5931 for (int item=0; item<staticText_d->itemCount;++item) {
5932 QStaticTextItem *textItem = staticText_d->items + item;
5933 for (int i=0; i<textItem->numGlyphs; ++i) {
5934 textItem->glyphPositions[i].x += fx - oldX;
5935 textItem->glyphPositions[i].y += fy - oldY;
5937 textItem->userDataNeedsUpdate = true;
5940 staticText_d->position = transformedPosition;
5943 QPen oldPen = d->state->pen;
5944 QColor currentColor = oldPen.color();
5945 for (int i=0; i<staticText_d->itemCount; ++i) {
5946 QStaticTextItem *item = staticText_d->items + i;
5947 if (item->color.isValid() && currentColor != item->color) {
5948 setPen(item->color);
5949 currentColor = item->color;
5951 d->extended->drawStaticTextItem(item);
5953 qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
5954 item->numGlyphs, item->fontEngine(), staticText_d->font,
5957 if (currentColor != oldPen.color())
5960 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
5961 d->state->matrix = oldMatrix;
5967 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
5969 #ifdef QT_DEBUG_DRAW
5970 if (qt_show_painter_debug_output)
5971 printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
5976 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
5979 if (tf & Qt::TextBypassShaping) {
5980 // Skip harfbuzz complex shaping, shape using glyph advances only
5981 int len = str.length();
5982 int numGlyphs = len;
5983 QVarLengthGlyphLayoutArray glyphs(len);
5984 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
5985 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
5986 glyphs.resize(numGlyphs);
5987 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
5988 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
5991 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
5992 drawTextItem(p, gf);
5996 QStackTextEngine engine(str, d->state->font);
5997 engine.option.setTextDirection(d->state->layoutDirection);
5998 if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
5999 engine.ignoreBidi = true;
6000 engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
6004 line.length = str.length();
6005 engine.shapeLine(line);
6007 int nItems = engine.layoutData->items.size();
6008 QVarLengthArray<int> visualOrder(nItems);
6009 QVarLengthArray<uchar> levels(nItems);
6010 for (int i = 0; i < nItems; ++i)
6011 levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
6012 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
6014 if (justificationPadding > 0) {
6015 engine.option.setAlignment(Qt::AlignJustify);
6016 engine.forceJustification = true;
6017 // this works because justify() is only interested in the difference between width and textWidth
6018 line.width = justificationPadding;
6019 engine.justify(line);
6021 QFixed x = QFixed::fromReal(p.x());
6023 for (int i = 0; i < nItems; ++i) {
6024 int item = visualOrder[i];
6025 const QScriptItem &si = engine.layoutData->items.at(item);
6026 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
6030 QFont f = engine.font(si);
6031 QTextItemInt gf(si, &f);
6032 gf.glyphs = engine.shapedGlyphs(&si);
6033 gf.chars = engine.layoutData->string.unicode() + si.position;
6034 gf.num_chars = engine.length(item);
6035 if (engine.forceJustification) {
6036 for (int j=0; j<gf.glyphs.numGlyphs; ++j)
6037 gf.width += gf.glyphs.effectiveAdvance(j);
6039 gf.width = si.width;
6041 gf.logClusters = engine.logClusters(&si);
6043 drawTextItem(QPointF(x.toReal(), p.y()), gf);
6049 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
6051 #ifdef QT_DEBUG_DRAW
6052 if (qt_show_painter_debug_output)
6053 printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
6054 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6059 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6063 d->updateState(d->state);
6066 qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
6068 *br = bounds.toAlignedRect();
6072 \fn void QPainter::drawText(const QPoint &position, const QString &text)
6076 Draws the given \a text with the currently defined text direction,
6077 beginning at the given \a position.
6079 By default, QPainter draws text anti-aliased.
6081 \note The y-position is used as the baseline of the font.
6086 \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
6089 Draws the given \a text within the provided \a rectangle.
6093 \o \inlineimage qpainter-text.png
6095 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 17
6098 The \a boundingRect (if not null) is set to the what the bounding rectangle
6099 should be in order to enclose the whole text. The \a flags argument is a bitwise
6100 OR of the following flags:
6112 \o Qt::TextSingleLine
6113 \o Qt::TextExpandTabs
6114 \o Qt::TextShowMnemonic
6116 \o Qt::TextIncludeTrailingSpaces
6119 \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
6121 By default, QPainter draws text anti-aliased.
6123 \note The y-coordinate of \a rectangle is used as the top of the font.
6125 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
6127 #ifdef QT_DEBUG_DRAW
6128 if (qt_show_painter_debug_output)
6129 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
6130 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6135 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6139 d->updateState(d->state);
6141 qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
6145 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
6148 Draws the given \a text within the provided \a rectangle according
6149 to the specified \a flags. The \a boundingRect (if not null) is set to
6150 the what the bounding rectangle should be in order to enclose the whole text.
6152 By default, QPainter draws text anti-aliased.
6154 \note The y-coordinate of \a rectangle is used as the top of the font.
6158 \fn void QPainter::drawText(int x, int y, const QString &text)
6162 Draws the given \a text at position (\a{x}, \a{y}), using the painter's
6163 currently defined text direction.
6165 By default, QPainter draws text anti-aliased.
6167 \note The y-position is used as the baseline of the font.
6172 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6173 const QString &text, QRect *boundingRect)
6177 Draws the given \a text within the rectangle with origin (\a{x},
6178 \a{y}), \a width and \a height.
6180 The \a boundingRect (if not null) is set to the actual bounding
6181 rectangle of the output. The \a flags argument is a bitwise OR of
6182 the following flags:
6193 \o Qt::TextSingleLine
6194 \o Qt::TextExpandTabs
6195 \o Qt::TextShowMnemonic
6199 By default, QPainter draws text anti-aliased.
6201 \note The y-position is used as the top of the font.
6203 \sa Qt::AlignmentFlag, Qt::TextFlag
6207 \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6208 const QTextOption &option)
6211 Draws the given \a text in the \a rectangle specified using the \a option
6212 to control its positioning and orientation.
6214 By default, QPainter draws text anti-aliased.
6216 \note The y-coordinate of \a rectangle is used as the top of the font.
6218 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6220 #ifdef QT_DEBUG_DRAW
6221 if (qt_show_painter_debug_output)
6222 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6223 r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6228 if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6232 d->updateState(d->state);
6234 qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6238 \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6245 \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6250 Draws the text item \a ti at position \a p.
6254 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6259 Draws the text item \a ti at position \a p.
6261 This method ignores the painters background mode and
6262 color. drawText and qt_format_text have to do it themselves, as
6263 only they know the extents of the complete string.
6265 It ignores the font set on the painter as the text item has one of its own.
6267 The underline and strikeout parameters of the text items font are
6268 ignored aswell. You'll need to pass in the correct flags to get
6269 underlining and strikeout.
6272 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6274 const qreal radiusBase = qMax(qreal(1), maxRadius);
6276 QString key = QLatin1Literal("WaveUnderline-")
6277 % pen.color().name()
6278 % HexString<qreal>(radiusBase);
6281 if (QPixmapCache::find(key, pixmap))
6284 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6285 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6286 const int radius = qFloor(radiusBase);
6293 while (xs < width) {
6296 path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6299 pixmap = QPixmap(width, radius * 2);
6300 pixmap.fill(Qt::transparent);
6303 wavePen.setCapStyle(Qt::SquareCap);
6305 // This is to protect against making the line too fat, as happens on Mac OS X
6306 // due to it having a rather thick width for the regular underline.
6307 const qreal maxPenWidth = .8 * radius;
6308 if (wavePen.widthF() > maxPenWidth)
6309 wavePen.setWidth(maxPenWidth);
6311 QPainter imgPainter(&pixmap);
6312 imgPainter.setPen(wavePen);
6313 imgPainter.setRenderHint(QPainter::Antialiasing);
6314 imgPainter.translate(0, radius);
6315 imgPainter.drawPath(path);
6318 QPixmapCache::insert(key, pixmap);
6323 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
6324 QTextCharFormat::UnderlineStyle underlineStyle,
6325 QTextItem::RenderFlags flags, qreal width,
6326 const QTextCharFormat &charFormat)
6328 if (underlineStyle == QTextCharFormat::NoUnderline
6329 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6332 const QPen oldPen = painter->pen();
6333 const QBrush oldBrush = painter->brush();
6334 painter->setBrush(Qt::NoBrush);
6336 pen.setStyle(Qt::SolidLine);
6337 pen.setWidthF(fe->lineThickness().toReal());
6338 pen.setCapStyle(Qt::FlatCap);
6340 QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6342 const qreal underlineOffset = fe->underlinePosition().toReal();
6343 // deliberately ceil the offset to avoid the underline coming too close to
6344 // the text above it.
6345 const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
6346 const qreal underlinePos = pos.y() + qCeil(underlineOffset) - aliasedCoordinateDelta;
6348 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6349 underlineStyle = QTextCharFormat::SpellCheckUnderline; // ### Qt5 QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle));
6352 if (underlineStyle == QTextCharFormat::WaveUnderline) {
6354 painter->translate(0, pos.y() + 1);
6356 QColor uc = charFormat.underlineColor();
6360 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6361 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6362 const int descent = (int) fe->descent().toReal();
6364 painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6365 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6367 } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6368 QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos);
6370 QColor uc = charFormat.underlineColor();
6374 pen.setStyle((Qt::PenStyle)(underlineStyle));
6375 painter->setPen(pen);
6376 painter->drawLine(underLine);
6379 pen.setStyle(Qt::SolidLine);
6380 pen.setColor(oldPen.color());
6382 if (flags & QTextItem::StrikeOut) {
6383 QLineF strikeOutLine = line;
6384 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6385 painter->setPen(pen);
6386 painter->drawLine(strikeOutLine);
6389 if (flags & QTextItem::Overline) {
6390 QLineF overLine = line;
6391 overLine.translate(0., - fe->ascent().toReal());
6392 painter->setPen(pen);
6393 painter->drawLine(overLine);
6396 painter->setPen(oldPen);
6397 painter->setBrush(oldBrush);
6400 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6401 const QFixedPoint *positions, int glyphCount,
6402 QFontEngine *fontEngine, const QFont &font,
6403 const QTextCharFormat &charFormat)
6405 if (!(font.underline() || font.strikeOut() || font.overline()))
6411 for (int i=0; i<glyphCount; ++i) {
6412 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6413 if (i == 0 || leftMost > positions[i].x)
6414 leftMost = positions[i].x;
6416 // We don't support glyphs that do not share a common baseline. If this turns out to
6417 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6418 // and do a drawTextItemDecorations call per cluster.
6419 if (i == 0 || baseLine < positions[i].y)
6420 baseLine = positions[i].y;
6422 // We use the advance rather than the actual bounds to match the algorithm in drawText()
6423 if (i == 0 || rightMost < positions[i].x + gm.xoff)
6424 rightMost = positions[i].x + gm.xoff;
6427 QFixed width = rightMost - leftMost;
6428 QTextItem::RenderFlags flags = 0;
6430 if (font.underline())
6431 flags |= QTextItem::Underline;
6432 if (font.overline())
6433 flags |= QTextItem::Overline;
6434 if (font.strikeOut())
6435 flags |= QTextItem::StrikeOut;
6437 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6439 font.underline() ? QTextCharFormat::SingleUnderline
6440 : QTextCharFormat::NoUnderline, flags,
6441 width.toReal(), charFormat);
6444 void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
6446 #ifdef QT_DEBUG_DRAW
6447 if (qt_show_painter_debug_output)
6448 printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6449 p.x(), p.y(), qPrintable(_ti.text()));
6458 qt_painter_thread_test(d->device->devType(),
6460 QFontDatabase::supportsThreadedFontRendering());
6463 QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6465 if (!d->extended && d->state->bgMode == Qt::OpaqueMode) {
6466 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6467 fillRect(rect, d->state->bgBrush);
6470 if (pen().style() == Qt::NoPen)
6473 const RenderHints oldRenderHints = d->state->renderHints;
6474 if (!d->state->renderHints & QPainter::Antialiasing && d->state->matrix.type() >= QTransform::TxScale) {
6475 // draw antialias decoration (underline/overline/strikeout) with
6479 const QTransform &m = d->state->matrix;
6480 if (d->state->matrix.type() < QTransform::TxShear) {
6481 bool isPlain90DegreeRotation =
6482 (qFuzzyIsNull(m.m11())
6483 && qFuzzyIsNull(m.m12() - qreal(1))
6484 && qFuzzyIsNull(m.m21() + qreal(1))
6485 && qFuzzyIsNull(m.m22())
6488 (qFuzzyIsNull(m.m11() + qreal(1))
6489 && qFuzzyIsNull(m.m12())
6490 && qFuzzyIsNull(m.m21())
6491 && qFuzzyIsNull(m.m22() + qreal(1))
6494 (qFuzzyIsNull(m.m11())
6495 && qFuzzyIsNull(m.m12() + qreal(1))
6496 && qFuzzyIsNull(m.m21() - qreal(1))
6497 && qFuzzyIsNull(m.m22())
6500 aa = !isPlain90DegreeRotation;
6503 setRenderHint(QPainter::Antialiasing, true);
6507 d->updateState(d->state);
6509 if (!ti.glyphs.numGlyphs) {
6511 } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6512 QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6514 const QGlyphLayout &glyphs = ti.glyphs;
6515 int which = glyphs.glyphs[0] >> 24;
6522 for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6523 const int e = glyphs.glyphs[end] >> 24;
6528 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6530 // set the high byte to zero and calc the width
6531 for (i = start; i < end; ++i) {
6532 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6533 ti2.width += ti.glyphs.effectiveAdvance(i);
6536 d->engine->drawTextItem(QPointF(x, y), ti2);
6538 // reset the high byte for all glyphs and advance to the next sub-string
6539 const int hi = which << 24;
6540 for (i = start; i < end; ++i) {
6541 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6543 x += ti2.width.toReal();
6550 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6552 // set the high byte to zero and calc the width
6553 for (i = start; i < end; ++i) {
6554 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6555 ti2.width += ti.glyphs.effectiveAdvance(i);
6559 d->extended->drawTextItem(QPointF(x, y), ti2);
6561 d->engine->drawTextItem(QPointF(x,y), ti2);
6563 // reset the high byte for all glyphs
6564 const int hi = which << 24;
6565 for (i = start; i < end; ++i)
6566 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6570 d->extended->drawTextItem(p, ti);
6572 d->engine->drawTextItem(p, ti);
6574 drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(),
6577 if (d->state->renderHints != oldRenderHints) {
6578 d->state->renderHints = oldRenderHints;
6580 d->extended->renderHintsChanged();
6582 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
6587 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6589 Returns the bounding rectangle of the \a text as it will appear
6590 when drawn inside the given \a rectangle with the specified \a
6591 flags using the currently set font(); i.e the function tells you
6592 where the drawText() function will draw when given the same
6595 If the \a text does not fit within the given \a rectangle using
6596 the specified \a flags, the function returns the required
6599 The \a flags argument is a bitwise OR of the following flags:
6608 \o Qt::TextSingleLine
6609 \o Qt::TextExpandTabs
6610 \o Qt::TextShowMnemonic
6612 \o Qt::TextIncludeTrailingSpaces
6614 If several of the horizontal or several of the vertical alignment
6615 flags are set, the resulting alignment is undefined.
6617 \sa drawText(), Qt::Alignment, Qt::TextFlag
6621 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6622 const QString &text)
6626 Returns the bounding rectangle of the \a text as it will appear
6627 when drawn inside the given \a rectangle with the specified \a
6628 flags using the currently set font().
6632 \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6633 const QString &text);
6637 Returns the bounding rectangle of the given \a text as it will
6638 appear when drawn inside the rectangle beginning at the point
6639 (\a{x}, \a{y}) with width \a w and height \a h.
6641 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6644 return QRect(rect.x(),rect.y(), 0,0);
6646 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6652 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6655 return QRectF(rect.x(),rect.y(), 0,0);
6657 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6662 \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6663 const QString &text, const QTextOption &option)
6667 Instead of specifying flags as a bitwise OR of the
6668 Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6669 an \a option argument. The QTextOption class provides a
6670 description of general rich text properties.
6674 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6678 if (!d->engine || text.length() == 0)
6679 return QRectF(r.x(),r.y(), 0,0);
6682 qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6687 \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6689 Draws a tiled \a pixmap, inside the given \a rectangle with its
6690 origin at the given \a position.
6692 Calling drawTiledPixmap() is similar to calling drawPixmap()
6693 several times to fill (tile) an area with a pixmap, but is
6694 potentially much more efficient depending on the underlying window
6699 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6701 #ifdef QT_DEBUG_DRAW
6702 if (qt_show_painter_debug_output)
6703 printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6704 r.x(), r.y(), r.width(), r.height(),
6705 pixmap.width(), pixmap.height(),
6710 if (!d->engine || pixmap.isNull() || r.isEmpty())
6714 qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6717 qreal sw = pixmap.width();
6718 qreal sh = pixmap.height();
6722 sx = qRound(sw) - qRound(-sx) % qRound(sw);
6724 sx = qRound(sx) % qRound(sw);
6726 sy = qRound(sh) - -qRound(sy) % qRound(sh);
6728 sy = qRound(sy) % qRound(sh);
6732 d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6736 if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6737 fillRect(r, d->state->bgBrush);
6739 d->updateState(d->state);
6740 if ((d->state->matrix.type() > QTransform::TxTranslate
6741 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6742 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6745 setBackgroundMode(Qt::TransparentMode);
6746 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6747 setBrush(QBrush(d->state->pen.color(), pixmap));
6750 // If there is no rotation involved we have to make sure we use the
6751 // antialiased and not the aliased coordinate system by rounding the coordinates.
6752 if (d->state->matrix.type() <= QTransform::TxScale) {
6753 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6755 if (d->state->matrix.type() <= QTransform::TxTranslate) {
6760 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6761 drawRect(QRectF(p, r.size()));
6763 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6772 if (d->state->matrix.type() == QTransform::TxTranslate
6773 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6774 x += d->state->matrix.dx();
6775 y += d->state->matrix.dy();
6778 d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6782 \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6783 const QPoint &position = QPoint())
6786 Draws a tiled \a pixmap, inside the given \a rectangle with its
6787 origin at the given \a position.
6791 \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6792 QPixmap &pixmap, int sx, int sy);
6795 Draws a tiled \a pixmap in the specified rectangle.
6797 (\a{x}, \a{y}) specifies the top-left point in the paint device
6798 that is to be drawn onto; with the given \a width and \a
6799 height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6800 pixmap that is to be drawn; this defaults to (0, 0).
6803 #ifndef QT_NO_PICTURE
6806 \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6808 Replays the given \a picture at the given \a point.
6810 The QPicture class is a paint device that records and replays
6811 QPainter commands. A picture serializes the painter commands to an
6812 IO device in a platform-independent format. Everything that can be
6813 painted on a widget or pixmap can also be stored in a picture.
6815 This function does exactly the same as QPicture::play() when
6816 called with \a point = QPoint(0, 0).
6821 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 18
6824 \sa QPicture::play()
6827 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6835 d->updateState(d->state);
6839 const_cast<QPicture *>(&picture)->play(this);
6844 \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6847 Replays the given \a picture at the given \a point.
6851 \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6854 Draws the given \a picture at point (\a x, \a y).
6857 #endif // QT_NO_PICTURE
6860 \fn void QPainter::eraseRect(const QRectF &rectangle)
6862 Erases the area inside the given \a rectangle. Equivalent to
6864 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 19
6868 void QPainter::eraseRect(const QRectF &r)
6872 fillRect(r, d->state->bgBrush);
6875 static inline bool needsResolving(const QBrush &brush)
6877 Qt::BrushStyle s = brush.style();
6878 return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
6879 s == Qt::ConicalGradientPattern) &&
6880 brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
6884 \fn void QPainter::eraseRect(const QRect &rectangle)
6887 Erases the area inside the given \a rectangle.
6891 \fn void QPainter::eraseRect(int x, int y, int width, int height)
6894 Erases the area inside the rectangle beginning at (\a x, \a y)
6895 with the given \a width and \a height.
6900 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
6903 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6904 width and \a height, using the brush \a style specified.
6910 \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
6913 Fills the given \a rectangle with the brush \a style specified.
6919 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
6922 Fills the given \a rectangle with the brush \a style specified.
6928 \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
6930 Fills the given \a rectangle with the \a brush specified.
6932 Alternatively, you can specify a QColor instead of a QBrush; the
6933 QBrush constructor (taking a QColor argument) will automatically
6934 create a solid pattern brush.
6938 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
6946 const QGradient *g = brush.gradient();
6947 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6948 d->extended->fillRect(r, brush);
6953 QPen oldPen = pen();
6954 QBrush oldBrush = this->brush();
6956 if (brush.style() == Qt::SolidPattern) {
6957 d->colorBrush.setStyle(Qt::SolidPattern);
6958 d->colorBrush.setColor(brush.color());
6959 setBrush(d->colorBrush);
6970 \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
6973 Fills the given \a rectangle with the specified \a brush.
6976 void QPainter::fillRect(const QRect &r, const QBrush &brush)
6984 const QGradient *g = brush.gradient();
6985 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6986 d->extended->fillRect(r, brush);
6991 QPen oldPen = pen();
6992 QBrush oldBrush = this->brush();
6994 if (brush.style() == Qt::SolidPattern) {
6995 d->colorBrush.setStyle(Qt::SolidPattern);
6996 d->colorBrush.setColor(brush.color());
6997 setBrush(d->colorBrush);
7010 \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
7013 Fills the given \a rectangle with the \a color specified.
7017 void QPainter::fillRect(const QRect &r, const QColor &color)
7025 d->extended->fillRect(r, color);
7029 fillRect(r, QBrush(color));
7034 \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
7037 Fills the given \a rectangle with the \a color specified.
7041 void QPainter::fillRect(const QRectF &r, const QColor &color)
7049 d->extended->fillRect(r, color);
7053 fillRect(r, QBrush(color));
7057 \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
7061 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7062 width and \a height, using the given \a brush.
7066 \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
7070 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7071 width and \a height, using the given \a color.
7077 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
7081 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7082 width and \a height, using the given \a color.
7088 \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
7092 Fills the given \a rectangle with the specified \a color.
7098 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
7102 Fills the given \a rectangle with the specified \a color.
7108 Sets the given render \a hint on the painter if \a on is true;
7109 otherwise clears the render hint.
7111 \sa setRenderHints(), renderHints(), {QPainter#Rendering
7112 Quality}{Rendering Quality}
7114 void QPainter::setRenderHint(RenderHint hint, bool on)
7116 #ifdef QT_DEBUG_DRAW
7117 if (qt_show_painter_debug_output)
7118 printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
7122 static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
7123 if (hint == QPainter::Antialiasing && antialiasingDisabled)
7127 setRenderHints(hint, on);
7133 Sets the given render \a hints on the painter if \a on is true;
7134 otherwise clears the render hints.
7136 \sa setRenderHint(), renderHints(), {QPainter#Rendering
7137 Quality}{Rendering Quality}
7140 void QPainter::setRenderHints(RenderHints hints, bool on)
7145 qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7150 d->state->renderHints |= hints;
7152 d->state->renderHints &= ~hints;
7155 d->extended->renderHintsChanged();
7157 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7161 Returns a flag that specifies the rendering hints that are set for
7164 \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7166 QPainter::RenderHints QPainter::renderHints() const
7168 Q_D(const QPainter);
7173 return d->state->renderHints;
7177 \fn bool QPainter::testRenderHint(RenderHint hint) const
7180 Returns true if \a hint is set; otherwise returns false.
7182 \sa renderHints(), setRenderHint()
7186 Returns true if view transformation is enabled; otherwise returns
7189 \sa setViewTransformEnabled(), worldTransform()
7192 bool QPainter::viewTransformEnabled() const
7194 Q_D(const QPainter);
7196 qWarning("QPainter::viewTransformEnabled: Painter not active");
7199 return d->state->VxF;
7203 \fn void QPainter::setWindow(const QRect &rectangle)
7205 Sets the painter's window to the given \a rectangle, and enables
7206 view transformations.
7208 The window rectangle is part of the view transformation. The
7209 window specifies the logical coordinate system. Its sister, the
7210 viewport(), specifies the device coordinate system.
7212 The default window rectangle is the same as the device's
7215 \sa window(), viewTransformEnabled(), {Coordinate
7216 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7220 \fn void QPainter::setWindow(int x, int y, int width, int height)
7223 Sets the painter's window to the rectangle beginning at (\a x, \a
7224 y) and the given \a width and \a height.
7227 void QPainter::setWindow(const QRect &r)
7229 #ifdef QT_DEBUG_DRAW
7230 if (qt_show_painter_debug_output)
7231 printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7237 qWarning("QPainter::setWindow: Painter not active");
7241 d->state->wx = r.x();
7242 d->state->wy = r.y();
7243 d->state->ww = r.width();
7244 d->state->wh = r.height();
7246 d->state->VxF = true;
7251 Returns the window rectangle.
7253 \sa setWindow(), setViewTransformEnabled()
7256 QRect QPainter::window() const
7258 Q_D(const QPainter);
7260 qWarning("QPainter::window: Painter not active");
7263 return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7267 \fn void QPainter::setViewport(const QRect &rectangle)
7269 Sets the painter's viewport rectangle to the given \a rectangle,
7270 and enables view transformations.
7272 The viewport rectangle is part of the view transformation. The
7273 viewport specifies the device coordinate system. Its sister, the
7274 window(), specifies the logical coordinate system.
7276 The default viewport rectangle is the same as the device's
7279 \sa viewport(), viewTransformEnabled() {Coordinate
7280 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7284 \fn void QPainter::setViewport(int x, int y, int width, int height)
7287 Sets the painter's viewport rectangle to be the rectangle
7288 beginning at (\a x, \a y) with the given \a width and \a height.
7291 void QPainter::setViewport(const QRect &r)
7293 #ifdef QT_DEBUG_DRAW
7294 if (qt_show_painter_debug_output)
7295 printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7301 qWarning("QPainter::setViewport: Painter not active");
7305 d->state->vx = r.x();
7306 d->state->vy = r.y();
7307 d->state->vw = r.width();
7308 d->state->vh = r.height();
7310 d->state->VxF = true;
7315 Returns the viewport rectangle.
7317 \sa setViewport(), setViewTransformEnabled()
7320 QRect QPainter::viewport() const
7322 Q_D(const QPainter);
7324 qWarning("QPainter::viewport: Painter not active");
7327 return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7330 /*! \fn bool QPainter::hasViewXForm() const
7333 Use viewTransformEnabled() instead.
7336 /*! \fn bool QPainter::hasWorldXForm() const
7339 Use worldMatrixEnabled() instead.
7342 /*! \fn void QPainter::resetXForm()
7345 Use resetTransform() instead.
7348 /*! \fn void QPainter::setViewXForm(bool enabled)
7351 Use setViewTransformEnabled() instead.
7354 /*! \fn void QPainter::setWorldXForm(bool enabled)
7357 Use setWorldMatrixEnabled() instead.
7360 Enables view transformations if \a enable is true, or disables
7361 view transformations if \a enable is false.
7363 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7364 Conversion}{Window-Viewport Conversion}
7367 void QPainter::setViewTransformEnabled(bool enable)
7369 #ifdef QT_DEBUG_DRAW
7370 if (qt_show_painter_debug_output)
7371 printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7377 qWarning("QPainter::setViewTransformEnabled: Painter not active");
7381 if (enable == d->state->VxF)
7384 d->state->VxF = enable;
7393 Please use QWidget::render() instead.
7395 Redirects all paint commands for the given paint \a device, to the
7396 \a replacement device. The optional point \a offset defines an
7397 offset within the source device.
7399 The redirection will not be effective until the begin() function
7400 has been called; make sure to call end() for the given \a
7401 device's painter (if any) before redirecting. Call
7402 restoreRedirected() to restore the previous redirection.
7404 \warning Making use of redirections in the QPainter API implies
7405 that QPainter::begin() and QPaintDevice destructors need to hold
7406 a mutex for a short period. This can impact performance. Use of
7407 QWidget::render is strongly encouraged.
7409 \sa redirected(), restoreRedirected()
7411 void QPainter::setRedirected(const QPaintDevice *device,
7412 QPaintDevice *replacement,
7413 const QPoint &offset)
7415 Q_ASSERT(device != 0);
7417 qWarning() << "QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead";
7425 Using QWidget::render() obsoletes the use of this function.
7427 Restores the previous redirection for the given \a device after a
7428 call to setRedirected().
7430 \warning Making use of redirections in the QPainter API implies
7431 that QPainter::begin() and QPaintDevice destructors need to hold
7432 a mutex for a short period. This can impact performance. Use of
7433 QWidget::render is strongly encouraged.
7437 void QPainter::restoreRedirected(const QPaintDevice *device)
7439 qWarning() << "QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead";
7447 Using QWidget::render() obsoletes the use of this function.
7449 Returns the replacement for given \a device. The optional out
7450 parameter \a offset returns the offset within the replaced device.
7452 \warning Making use of redirections in the QPainter API implies
7453 that QPainter::begin() and QPaintDevice destructors need to hold
7454 a mutex for a short period. This can impact performance. Use of
7455 QWidget::render is strongly encouraged.
7457 \sa setRedirected(), restoreRedirected()
7459 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7464 void qt_format_text(const QFont &fnt, const QRectF &_r,
7465 int tf, const QString& str, QRectF *brect,
7466 int tabstops, int *ta, int tabarraylen,
7469 qt_format_text(fnt, _r,
7471 tabstops, ta, tabarraylen,
7474 void qt_format_text(const QFont &fnt, const QRectF &_r,
7475 int tf, const QTextOption *option, const QString& str, QRectF *brect,
7476 int tabstops, int *ta, int tabarraylen,
7480 Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
7483 tf |= option->alignment();
7484 if (option->wrapMode() != QTextOption::NoWrap)
7485 tf |= Qt::TextWordWrap;
7487 if (option->flags() & QTextOption::IncludeTrailingSpaces)
7488 tf |= Qt::TextIncludeTrailingSpaces;
7490 if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
7491 tf |= Qt::TextExpandTabs;
7494 // we need to copy r here to protect against the case (&r == brect).
7497 bool dontclip = (tf & Qt::TextDontClip);
7498 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
7499 bool singleline = (tf & Qt::TextSingleLine);
7500 bool showmnemonic = (tf & Qt::TextShowMnemonic);
7501 bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
7503 Qt::LayoutDirection layout_direction;
7504 if (tf & Qt::TextForceLeftToRight)
7505 layout_direction = Qt::LeftToRight;
7506 else if (tf & Qt::TextForceRightToLeft)
7507 layout_direction = Qt::RightToLeft;
7509 layout_direction = option->textDirection();
7511 layout_direction = painter->layoutDirection();
7513 layout_direction = Qt::LeftToRight;
7515 tf = QGuiApplicationPrivate::visualAlignment(layout_direction, QFlag(tf));
7517 bool isRightToLeft = layout_direction == Qt::RightToLeft;
7518 bool expandtabs = ((tf & Qt::TextExpandTabs) &&
7519 (((tf & Qt::AlignLeft) && !isRightToLeft) ||
7520 ((tf & Qt::AlignRight) && isRightToLeft)));
7523 tf |= Qt::TextDontPrint;
7525 uint maxUnderlines = 0;
7526 int numUnderlines = 0;
7527 QVarLengthArray<int, 32> underlinePositions(1);
7529 QFontMetricsF fm(fnt);
7532 start_lengthVariant:
7533 bool hasMoreLengthVariants = false;
7534 // compatible behaviour to the old implementation. Replace
7536 int old_offset = offset;
7537 for (; offset < text.length(); offset++) {
7538 QChar chr = text.at(offset);
7539 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
7540 text[offset] = QLatin1Char(' ');
7541 } else if (chr == QLatin1Char('\n')) {
7542 text[offset] = QChar::LineSeparator;
7543 } else if (chr == QLatin1Char('&')) {
7545 } else if (chr == QLatin1Char('\t')) {
7547 text[offset] = QLatin1Char(' ');
7548 } else if (!tabarraylen && !tabstops) {
7549 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
7551 } else if (chr == QChar(ushort(0x9c))) {
7552 // string with multiple length variants
7553 hasMoreLengthVariants = true;
7558 int length = offset - old_offset;
7559 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
7560 underlinePositions.resize(maxUnderlines + 1);
7562 QChar *cout = text.data() + old_offset;
7566 if (*cin == QLatin1Char('&')) {
7572 if (*cin != QLatin1Char('&') && !hidemnmemonic)
7573 underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
7582 // no need to do extra work for underlines if we don't paint
7583 if (tf & Qt::TextDontPrint)
7586 underlinePositions[numUnderlines] = -1;
7590 QString finalText = text.mid(old_offset, length);
7591 QStackTextEngine engine(finalText, fnt);
7593 engine.option = *option;
7596 if (engine.option.tabStop() < 0 && tabstops > 0)
7597 engine.option.setTabStop(tabstops);
7599 if (engine.option.tabs().isEmpty() && ta) {
7601 for (int i = 0; i < tabarraylen; i++)
7602 tabs.append(qreal(ta[i]));
7603 engine.option.setTabArray(tabs);
7606 engine.option.setTextDirection(layout_direction);
7607 if (tf & Qt::AlignJustify)
7608 engine.option.setAlignment(Qt::AlignJustify);
7610 engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
7612 if (!option && (tf & Qt::TextWrapAnywhere))
7613 engine.option.setWrapMode(QTextOption::WrapAnywhere);
7615 if (tf & Qt::TextJustificationForced)
7616 engine.forceJustification = true;
7617 QTextLayout textLayout(&engine);
7618 textLayout.setCacheEnabled(true);
7619 textLayout.engine()->underlinePositions = underlinePositions.data();
7621 if (finalText.isEmpty()) {
7622 height = fm.height();
7624 tf |= Qt::TextDontPrint;
7626 qreal lineWidth = 0x01000000;
7627 if (wordwrap || (tf & Qt::TextJustificationForced))
7628 lineWidth = qMax<qreal>(0, r.width());
7630 tf |= Qt::TextIncludeTrailingSpaces;
7631 textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
7632 textLayout.beginLayout();
7634 qreal leading = fm.leading();
7638 QTextLine l = textLayout.createLine();
7642 l.setLineWidth(lineWidth);
7644 l.setPosition(QPointF(0., height));
7645 height += l.height();
7646 width = qMax(width, l.naturalTextWidth());
7647 if (!dontclip && !brect && height >= r.height())
7650 textLayout.endLayout();
7655 if (tf & Qt::AlignBottom) {
7656 yoff = r.height() - height;
7657 } else if (tf & Qt::AlignVCenter) {
7658 yoff = (r.height() - height)/2;
7660 QTransform::TransformationType type = painter->transform().type();
7661 if (type <= QTransform::TxScale) {
7662 // do the rounding manually to work around inconsistencies
7663 // in the paint engines when drawing on floating point offsets
7664 const qreal scale = painter->transform().m22();
7666 yoff = -qRound(-yoff * scale) / scale;
7670 if (tf & Qt::AlignRight) {
7671 xoff = r.width() - width;
7672 } else if (tf & Qt::AlignHCenter) {
7673 xoff = (r.width() - width)/2;
7675 QTransform::TransformationType type = painter->transform().type();
7676 if (type <= QTransform::TxScale) {
7677 // do the rounding manually to work around inconsistencies
7678 // in the paint engines when drawing on floating point offsets
7679 const qreal scale = painter->transform().m11();
7681 xoff = qRound(xoff * scale) / scale;
7685 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
7687 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
7689 goto start_lengthVariant;
7694 if (!(tf & Qt::TextDontPrint)) {
7695 bool restore = false;
7696 if (!dontclip && !r.contains(bounds)) {
7699 painter->setClipRect(r, Qt::IntersectClip);
7702 for (int i = 0; i < textLayout.lineCount(); i++) {
7703 QTextLine line = textLayout.lineAt(i);
7705 qreal advance = line.horizontalAdvance();
7707 if (tf & Qt::AlignRight) {
7708 QTextEngine *eng = textLayout.engine();
7709 xoff = r.width() - advance -
7710 eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
7712 else if (tf & Qt::AlignHCenter)
7713 xoff = (r.width() - advance) / 2;
7715 line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
7725 Sets the layout direction used by the painter when drawing text,
7726 to the specified \a direction.
7728 The default is Qt::LayoutDirectionAuto, which will implicitly determine the
7729 direction from the text drawn.
7731 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
7733 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
7737 d->state->layoutDirection = direction;
7741 Returns the layout direction used by the painter when drawing text.
7743 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
7745 Qt::LayoutDirection QPainter::layoutDirection() const
7747 Q_D(const QPainter);
7748 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
7751 QPainterState::QPainterState(const QPainterState *s)
7752 : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
7753 pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
7754 clipRegion(s->clipRegion), clipPath(s->clipPath),
7755 clipOperation(s->clipOperation),
7756 renderHints(s->renderHints), clipInfo(s->clipInfo),
7757 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
7758 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
7759 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
7760 opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
7761 clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
7762 layoutDirection(s->layoutDirection),
7763 composition_mode(s->composition_mode),
7764 emulationSpecifier(s->emulationSpecifier), changeFlags(0)
7766 dirtyFlags = s->dirtyFlags;
7769 QPainterState::QPainterState()
7770 : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
7772 wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
7773 opacity(1), WxF(false), VxF(false), clipEnabled(true),
7774 bgMode(Qt::TransparentMode), painter(0),
7775 layoutDirection(QGuiApplication::layoutDirection()),
7776 composition_mode(QPainter::CompositionMode_SourceOver),
7777 emulationSpecifier(0), changeFlags(0)
7782 QPainterState::~QPainterState()
7786 void QPainterState::init(QPainter *p) {
7787 bgBrush = Qt::white;
7788 bgMode = Qt::TransparentMode;
7792 wx = wy = ww = wh = 0;
7793 vx = vy = vw = vh = 0;
7796 brushOrigin = QPointF(0, 0);
7798 font = deviceFont = QFont();
7799 clipRegion = QRegion();
7800 clipPath = QPainterPath();
7801 clipOperation = Qt::NoClip;
7803 worldMatrix.reset();
7805 layoutDirection = QGuiApplication::layoutDirection();
7806 composition_mode = QPainter::CompositionMode_SourceOver;
7807 emulationSpecifier = 0;
7815 \fn void QPainter::setBackgroundColor(const QColor &color)
7817 Use setBackground() instead.
7821 \fn const QColor &QPainter::backgroundColor() const
7823 Use background() and QBrush::color() instead.
7826 QColor myColor = backgroundColor();
7828 QColor myColor = background().color();
7831 Note that the background can be a complex brush such as a texture
7836 \fn void QPainter::drawText(int x, int y, const QString &text, int pos, int length)
7839 Use drawText() combined with QString::mid() instead.
7842 QPainter painter(this);
7843 painter.drawText(x, y, text, pos, length);
7845 QPainter painter(this);
7846 painter.drawText(x, y, text.mid(pos, length));
7851 \fn void QPainter::drawText(const QPoint &point, const QString &text, int pos, int length)
7854 Use drawText() combined with QString::mid() instead.
7857 QPainter painter(this);
7858 painter.drawText(point, text, pos, length);
7860 QPainter painter(this);
7861 painter.drawText(point, text.mid(pos, length));
7866 \fn void QPainter::drawText(int x, int y, const QString &text, int length)
7869 Use drawText() combined with QString::left() instead.
7872 QPainter painter(this);
7873 painter.drawText(x, y, text, length);
7875 QPainter painter(this);
7876 painter.drawText(x, y, text.left(length));
7881 \fn void QPainter::drawText(const QPoint &point, const QString &text, int length)
7884 Use drawText() combined with QString::left() instead.
7887 QPainter painter(this);
7888 painter.drawText(point, text, length);
7890 QPainter painter(this);
7891 painter.drawText(point, text.left(length));
7896 \fn bool QPainter::begin(QPaintDevice *device, const QWidget *init)
7899 Use begin() instead.
7901 If the paint \a device is a QWidget, QPainter is initialized after
7902 the widget's settings automatically. Otherwise, you must call the
7903 initFrom() function to initialize the painters pen, background and
7904 font to the same as any given widget.
7907 QPainter painter(this);
7908 painter.begin(device, init);
7910 QPainter painter(this);
7911 painter.begin(device);
7912 painter.initFrom(init);
7917 \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
7918 Qt::ImageConversionFlags flags)
7920 Draws the rectangular portion \a source of the given \a image
7921 into the \a target rectangle in the paint device.
7923 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7925 If the image needs to be modified to fit in a lower-resolution
7926 result (e.g. converting from 32-bit to 8-bit), use the \a flags to
7927 specify how you would prefer this to happen.
7932 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 20
7939 \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
7940 Qt::ImageConversionFlags flags)
7943 Draws the rectangular portion \a source of the given \a image
7944 into the \a target rectangle in the paint device.
7946 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7950 \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
7954 Draws the given \a image at the given \a point.
7958 \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
7962 Draws the given \a image at the given \a point.
7966 \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
7967 Qt::ImageConversionFlags flags = 0)
7971 Draws the rectangular portion \a source of the given \a image with
7972 its origin at the given \a point.
7976 \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
7977 Qt::ImageConversionFlags flags = 0)
7980 Draws the rectangular portion \a source of the given \a image with
7981 its origin at the given \a point.
7985 \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
7989 Draws the given \a image into the given \a rectangle.
7991 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7995 \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
7999 Draws the given \a image into the given \a rectangle.
8001 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8005 \fn void QPainter::drawImage(int x, int y, const QImage &image,
8006 int sx, int sy, int sw, int sh,
8007 Qt::ImageConversionFlags flags)
8010 Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
8013 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
8014 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
8015 image that is to be drawn. The default is (0, 0).
8017 (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
8018 The default, (0, 0) (and negative) means all the way to the
8019 bottom-right of the image.
8023 \fn void QPainter::redirect(QPaintDevice *pdev, QPaintDevice *replacement)
8025 Use setRedirected() instead.
8029 \fn QPaintDevice *QPainter::redirect(QPaintDevice *pdev)
8031 Use redirected() instead.
8035 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
8036 const QString &text, int length)
8039 Returns the bounding rectangle for the given \a length of the \a
8040 text constrained by the provided \a rectangle.
8042 Use boundingRect() combined with QString::left() instead.
8045 QRect rectangle = boundingRect(rect, flags, text, length);
8047 QRect rectangle = boundingRect(rect, flags, text.left(length));
8052 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text,
8053 int length, QRect *br)
8056 Use drawText() combined with QString::left() instead.
8059 QPainter painter(this);
8060 painter.drawText(rectangle, flags, text, length, br );
8062 QPainter painter(this);
8063 painter.drawText(rectangle, flags, text.left(length), br );
8068 \fn QRect QPainter::boundingRect(int x, int y, int width, int height, int flags,
8069 const QString &text, int length);
8073 Returns the bounding rectangle for the given \a length of the \a
8074 text constrained by the rectangle that begins at point (\a{x},
8075 \a{y}) with the given \a width and \a height.
8077 Use boundingRect() combined with QString::left() instead.
8080 QRect rectangle = boundingRect(x, y, width, height, flags, text, length);
8082 QRect rectangle = boundingRect(x, y, width, height, flags, text.left(length));
8087 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
8088 const QString &text, int length, QRect *br)
8092 Use drawText() combined with QString::left() instead.
8095 QPainter painter(this);
8096 painter.drawText(x, y, width, height, flags, text, length, br );
8098 QPainter painter(this);
8099 painter.drawText(x, y, width, height, flags, text.left(length), br );
8105 \class QPaintEngineState
8108 \brief The QPaintEngineState class provides information about the
8109 active paint engine's current state.
8112 QPaintEngineState records which properties that have changed since
8113 the last time the paint engine was updated, as well as their
8116 Which properties that have changed can at any time be retrieved
8117 using the state() function. This function returns an instance of
8118 the QPaintEngine::DirtyFlags type which stores an OR combination
8119 of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
8120 enum defines whether a property has changed since the last update
8123 If a property is marked with a dirty flag, its current value can
8124 be retrieved using the corresponding get function:
8129 \header \o Property Flag \o Current Property Value
8130 \row \o QPaintEngine::DirtyBackground \o backgroundBrush()
8131 \row \o QPaintEngine::DirtyBackgroundMode \o backgroundMode()
8132 \row \o QPaintEngine::DirtyBrush \o brush()
8133 \row \o QPaintEngine::DirtyBrushOrigin \o brushOrigin()
8134 \row \o QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
8136 \row \o QPaintEngine::DirtyClipPath \o clipPath()
8137 \row \o QPaintEngine::DirtyClipRegion \o clipRegion()
8138 \row \o QPaintEngine::DirtyCompositionMode \o compositionMode()
8139 \row \o QPaintEngine::DirtyFont \o font()
8140 \row \o QPaintEngine::DirtyTransform \o transform()
8141 \row \o QPaintEngine::DirtyClipEnabled \o isClipEnabled()
8142 \row \o QPaintEngine::DirtyPen \o pen()
8143 \row \o QPaintEngine::DirtyHints \o renderHints()
8146 The QPaintEngineState class also provide the painter() function
8147 which returns a pointer to the painter that is currently updating
8150 An instance of this class, representing the current state of the
8151 active paint engine, is passed as argument to the
8152 QPaintEngine::updateState() function. The only situation in which
8153 you will have to use this class directly is when implementing your
8161 \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
8163 Returns a combination of flags identifying the set of properties
8164 that need to be updated when updating the paint engine's state
8165 (i.e. during a call to the QPaintEngine::updateState() function).
8167 \sa QPaintEngine::updateState()
8172 Returns the pen in the current paint engine state.
8174 This variable should only be used when the state() returns a
8175 combination which includes the QPaintEngine::DirtyPen flag.
8177 \sa state(), QPaintEngine::updateState()
8180 QPen QPaintEngineState::pen() const
8182 return static_cast<const QPainterState *>(this)->pen;
8186 Returns the brush in the current paint engine state.
8188 This variable should only be used when the state() returns a
8189 combination which includes the QPaintEngine::DirtyBrush flag.
8191 \sa state(), QPaintEngine::updateState()
8194 QBrush QPaintEngineState::brush() const
8196 return static_cast<const QPainterState *>(this)->brush;
8200 Returns the brush origin in the current paint engine state.
8202 This variable should only be used when the state() returns a
8203 combination which includes the QPaintEngine::DirtyBrushOrigin flag.
8205 \sa state(), QPaintEngine::updateState()
8208 QPointF QPaintEngineState::brushOrigin() const
8210 return static_cast<const QPainterState *>(this)->brushOrigin;
8214 Returns the background brush in the current paint engine state.
8216 This variable should only be used when the state() returns a
8217 combination which includes the QPaintEngine::DirtyBackground flag.
8219 \sa state(), QPaintEngine::updateState()
8222 QBrush QPaintEngineState::backgroundBrush() const
8224 return static_cast<const QPainterState *>(this)->bgBrush;
8228 Returns the background mode in the current paint engine
8231 This variable should only be used when the state() returns a
8232 combination which includes the QPaintEngine::DirtyBackgroundMode flag.
8234 \sa state(), QPaintEngine::updateState()
8237 Qt::BGMode QPaintEngineState::backgroundMode() const
8239 return static_cast<const QPainterState *>(this)->bgMode;
8243 Returns the font in the current paint engine
8246 This variable should only be used when the state() returns a
8247 combination which includes the QPaintEngine::DirtyFont flag.
8249 \sa state(), QPaintEngine::updateState()
8252 QFont QPaintEngineState::font() const
8254 return static_cast<const QPainterState *>(this)->font;
8261 Returns the matrix in the current paint engine
8264 \note It is advisable to use transform() instead of this function to
8265 preserve the properties of perspective transformations.
8267 This variable should only be used when the state() returns a
8268 combination which includes the QPaintEngine::DirtyTransform flag.
8270 \sa state(), QPaintEngine::updateState()
8273 QMatrix QPaintEngineState::matrix() const
8275 const QPainterState *st = static_cast<const QPainterState *>(this);
8277 return st->matrix.toAffine();
8283 Returns the matrix in the current paint engine state.
8285 This variable should only be used when the state() returns a
8286 combination which includes the QPaintEngine::DirtyTransform flag.
8288 \sa state(), QPaintEngine::updateState()
8292 QTransform QPaintEngineState::transform() const
8294 const QPainterState *st = static_cast<const QPainterState *>(this);
8301 Returns the clip operation in the current paint engine
8304 This variable should only be used when the state() returns a
8305 combination which includes either the QPaintEngine::DirtyClipPath
8306 or the QPaintEngine::DirtyClipRegion flag.
8308 \sa state(), QPaintEngine::updateState()
8311 Qt::ClipOperation QPaintEngineState::clipOperation() const
8313 return static_cast<const QPainterState *>(this)->clipOperation;
8319 Returns whether the coordinate of the fill have been specified
8320 as bounded by the current rendering operation and have to be
8321 resolved (about the currently rendered primitive).
8323 bool QPaintEngineState::brushNeedsResolving() const
8325 const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
8326 return needsResolving(brush);
8333 Returns whether the coordinate of the stroke have been specified
8334 as bounded by the current rendering operation and have to be
8335 resolved (about the currently rendered primitive).
8337 bool QPaintEngineState::penNeedsResolving() const
8339 const QPen &pen = static_cast<const QPainterState *>(this)->pen;
8340 return needsResolving(pen.brush());
8344 Returns the clip region in the current paint engine state.
8346 This variable should only be used when the state() returns a
8347 combination which includes the QPaintEngine::DirtyClipRegion flag.
8349 \sa state(), QPaintEngine::updateState()
8352 QRegion QPaintEngineState::clipRegion() const
8354 return static_cast<const QPainterState *>(this)->clipRegion;
8358 Returns the clip path in the current paint engine state.
8360 This variable should only be used when the state() returns a
8361 combination which includes the QPaintEngine::DirtyClipPath flag.
8363 \sa state(), QPaintEngine::updateState()
8366 QPainterPath QPaintEngineState::clipPath() const
8368 return static_cast<const QPainterState *>(this)->clipPath;
8372 Returns whether clipping is enabled or not in the current paint
8375 This variable should only be used when the state() returns a
8376 combination which includes the QPaintEngine::DirtyClipEnabled
8379 \sa state(), QPaintEngine::updateState()
8382 bool QPaintEngineState::isClipEnabled() const
8384 return static_cast<const QPainterState *>(this)->clipEnabled;
8388 Returns the render hints in the current paint engine state.
8390 This variable should only be used when the state() returns a
8391 combination which includes the QPaintEngine::DirtyHints
8394 \sa state(), QPaintEngine::updateState()
8397 QPainter::RenderHints QPaintEngineState::renderHints() const
8399 return static_cast<const QPainterState *>(this)->renderHints;
8403 Returns the composition mode in the current paint engine state.
8405 This variable should only be used when the state() returns a
8406 combination which includes the QPaintEngine::DirtyCompositionMode
8409 \sa state(), QPaintEngine::updateState()
8412 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8414 return static_cast<const QPainterState *>(this)->composition_mode;
8419 Returns a pointer to the painter currently updating the paint
8423 QPainter *QPaintEngineState::painter() const
8425 return static_cast<const QPainterState *>(this)->painter;
8432 Returns the opacity in the current paint engine state.
8435 qreal QPaintEngineState::opacity() const
8437 return static_cast<const QPainterState *>(this)->opacity;
8443 Sets the world transformation matrix.
8444 If \a combine is true, the specified \a transform is combined with
8445 the current matrix; otherwise it replaces the current matrix.
8447 \sa transform() setWorldTransform()
8450 void QPainter::setTransform(const QTransform &transform, bool combine )
8452 setWorldTransform(transform, combine);
8456 Returns the world transformation matrix.
8458 \sa worldTransform()
8461 const QTransform & QPainter::transform() const
8463 return worldTransform();
8468 Returns the matrix that transforms from logical coordinates to
8469 device coordinates of the platform dependent paint device.
8471 This function is \e only needed when using platform painting
8472 commands on the platform dependent handle (Qt::HANDLE), and the
8473 platform does not do transformations nativly.
8475 The QPaintEngine::PaintEngineFeature enum can be queried to
8476 determine whether the platform performs the transformations or
8479 \sa worldTransform(), QPaintEngine::hasFeature(),
8482 const QTransform & QPainter::deviceTransform() const
8484 Q_D(const QPainter);
8486 qWarning("QPainter::deviceTransform: Painter not active");
8487 return d->fakeState()->transform;
8489 return d->state->matrix;
8494 Resets any transformations that were made using translate(),
8495 scale(), shear(), rotate(), setWorldTransform(), setViewport()
8498 \sa {Coordinate Transformations}
8501 void QPainter::resetTransform()
8504 #ifdef QT_DEBUG_DRAW
8505 if (qt_show_painter_debug_output)
8506 printf("QPainter::resetMatrix()\n");
8509 qWarning("QPainter::resetMatrix: Painter not active");
8513 d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins
8514 d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
8515 d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
8516 d->state->worldMatrix = QTransform();
8517 setMatrixEnabled(false);
8518 setViewTransformEnabled(false);
8520 d->extended->transformChanged();
8522 d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
8526 Sets the world transformation matrix.
8527 If \a combine is true, the specified \a matrix is combined with the current matrix;
8528 otherwise it replaces the current matrix.
8530 \sa transform(), setTransform()
8533 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
8538 qWarning("QPainter::setWorldTransform: Painter not active");
8543 d->state->worldMatrix = matrix * d->state->worldMatrix; // combines
8545 d->state->worldMatrix = matrix; // set new matrix
8547 d->state->WxF = true;
8552 Returns the world transformation matrix.
8555 const QTransform & QPainter::worldTransform() const
8557 Q_D(const QPainter);
8559 qWarning("QPainter::worldTransform: Painter not active");
8560 return d->fakeState()->transform;
8562 return d->state->worldMatrix;
8566 Returns the transformation matrix combining the current
8567 window/viewport and world transformation.
8569 \sa setWorldTransform(), setWindow(), setViewport()
8572 QTransform QPainter::combinedTransform() const
8574 Q_D(const QPainter);
8576 qWarning("QPainter::combinedTransform: Painter not active");
8577 return QTransform();
8579 return d->state->worldMatrix * d->viewTransform();
8585 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
8586 at multiple positions with different scale, rotation and opacity. \a
8587 fragments is an array of \a fragmentCount elements specifying the
8588 parameters used to draw each pixmap fragment. The \a hints
8589 parameter can be used to pass in drawing hints.
8591 This function is potentially faster than multiple calls to drawPixmap(),
8592 since the backend can optimize state changes.
8594 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
8597 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
8598 const QPixmap &pixmap, PixmapFragmentHints hints)
8602 if (!d->engine || pixmap.isNull())
8606 for (int i = 0; i < fragmentCount; ++i) {
8607 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8608 fragments[i].width, fragments[i].height);
8609 if (!(QRectF(pixmap.rect()).contains(sourceRect)))
8610 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
8614 if (d->engine->isExtended()) {
8615 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
8617 qreal oldOpacity = opacity();
8618 QTransform oldTransform = transform();
8620 for (int i = 0; i < fragmentCount; ++i) {
8621 QTransform transform = oldTransform;
8624 if (fragments[i].rotation == 0) {
8625 xOffset = fragments[i].x;
8626 yOffset = fragments[i].y;
8628 transform.translate(fragments[i].x, fragments[i].y);
8629 transform.rotate(fragments[i].rotation);
8631 setOpacity(oldOpacity * fragments[i].opacity);
8632 setTransform(transform);
8634 qreal w = fragments[i].scaleX * fragments[i].width;
8635 qreal h = fragments[i].scaleY * fragments[i].height;
8636 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8637 fragments[i].width, fragments[i].height);
8638 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
8641 setOpacity(oldOpacity);
8642 setTransform(oldTransform);
8648 \class QPainter::PixmapFragment
8650 \brief This class is used in conjunction with the
8651 QPainter::drawPixmapFragments() function to specify how a pixmap, or
8652 sub-rect of a pixmap, is drawn.
8654 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
8655 as a source rectangle within the pixmap passed into the
8656 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
8657 width and \a height are used to calculate the target rectangle that is
8658 drawn. \a x and \a y denotes the center of the target rectangle. The \a
8659 width and \a height in the target rectangle is scaled by the \a scaleX and
8660 \a scaleY values. The resulting target rectangle is then rotated \a
8661 rotation degrees around the \a x, \a y center point.
8663 \sa QPainter::drawPixmapFragments()
8669 This is a convenience function that returns a QPainter::PixmapFragment that is
8670 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
8671 rotation, \a opacity parameters.
8674 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
8675 qreal scaleX, qreal scaleY, qreal rotation,
8678 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
8679 sourceRect.height(), scaleX, scaleY, rotation, opacity};
8684 \variable QPainter::PixmapFragment::x
8685 \brief the x coordinate of center point in the target rectangle.
8689 \variable QPainter::PixmapFragment::y
8690 \brief the y coordinate of the center point in the target rectangle.
8694 \variable QPainter::PixmapFragment::sourceLeft
8695 \brief the left coordinate of the source rectangle.
8699 \variable QPainter::PixmapFragment::sourceTop
8700 \brief the top coordinate of the source rectangle.
8704 \variable QPainter::PixmapFragment::width
8706 \brief the width of the source rectangle and is used to calculate the width
8707 of the target rectangle.
8711 \variable QPainter::PixmapFragment::height
8713 \brief the height of the source rectangle and is used to calculate the
8714 height of the target rectangle.
8718 \variable QPainter::PixmapFragment::scaleX
8719 \brief the horizontal scale of the target rectangle.
8723 \variable QPainter::PixmapFragment::scaleY
8724 \brief the vertical scale of the target rectangle.
8728 \variable QPainter::PixmapFragment::rotation
8730 \brief the rotation of the target rectangle in degrees. The target
8731 rectangle is rotated after it has been scaled.
8735 \variable QPainter::PixmapFragment::opacity
8737 \brief the opacity of the target rectangle, where 0.0 is fully transparent
8738 and 1.0 is fully opaque.
8744 \enum QPainter::PixmapFragmentHint
8746 \value OpaqueHint Indicates that the pixmap fragments to be drawn are
8747 opaque. Opaque fragments are potentially faster to draw.
8749 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
8752 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
8754 p->draw_helper(path, operation);
8757 /*! \fn Display *QPaintDevice::x11Display() const
8758 Use QX11Info::display() instead.
8761 Display *display = widget->x11Display();
8763 Display *display = QX11Info::display();
8766 \sa QWidget::x11Info(), QX11Info::display()
8769 /*! \fn int QPaintDevice::x11Screen() const
8770 Use QX11Info::screen() instead.
8773 int screen = widget->x11Screen();
8775 int screen = widget->x11Info().screen();
8778 \sa QWidget::x11Info(), QPixmap::x11Info()
8781 /*! \fn void *QPaintDevice::x11Visual() const
8782 Use QX11Info::visual() instead.
8785 void *visual = widget->x11Visual();
8787 void *visual = widget->x11Info().visual();
8790 \sa QWidget::x11Info(), QPixmap::x11Info()
8793 /*! \fn int QPaintDevice::x11Depth() const
8794 Use QX11Info::depth() instead.
8797 int depth = widget->x11Depth();
8799 int depth = widget->x11Info().depth();
8802 \sa QWidget::x11Info(), QPixmap::x11Info()
8805 /*! \fn int QPaintDevice::x11Cells() const
8806 Use QX11Info::cells() instead.
8809 int cells = widget->x11Cells();
8811 int cells = widget->x11Info().cells();
8814 \sa QWidget::x11Info(), QPixmap::x11Info()
8817 /*! \fn Qt::HANDLE QPaintDevice::x11Colormap() const
8818 Use QX11Info::colormap() instead.
8821 unsigned long screen = widget->x11Colormap();
8823 unsigned long screen = widget->x11Info().colormap();
8826 \sa QWidget::x11Info(), QPixmap::x11Info()
8829 /*! \fn bool QPaintDevice::x11DefaultColormap() const
8830 Use QX11Info::defaultColormap() instead.
8833 bool isDefault = widget->x11DefaultColormap();
8835 bool isDefault = widget->x11Info().defaultColormap();
8838 \sa QWidget::x11Info(), QPixmap::x11Info()
8841 /*! \fn bool QPaintDevice::x11DefaultVisual() const
8842 Use QX11Info::defaultVisual() instead.
8845 bool isDefault = widget->x11DefaultVisual();
8847 bool isDefault = widget->x11Info().defaultVisual();
8850 \sa QWidget::x11Info(), QPixmap::x11Info()
8853 /*! \fn void *QPaintDevice::x11AppVisual(int screen)
8854 Use QX11Info::visual() instead.
8857 void *visual = QPaintDevice::x11AppVisual(screen);
8859 void *visual = qApp->x11Info(screen).visual();
8862 \sa QWidget::x11Info(), QPixmap::x11Info()
8865 /*! \fn Qt::HANDLE QPaintDevice::x11AppColormap(int screen)
8866 Use QX11Info::colormap() instead.
8869 unsigned long colormap = QPaintDevice::x11AppColormap(screen);
8871 unsigned long colormap = qApp->x11Info(screen).colormap();
8874 \sa QWidget::x11Info(), QPixmap::x11Info()
8877 /*! \fn Display *QPaintDevice::x11AppDisplay()
8878 Use QX11Info::display() instead.
8881 Display *display = QPaintDevice::x11AppDisplay();
8883 Display *display = qApp->x11Info().display();
8886 \sa QWidget::x11Info(), QPixmap::x11Info()
8889 /*! \fn int QPaintDevice::x11AppScreen()
8890 Use QX11Info::screen() instead.
8893 int screen = QPaintDevice::x11AppScreen();
8895 int screen = qApp->x11Info().screen();
8898 \sa QWidget::x11Info(), QPixmap::x11Info()
8901 /*! \fn int QPaintDevice::x11AppDepth(int screen)
8902 Use QX11Info::depth() instead.
8905 int depth = QPaintDevice::x11AppDepth(screen);
8907 int depth = qApp->x11Info(screen).depth();
8910 \sa QWidget::x11Info(), QPixmap::x11Info()
8913 /*! \fn int QPaintDevice::x11AppCells(int screen)
8914 Use QX11Info::cells() instead.
8917 int cells = QPaintDevice::x11AppCells(screen);
8919 int cells = qApp->x11Info(screen).cells();
8922 \sa QWidget::x11Info(), QPixmap::x11Info()
8925 /*! \fn Qt::HANDLE QPaintDevice::x11AppRootWindow(int screen)
8926 Use QX11Info::appRootWindow() instead.
8929 unsigned long window = QPaintDevice::x11AppRootWindow(screen);
8931 unsigned long window = qApp->x11Info(screen).appRootWindow();
8934 \sa QWidget::x11Info(), QPixmap::x11Info()
8937 /*! \fn bool QPaintDevice::x11AppDefaultColormap(int screen)
8938 Use QX11Info::defaultColormap() instead.
8941 bool isDefault = QPaintDevice::x11AppDefaultColormap(screen);
8943 bool isDefault = qApp->x11Info(screen).defaultColormap();
8946 \sa QWidget::x11Info(), QPixmap::x11Info()
8949 /*! \fn bool QPaintDevice::x11AppDefaultVisual(int screen)
8950 Use QX11Info::defaultVisual() instead.
8953 bool isDefault = QPaintDevice::x11AppDefaultVisual(screen);
8955 bool isDefault = qApp->x11Info(screen).defaultVisual();
8958 \sa QWidget::x11Info(), QPixmap::x11Info()
8961 /*! \fn void QPaintDevice::x11SetAppDpiX(int dpi, int screen)
8962 Use QX11Info::setAppDpiX() instead.
8965 /*! \fn void QPaintDevice::x11SetAppDpiY(int dpi, int screen)
8966 Use QX11Info::setAppDpiY() instead.
8969 /*! \fn int QPaintDevice::x11AppDpiX(int screen)
8970 Use QX11Info::appDpiX() instead.
8973 bool isDefault = QPaintDevice::x11AppDpiX(screen);
8975 bool isDefault = qApp->x11Info(screen).appDpiX();
8978 \sa QWidget::x11Info(), QPixmap::x11Info()
8981 /*! \fn int QPaintDevice::x11AppDpiY(int screen)
8982 Use QX11Info::appDpiY() instead.
8985 bool isDefault = QPaintDevice::x11AppDpiY(screen);
8987 bool isDefault = qApp->x11Info(screen).appDpiY();
8990 \sa QWidget::x11Info(), QPixmap::x11Info()
8993 /*! \fn HDC QPaintDevice::getDC() const
8997 /*! \fn void QPaintDevice::releaseDC(HDC) const
9001 /*! \fn QWSDisplay *QPaintDevice::qwsDisplay()