1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
50 #include "qpaintdevice.h"
51 #include "qpaintengine.h"
53 #include "qpainter_p.h"
54 #include "qpainterpath.h"
56 #include "qpixmapcache.h"
58 #include "qtextlayout.h"
60 #include "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);
153 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
156 case QInternal::Image:
157 case QInternal::Printer:
158 case QInternal::Picture:
159 // can be drawn onto these devices safely from any thread
166 if (QApplication::testAttribute(Qt::AA_X11InitThreads))
169 if (!extraCondition && QThread::currentThread() != qApp->thread()) {
170 qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
179 void QPainterPrivate::checkEmulation()
182 if (extended->flags() & QPaintEngineEx::DoNotEmulate)
185 bool doEmulation = false;
186 if (state->bgMode == Qt::OpaqueMode)
189 const QGradient *bg = state->brush.gradient();
190 if (bg && bg->coordinateMode() > QGradient::LogicalMode)
193 const QGradient *pg = qpen_brush(state->pen).gradient();
194 if (pg && pg->coordinateMode() > QGradient::LogicalMode)
198 if (extended != emulationEngine) {
199 if (!emulationEngine)
200 emulationEngine = new QEmulationPaintEngine(extended);
201 extended = emulationEngine;
202 extended->setState(state);
204 } else if (emulationEngine == extended) {
205 extended = emulationEngine->real_engine;
210 QPainterPrivate::~QPainterPrivate()
212 delete emulationEngine;
213 for (int i=0; i<states.size(); ++i)
221 QTransform QPainterPrivate::viewTransform() const
224 qreal scaleW = qreal(state->vw)/qreal(state->ww);
225 qreal scaleH = qreal(state->vh)/qreal(state->wh);
226 return QTransform(scaleW, 0, 0, scaleH,
227 state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
235 Returns true if using a shared painter; otherwise false.
237 bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
242 QPainter *sp = pdev->sharedPainter();
246 // Save the current state of the shared painter and assign
247 // the current d_ptr to the shared painter's d_ptr.
249 if (!sp->d_ptr->d_ptrs) {
250 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
251 // redirections within the same paintEvent(), which should be enough
252 // in 99% of all cases). E.g: A renders B which renders C which renders D.
253 sp->d_ptr->d_ptrs_size = 4;
254 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
255 Q_CHECK_PTR(sp->d_ptr->d_ptrs);
256 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
257 // However, to support corner cases we grow the array dynamically if needed.
258 sp->d_ptr->d_ptrs_size <<= 1;
259 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
260 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
262 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
264 q->d_ptr.reset(sp->d_ptr.data());
266 Q_ASSERT(q->d_ptr->state);
268 // Now initialize the painter with correct widget properties.
271 pdev->redirected(&offset);
272 offset += q->d_ptr->engine->coordinateOffset();
274 // Update system rect.
275 q->d_ptr->state->ww = q->d_ptr->state->vw = pdev->width();
276 q->d_ptr->state->wh = q->d_ptr->state->vh = pdev->height();
279 if (q->d_ptr->state->WxF) {
280 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix;
281 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
282 q->d_ptr->state->worldMatrix = QTransform();
283 q->d_ptr->state->WxF = false;
285 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
287 q->d_ptr->updateMatrix();
289 QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
290 if (enginePrivate->currentClipDevice == pdev) {
291 enginePrivate->systemStateChanged();
295 // Update system transform and clip.
296 enginePrivate->currentClipDevice = pdev;
297 enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
301 void QPainterPrivate::detachPainterPrivate(QPainter *q)
303 Q_ASSERT(refcount > 1);
306 QPainterPrivate *original = d_ptrs[--refcount - 1];
308 inDestructor = false;
310 original->inDestructor = true;
311 } else if (!original) {
312 original = new QPainterPrivate(q);
315 d_ptrs[refcount - 1] = 0;
318 q->d_ptr.reset(original);
320 if (emulationEngine) {
321 extended = emulationEngine->real_engine;
322 delete emulationEngine;
328 void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op)
331 if (qt_show_painter_debug_output) {
332 printf("QPainter::drawHelper\n");
336 if (originalPath.isEmpty())
339 QPaintEngine::PaintEngineFeatures gradientStretch =
340 QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
341 | QPaintEngine::ObjectBoundingModeGradients);
343 const bool mustEmulateObjectBoundingModeGradients = extended
344 || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients)
345 && !engine->hasFeature(QPaintEngine::PatternTransform));
347 if (!(state->emulationSpecifier & ~gradientStretch)
348 && !mustEmulateObjectBoundingModeGradients) {
349 drawStretchedGradient(originalPath, op);
351 } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {
352 drawOpaqueBackground(originalPath, op);
358 qreal strokeOffsetX = 0, strokeOffsetY = 0;
360 QPainterPath path = originalPath * state->matrix;
361 QRectF pathBounds = path.boundingRect();
363 bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
365 qreal penWidth = state->pen.widthF();
370 // In case of complex xform
371 if (state->matrix.type() > QTransform::TxScale) {
372 QPainterPathStroker stroker;
373 stroker.setWidth(penWidth);
374 stroker.setJoinStyle(state->pen.joinStyle());
375 stroker.setCapStyle(state->pen.capStyle());
376 QPainterPath stroke = stroker.createStroke(originalPath);
377 strokeBounds = (stroke * state->matrix).boundingRect();
379 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);
380 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);
386 if (!strokeBounds.isEmpty()) {
387 absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
389 absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
390 .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
393 if (q->hasClipping()) {
394 bool hasPerspectiveTransform = false;
395 for (int i = 0; i < state->clipInfo.size(); ++i) {
396 const QPainterClipInfo &info = state->clipInfo.at(i);
397 if (info.matrix.type() == QTransform::TxProject) {
398 hasPerspectiveTransform = true;
402 // avoid mapping QRegions with perspective transforms
403 if (!hasPerspectiveTransform) {
404 // The trick with txinv and invMatrix is done in order to
405 // avoid transforming the clip to logical coordinates, and
406 // then back to device coordinates. This is a problem with
407 // QRegion/QRect based clips, since they use integer
408 // coordinates and converting to/from logical coordinates will
410 bool old_txinv = txinv;
411 QTransform old_invMatrix = invMatrix;
413 invMatrix = QTransform();
414 QPainterPath clipPath = q->clipPath();
415 QRectF r = clipPath.boundingRect().intersected(absPathRect);
416 absPathRect = r.toAlignedRect();
418 invMatrix = old_invMatrix;
422 // qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
423 // devMinX, devMinY, device->width(), device->height());
424 // qDebug() << " - matrix" << state->matrix;
425 // qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
426 // qDebug() << " - path.bounds" << path.boundingRect();
428 if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
431 QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
436 p.d_ptr->helper_device = helper_device;
438 p.setOpacity(state->opacity);
439 p.translate(-absPathRect.x(), -absPathRect.y());
440 p.setTransform(state->matrix, true);
441 p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
442 p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
443 p.setBackground(state->bgBrush);
444 p.setBackgroundMode(state->bgMode);
445 p.setBrushOrigin(state->brushOrigin);
447 p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);
448 p.setRenderHint(QPainter::SmoothPixmapTransform,
449 state->renderHints & QPainter::SmoothPixmapTransform);
451 p.drawPath(originalPath);
454 static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0;
455 if (do_fallback_overlay) {
456 QImage block(8, 8, QImage::Format_ARGB32_Premultiplied);
458 pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
459 pt.drawLine(0, 0, 8, 8);
462 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
464 p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
471 state->matrix = QTransform();
473 extended->transformChanged();
475 state->dirtyFlags |= QPaintEngine::DirtyTransform;
478 engine->drawImage(absPathRect,
480 QRectF(0, 0, absPathRect.width(), absPathRect.height()),
481 Qt::OrderedDither | Qt::OrderedAlphaDither);
485 void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op)
489 q->setBackgroundMode(Qt::TransparentMode);
491 if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
492 q->fillPath(path, state->bgBrush.color());
493 q->fillPath(path, state->brush);
496 if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
497 q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
498 q->strokePath(path, state->pen);
501 q->setBackgroundMode(Qt::OpaqueMode);
504 static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
506 Q_ASSERT(brush.style() >= Qt::LinearGradientPattern
507 && brush.style() <= Qt::ConicalGradientPattern);
509 QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
510 boundingRect.x(), boundingRect.y());
512 QGradient g = *brush.gradient();
513 g.setCoordinateMode(QGradient::LogicalMode);
516 b.setTransform(gradientToUser * b.transform());
520 void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op)
524 const qreal sw = helper_device->width();
525 const qreal sh = helper_device->height();
527 bool changedPen = false;
528 bool changedBrush = false;
529 bool needsFill = false;
531 const QPen pen = state->pen;
532 const QBrush brush = state->brush;
534 const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
535 const QGradient::CoordinateMode brushMode = coordinateMode(brush);
539 // Draw the xformed fill if the brush is a stretch gradient.
540 if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
541 if (brushMode == QGradient::StretchToDeviceMode) {
542 q->setPen(Qt::NoPen);
543 changedPen = pen.style() != Qt::NoPen;
547 const qreal isw = 1.0 / sw;
548 const qreal ish = 1.0 / sh;
549 QTransform inv(isw, 0, 0, ish, 0, 0);
550 engine->drawPath(path * inv);
555 if (brushMode == QGradient::ObjectBoundingMode) {
556 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
557 boundingRect = path.boundingRect();
558 q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
564 if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
565 // Draw the xformed outline if the pen is a stretch gradient.
566 if (penMode == QGradient::StretchToDeviceMode) {
567 q->setPen(Qt::NoPen);
572 engine->drawPath(path);
576 q->setBrush(pen.brush());
580 QPainterPathStroker stroker;
581 stroker.setDashPattern(pen.style());
582 stroker.setWidth(pen.widthF());
583 stroker.setJoinStyle(pen.joinStyle());
584 stroker.setCapStyle(pen.capStyle());
585 stroker.setMiterLimit(pen.miterLimit());
586 QPainterPath stroke = stroker.createStroke(path);
588 const qreal isw = 1.0 / sw;
589 const qreal ish = 1.0 / sh;
590 QTransform inv(isw, 0, 0, ish, 0, 0);
591 engine->drawPath(stroke * inv);
594 if (!needsFill && brush.style() != Qt::NoBrush) {
595 q->setBrush(Qt::NoBrush);
599 if (penMode == QGradient::ObjectBoundingMode) {
600 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
602 // avoid computing the bounding rect twice
603 if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
604 boundingRect = path.boundingRect();
607 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect));
610 } else if (changedPen) {
616 engine->drawPath(path);
618 } else if (needsFill) {
619 if (pen.style() != Qt::NoPen) {
620 q->setPen(Qt::NoPen);
625 engine->drawPath(path);
635 void QPainterPrivate::updateMatrix()
637 state->matrix = state->WxF ? state->worldMatrix : QTransform();
639 state->matrix *= viewTransform();
641 txinv = false; // no inverted matrix
642 state->matrix *= state->redirectionMatrix;
644 extended->transformChanged();
646 state->dirtyFlags |= QPaintEngine::DirtyTransform;
648 // printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
649 // qDebug() << " --- using matrix" << state->matrix << redirection_offset;
653 void QPainterPrivate::updateInvMatrix()
655 Q_ASSERT(txinv == false);
656 txinv = true; // creating inverted matrix
657 invMatrix = state->matrix.inverted();
660 extern bool qt_isExtendedRadialGradient(const QBrush &brush);
662 void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
665 bool linearGradient = false;
666 bool radialGradient = false;
667 bool extendedRadialGradient = false;
668 bool conicalGradient = false;
669 bool patternBrush = false;
671 bool complexXform = false;
675 // Pen and brush properties (we have to check both if one changes because the
676 // one that's unchanged can still be in a state which requires emulation)
677 if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) {
678 // Check Brush stroke emulation
679 if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke))
680 s->emulationSpecifier |= QPaintEngine::BrushStroke;
682 s->emulationSpecifier &= ~QPaintEngine::BrushStroke;
686 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
687 Qt::BrushStyle brushStyle = qbrush_style(s->brush);
688 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
689 alpha = (penBrushStyle != Qt::NoBrush
690 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
691 && !penBrush.isOpaque())
692 || (brushStyle != Qt::NoBrush
693 && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
694 && !s->brush.isOpaque());
695 linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
696 (brushStyle == Qt::LinearGradientPattern));
697 radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
698 (brushStyle == Qt::RadialGradientPattern));
699 extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
700 conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
701 (brushStyle == Qt::ConicalGradientPattern));
702 patternBrush = (((penBrushStyle > Qt::SolidPattern
703 && penBrushStyle < Qt::LinearGradientPattern)
704 || penBrushStyle == Qt::TexturePattern) ||
705 ((brushStyle > Qt::SolidPattern
706 && brushStyle < Qt::LinearGradientPattern)
707 || brushStyle == Qt::TexturePattern));
709 bool penTextureAlpha = false;
710 if (penBrush.style() == Qt::TexturePattern)
711 penTextureAlpha = qHasPixmapTexture(penBrush)
712 ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
713 : penBrush.textureImage().hasAlphaChannel();
714 bool brushTextureAlpha = false;
715 if (s->brush.style() == Qt::TexturePattern) {
716 brushTextureAlpha = qHasPixmapTexture(s->brush)
717 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
718 : s->brush.textureImage().hasAlphaChannel();
720 if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
721 || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
722 && !engine->hasFeature(QPaintEngine::MaskedBrush))
723 s->emulationSpecifier |= QPaintEngine::MaskedBrush;
725 s->emulationSpecifier &= ~QPaintEngine::MaskedBrush;
728 if (s->state() & (QPaintEngine::DirtyHints
729 | QPaintEngine::DirtyOpacity
730 | QPaintEngine::DirtyBackgroundMode)) {
738 qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
740 " - linearGradient: %d\n"
741 " - radialGradient: %d\n"
742 " - conicalGradient: %d\n"
743 " - patternBrush: %d\n"
752 uint(s->renderHints),
757 if (s->state() & QPaintEngine::DirtyTransform) {
758 xform = !s->matrix.isIdentity();
759 complexXform = !s->matrix.isAffine();
760 } else if (s->matrix.type() >= QTransform::TxTranslate) {
762 complexXform = !s->matrix.isAffine();
765 const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone);
766 const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone);
768 const bool patternXform = patternBrush && (xform || brushXform || penXform);
770 // Check alphablending
771 if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend))
772 s->emulationSpecifier |= QPaintEngine::AlphaBlend;
774 s->emulationSpecifier &= ~QPaintEngine::AlphaBlend;
776 // Linear gradient emulation
777 if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill))
778 s->emulationSpecifier |= QPaintEngine::LinearGradientFill;
780 s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
782 // Radial gradient emulation
783 if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
784 s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
786 s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
788 // Conical gradient emulation
789 if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
790 s->emulationSpecifier |= QPaintEngine::ConicalGradientFill;
792 s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill;
795 if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
796 s->emulationSpecifier |= QPaintEngine::PatternBrush;
798 s->emulationSpecifier &= ~QPaintEngine::PatternBrush;
801 if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform))
802 s->emulationSpecifier |= QPaintEngine::PatternTransform;
804 s->emulationSpecifier &= ~QPaintEngine::PatternTransform;
807 if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform))
808 s->emulationSpecifier |= QPaintEngine::PrimitiveTransform;
810 s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform;
812 // Perspective XForms
813 if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform))
814 s->emulationSpecifier |= QPaintEngine::PerspectiveTransform;
816 s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform;
819 if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity))
820 s->emulationSpecifier |= QPaintEngine::ConstantOpacity;
822 s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity;
824 bool gradientStretch = false;
825 bool objectBoundingMode = false;
826 if (linearGradient || conicalGradient || radialGradient) {
827 QGradient::CoordinateMode brushMode = coordinateMode(s->brush);
828 QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush());
830 gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
831 gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
833 objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
834 objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
837 s->emulationSpecifier |= QGradient_StretchToDevice;
839 s->emulationSpecifier &= ~QGradient_StretchToDevice;
841 if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
842 s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients;
844 s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients;
846 // Opaque backgrounds...
847 if (s->bgMode == Qt::OpaqueMode &&
848 (is_pen_transparent(s->pen) || is_brush_transparent(s->brush)))
849 s->emulationSpecifier |= QPaintEngine_OpaqueBackground;
851 s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground;
854 //won't be correct either way because the device can already have
855 // something rendered to it in which case subsequent emulation
856 // on a fully transparent qimage and then blitting the results
857 // won't produce correct results
859 if (state->composition_mode > QPainter::CompositionMode_Xor &&
860 !engine->hasFeature(QPaintEngine::BlendModes))
861 s->emulationSpecifier |= QPaintEngine::BlendModes;
863 s->emulationSpecifier &= ~QPaintEngine::BlendModes;
867 void QPainterPrivate::updateStateImpl(QPainterState *newState)
869 // ### we might have to call QPainter::begin() here...
870 if (!engine->state) {
871 engine->state = newState;
872 engine->setDirty(QPaintEngine::AllDirty);
875 if (engine->state->painter() != newState->painter)
876 // ### this could break with clip regions vs paths.
877 engine->setDirty(QPaintEngine::AllDirty);
879 // Upon restore, revert all changes since last save
880 else if (engine->state != newState)
881 newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
883 // We need to store all changes made so that restore can deal with them
885 newState->changeFlags |= newState->dirtyFlags;
887 updateEmulationSpecifier(newState);
889 // Unset potential dirty background mode
890 newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode
891 | QPaintEngine::DirtyBackground);
893 engine->state = newState;
894 engine->updateState(*newState);
895 engine->clearDirty(QPaintEngine::AllDirty);
899 void QPainterPrivate::updateState(QPainterState *newState)
903 engine->state = newState;
905 } else if (newState->state() || engine->state!=newState) {
906 bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
907 && newState->pen.widthF() == 0;
908 if (setNonCosmeticPen) {
909 // Override the default pen's cosmetic state if the
910 // NonCosmeticDefaultPen render hint is used.
911 QPen oldPen = newState->pen;
912 newState->pen.setWidth(1);
913 newState->pen.setCosmetic(false);
914 newState->dirtyFlags |= QPaintEngine::DirtyPen;
916 updateStateImpl(newState);
918 // Restore the state pen back to its default to preserve visible
920 newState->pen = oldPen;
922 updateStateImpl(newState);
930 \brief The QPainter class performs low-level painting on widgets and
937 QPainter provides highly optimized functions to do most of the
938 drawing GUI programs require. It can draw everything from simple
939 lines to complex shapes like pies and chords. It can also draw
940 aligned text and pixmaps. Normally, it draws in a "natural"
941 coordinate system, but it can also do view and world
942 transformation. QPainter can operate on any object that inherits
943 the QPaintDevice class.
945 The common use of QPainter is inside a widget's paint event:
946 Construct and customize (e.g. set the pen or the brush) the
947 painter. Then draw. Remember to destroy the QPainter object after
948 drawing. For example:
950 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 0
952 The core functionality of QPainter is drawing, but the class also
953 provide several functions that allows you to customize QPainter's
954 settings and its rendering quality, and others that enable
955 clipping. In addition you can control how different shapes are
956 merged together by specifying the painter's composition mode.
958 The isActive() function indicates whether the painter is active. A
959 painter is activated by the begin() function and the constructor
960 that takes a QPaintDevice argument. The end() function, and the
961 destructor, deactivates it.
963 Together with the QPaintDevice and QPaintEngine classes, QPainter
964 form the basis for Qt's paint system. QPainter is the class used
965 to perform drawing operations. QPaintDevice represents a device
966 that can be painted on using a QPainter. QPaintEngine provides the
967 interface that the painter uses to draw onto different types of
968 devices. If the painter is active, device() returns the paint
969 device on which the painter paints, and paintEngine() returns the
970 paint engine that the painter is currently operating on. For more
971 information, see the \l {Paint System}.
973 Sometimes it is desirable to make someone else paint on an unusual
974 QPaintDevice. QPainter supports a static function to do this,
977 \warning When the paintdevice is a widget, QPainter can only be
978 used inside a paintEvent() function or in a function called by
979 paintEvent(); that is unless the Qt::WA_PaintOutsidePaintEvent
980 widget attribute is set. On Mac OS X and Windows, you can only
981 paint in a paintEvent() function regardless of this attribute's
988 There are several settings that you can customize to make QPainter
989 draw according to your preferences:
993 \o font() is the font used for drawing text. If the painter
994 isActive(), you can retrieve information about the currently set
995 font, and its metrics, using the fontInfo() and fontMetrics()
996 functions respectively.
998 \o brush() defines the color or pattern that is used for filling
1001 \o pen() defines the color or stipple that is used for drawing
1002 lines or boundaries.
1004 \o backgroundMode() defines whether there is a background() or
1005 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
1007 \o background() only applies when backgroundMode() is \l
1008 Qt::OpaqueMode and pen() is a stipple. In that case, it
1009 describes the color of the background pixels in the stipple.
1011 \o brushOrigin() defines the origin of the tiled brushes, normally
1012 the origin of widget's background.
1014 \o viewport(), window(), worldTransform() make up the painter's coordinate
1015 transformation system. For more information, see the \l
1016 {Coordinate Transformations} section and the \l {Coordinate
1017 System} documentation.
1019 \o hasClipping() tells whether the painter clips at all. (The paint
1020 device clips, too.) If the painter clips, it clips to clipRegion().
1022 \o layoutDirection() defines the layout direction used by the
1023 painter when drawing text.
1025 \o worldMatrixEnabled() tells whether world transformation is enabled.
1027 \o viewTransformEnabled() tells whether view transformation is
1032 Note that some of these settings mirror settings in some paint
1033 devices, e.g. QWidget::font(). The QPainter::begin() function (or
1034 equivalently the QPainter constructor) copies these attributes
1035 from the paint device.
1037 You can at any time save the QPainter's state by calling the
1038 save() function which saves all the available settings on an
1039 internal stack. The restore() function pops them back.
1043 QPainter provides functions to draw most primitives: drawPoint(),
1044 drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1045 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1046 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
1047 convenience functions, drawRects() and drawLines(), draw the given
1048 number of rectangles or lines in the given array of \l
1049 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1052 The QPainter class also provides the fillRect() function which
1053 fills the given QRect, with the given QBrush, and the eraseRect()
1054 function that erases the area inside the given rectangle.
1056 All of these functions have both integer and floating point
1061 \o \inlineimage qpainter-basicdrawing.png
1063 \bold {Basic Drawing Example}
1065 The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1066 display basic graphics primitives in a variety of styles using the
1071 If you need to draw a complex shape, especially if you need to do
1072 so repeatedly, consider creating a QPainterPath and drawing it
1078 \bold {Painter Paths example}
1080 The QPainterPath class provides a container for painting
1081 operations, enabling graphical shapes to be constructed and
1084 The \l {painting/painterpaths}{Painter Paths} example shows how
1085 painter paths can be used to build complex shapes for rendering.
1087 \o \inlineimage qpainter-painterpaths.png
1090 QPainter also provides the fillPath() function which fills the
1091 given QPainterPath with the given QBrush, and the strokePath()
1092 function that draws the outline of the given path (i.e. strokes
1095 See also the \l {demos/deform}{Vector Deformation} demo which
1096 shows how to use advanced vector techniques to draw text using a
1097 QPainterPath, the \l {demos/gradients}{Gradients} demo which shows
1098 the different types of gradients that are available in Qt, and the \l
1099 {demos/pathstroke}{Path Stroking} demo which shows Qt's built-in
1100 dash patterns and shows how custom patterns can be used to extend
1101 the range of available patterns.
1105 \o \l {demos/deform}{Vector Deformation}
1106 \o \l {demos/gradients}{Gradients}
1107 \o \l {demos/pathstroke}{Path Stroking}
1109 \o \inlineimage qpainter-vectordeformation.png
1110 \o \inlineimage qpainter-gradients.png
1111 \o \inlineimage qpainter-pathstroking.png
1115 There are functions to draw pixmaps/images, namely drawPixmap(),
1116 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1117 produce the same result, except that drawPixmap() is faster
1118 on-screen while drawImage() may be faster on a QPrinter or other
1121 Text drawing is done using drawText(). When you need
1122 fine-grained positioning, boundingRect() tells you where a given
1123 drawText() command will draw.
1125 There is a drawPicture() function that draws the contents of an
1126 entire QPicture. The drawPicture() function is the only function
1127 that disregards all the painter's settings as QPicture has its own
1130 \section1 Rendering Quality
1132 To get the optimal rendering result using QPainter, you should use
1133 the platform independent QImage as paint device; i.e. using QImage
1134 will ensure that the result has an identical pixel representation
1137 The QPainter class also provides a means of controlling the
1138 rendering quality through its RenderHint enum and the support for
1139 floating point precision: All the functions for drawing primitives
1140 has a floating point version. These are often used in combination
1141 with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1145 \o \inlineimage qpainter-concentriccircles.png
1147 \bold {Concentric Circles Example}
1149 The \l {painting/concentriccircles}{Concentric Circles} example
1150 shows the improved rendering quality that can be obtained using
1151 floating point precision and anti-aliasing when drawing custom
1154 The application's main window displays several widgets which are
1155 drawn using the various combinations of precision and
1160 The RenderHint enum specifies flags to QPainter that may or may
1161 not be respected by any given engine. \l
1162 {RenderHint}{QPainter::Antialiasing} indicates that the engine
1163 should antialias edges of primitives if possible, \l
1164 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1165 should antialias text if possible, and the \l
1166 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1167 engine should use a smooth pixmap transformation algorithm.
1168 \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
1169 indicating that the engine should use fragment programs and offscreen
1170 rendering for antialiasing.
1172 The renderHints() function returns a flag that specifies the
1173 rendering hints that are set for this painter. Use the
1174 setRenderHint() function to set or clear the currently set
1177 \section1 Coordinate Transformations
1179 Normally, the QPainter operates on the device's own coordinate
1180 system (usually pixels), but QPainter has good support for
1181 coordinate transformations.
1185 \o nop \o rotate() \o scale() \o translate()
1187 \o \inlineimage qpainter-clock.png
1188 \o \inlineimage qpainter-rotation.png
1189 \o \inlineimage qpainter-scale.png
1190 \o \inlineimage qpainter-translation.png
1193 The most commonly used transformations are scaling, rotation,
1194 translation and shearing. Use the scale() function to scale the
1195 coordinate system by a given offset, the rotate() function to
1196 rotate it clockwise and translate() to translate it (i.e. adding a
1197 given offset to the points). You can also twist the coordinate
1198 system around the origin using the shear() function. See the \l
1199 {demos/affine}{Affine Transformations} demo for a visualization of
1200 a sheared coordinate system.
1202 See also the \l {painting/transformations}{Transformations}
1203 example which shows how transformations influence the way that
1204 QPainter renders graphics primitives. In particular it shows how
1205 the order of transformations affects the result.
1210 \bold {Affine Transformations Demo}
1212 The \l {demos/affine}{Affine Transformations} demo show Qt's
1213 ability to perform affine transformations on painting
1214 operations. The demo also allows the user to experiment with the
1215 transformation operations and see the results immediately.
1217 \o \inlineimage qpainter-affinetransformations.png
1220 All the tranformation operations operate on the transformation
1221 worldTransform(). A matrix transforms a point in the plane to another
1222 point. For more information about the transformation matrix, see
1223 the \l {Coordinate System} and QTransform documentation.
1225 The setWorldTransform() function can replace or add to the currently
1226 set worldTransform(). The resetTransform() function resets any
1227 transformations that were made using translate(), scale(),
1228 shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1229 functions. The deviceTransform() returns the matrix that transforms
1230 from logical coordinates to device coordinates of the platform
1231 dependent paint device. The latter function is only needed when
1232 using platform painting commands on the platform dependent handle,
1233 and the platform does not do transformations nativly.
1235 When drawing with QPainter, we specify points using logical
1236 coordinates which then are converted into the physical coordinates
1237 of the paint device. The mapping of the logical coordinates to the
1238 physical coordinates are handled by QPainter's combinedTransform(), a
1239 combination of viewport() and window() and worldTransform(). The
1240 viewport() represents the physical coordinates specifying an
1241 arbitrary rectangle, the window() describes the same rectangle in
1242 logical coordinates, and the worldTransform() is identical with the
1243 transformation matrix.
1245 See also \l {Coordinate System}
1249 QPainter can clip any drawing operation to a rectangle, a region,
1250 or a vector path. The current clip is available using the
1251 functions clipRegion() and clipPath(). Whether paths or regions are
1252 preferred (faster) depends on the underlying paintEngine(). For
1253 example, the QImage paint engine prefers paths while the X11 paint
1254 engine prefers regions. Setting a clip is done in the painters
1255 logical coordinates.
1257 After QPainter's clipping, the paint device may also clip. For
1258 example, most widgets clip away the pixels used by child widgets,
1259 and most printers clip away an area near the edges of the paper.
1260 This additional clipping is not reflected by the return value of
1261 clipRegion() or hasClipping().
1263 \section1 Composition Modes
1264 \target Composition Modes
1266 QPainter provides the CompositionMode enum which defines the
1267 Porter-Duff rules for digital image compositing; it describes a
1268 model for combining the pixels in one image, the source, with the
1269 pixels in another image, the destination.
1271 The two most common forms of composition are \l
1272 {QPainter::CompositionMode}{Source} and \l
1273 {QPainter::CompositionMode}{SourceOver}. \l
1274 {QPainter::CompositionMode}{Source} is used to draw opaque objects
1275 onto a paint device. In this mode, each pixel in the source
1276 replaces the corresponding pixel in the destination. In \l
1277 {QPainter::CompositionMode}{SourceOver} composition mode, the
1278 source object is transparent and is drawn on top of the
1281 Note that composition transformation operates pixelwise. For that
1282 reason, there is a difference between using the graphic primitive
1283 itself and its bounding rectangle: The bounding rect contains
1284 pixels with alpha == 0 (i.e the pixels surrounding the
1285 primitive). These pixels will overwrite the other image's pixels,
1286 affectively clearing those, while the primitive only overwrites
1291 \o \inlineimage qpainter-compositiondemo.png
1294 \bold {Composition Modes Demo}
1296 The \l {demos/composition}{Composition Modes} demo, available in
1297 Qt's demo directory, allows you to experiment with the various
1298 composition modes and see the results immediately.
1302 \section1 Limitations
1305 If you are using coordinates with Qt's raster-based paint engine, it is
1306 important to note that, while coordinates greater than +/- 2\sup 15 can
1307 be used, any painting performed with coordinates outside this range is not
1308 guaranteed to be shown; the drawing may be clipped. This is due to the
1309 use of \c{short int} in the implementation.
1311 The outlines generated by Qt's stroker are only an approximation when dealing
1312 with curved shapes. It is in most cases impossible to represent the outline of
1313 a bezier curve segment using another bezier curve segment, and so Qt approximates
1314 the curve outlines by using several smaller curves. For performance reasons there
1315 is a limit to how many curves Qt uses for these outlines, and thus when using
1316 large pen widths or scales the outline error increases. To generate outlines with
1317 smaller errors it is possible to use the QPainterPathStroker class, which has the
1318 setCurveThreshold member function which let's the user specify the error tolerance.
1319 Another workaround is to convert the paths to polygons first and then draw the
1322 \section1 Performance
1324 QPainter is a rich framework that allows developers to do a great
1325 variety of graphical operations, such as gradients, composition
1326 modes and vector graphics. And QPainter can do this across a
1327 variety of different hardware and software stacks. Naturally the
1328 underlying combination of hardware and software has some
1329 implications for performance, and ensuring that every single
1330 operation is fast in combination with all the various combinations
1331 of composition modes, brushes, clipping, transformation, etc, is
1332 close to an impossible task because of the number of
1333 permutations. As a compromise we have selected a subset of the
1334 QPainter API and backends, where performance is guaranteed to be as
1335 good as we can sensibly get it for the given combination of
1336 hardware and software.
1338 The backends we focus on as high-performance engines are:
1342 \o Raster - This backend implements all rendering in pure software
1343 and is always used to render into QImages. For optimal performance
1344 only use the format types QImage::Format_ARGB32_Premultiplied,
1345 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1346 including QImage::Format_ARGB32, has significantly worse
1347 performance. This engine is used by default for QWidget and QPixmap.
1349 \o OpenGL 2.0 (ES) - This backend is the primary backend for
1350 hardware accelerated graphics. It can be run on desktop machines
1351 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1352 specification. This includes most graphics chips produced in the
1353 last couple of years. The engine can be enabled by using QPainter
1354 onto a QGLWidget or by passing \c {-graphicssystem opengl} on the
1355 command line when the underlying system supports it.
1357 \o OpenVG - This backend implements the Khronos standard for 2D
1358 and Vector Graphics. It is primarily for embedded devices with
1359 hardware support for OpenVG. The engine can be enabled by
1360 passing \c {-graphicssystem openvg} on the command line when
1361 the underlying system supports it.
1365 These operations are:
1369 \o Simple transformations, meaning translation and scaling, pluss
1370 0, 90, 180, 270 degree rotations.
1372 \o \c drawPixmap() in combination with simple transformations and
1373 opacity with non-smooth transformation mode
1374 (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1376 \o Rectangle fills with solid color, two-color linear gradients
1377 and simple transforms.
1379 \o Rectangular clipping with simple transformations and intersect
1382 \o Composition Modes \c QPainter::CompositionMode_Source and
1383 QPainter::CompositionMode_SourceOver
1385 \o Rounded rectangle filling using solid color and two-color
1386 linear gradients fills.
1388 \o 3x3 patched pixmaps, via qDrawBorderPixmap.
1392 This list gives an indication of which features to safely use in
1393 an application where performance is critical. For certain setups,
1394 other operations may be fast too, but before making extensive use
1395 of them, it is recommended to benchmark and verify them on the
1396 system where the software will run in the end. There are also
1397 cases where expensive operations are ok to use, for instance when
1398 the result is cached in a QPixmap.
1400 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
1401 {Drawing Utility Functions}
1405 \enum QPainter::RenderHint
1407 Renderhints are used to specify flags to QPainter that may or
1408 may not be respected by any given engine.
1410 \value Antialiasing Indicates that the engine should antialias
1411 edges of primitives if possible.
1413 \value TextAntialiasing Indicates that the engine should antialias
1414 text if possible. To forcibly disable antialiasing for text, do not
1415 use this hint. Instead, set QFont::NoAntialias on your font's style
1418 \value SmoothPixmapTransform Indicates that the engine should use
1419 a smooth pixmap transformation algorithm (such as bilinear) rather
1420 than nearest neighbor.
1422 \value HighQualityAntialiasing An OpenGL-specific rendering hint
1423 indicating that the engine should use fragment programs and offscreen
1424 rendering for antialiasing.
1426 \value NonCosmeticDefaultPen The engine should interpret pens with a width
1427 of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
1428 pen with a width of 1.
1430 \sa renderHints(), setRenderHint(), {QPainter#Rendering
1431 Quality}{Rendering Quality}, {Concentric Circles Example}
1436 Constructs a painter.
1441 QPainter::QPainter()
1442 : d_ptr(new QPainterPrivate(this))
1447 \fn QPainter::QPainter(QPaintDevice *device)
1449 Constructs a painter that begins painting the paint \a device
1452 This constructor is convenient for short-lived painters, e.g. in a
1453 QWidget::paintEvent() and should be used only once. The
1454 constructor calls begin() for you and the QPainter destructor
1455 automatically calls end().
1457 Here's an example using begin() and end():
1458 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 1
1460 The same example using this constructor:
1461 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 2
1463 Since the constructor cannot provide feedback when the initialization
1464 of the painter failed you should rather use begin() and end() to paint
1465 on external devices, e.g. printers.
1470 QPainter::QPainter(QPaintDevice *pd)
1474 if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1475 d_ptr.reset(new QPainterPrivate(this));
1482 Destroys the painter.
1484 QPainter::~QPainter()
1486 d_ptr->inDestructor = true;
1490 else if (d_ptr->refcount > 1)
1491 d_ptr->detachPainterPrivate(this);
1493 // don't throw anything in the destructor.
1496 // Make sure we haven't messed things up.
1497 Q_ASSERT(d_ptr->inDestructor);
1498 d_ptr->inDestructor = false;
1499 Q_ASSERT(d_ptr->refcount == 1);
1501 free(d_ptr->d_ptrs);
1506 Returns the paint device on which this painter is currently
1507 painting, or 0 if the painter is not active.
1512 QPaintDevice *QPainter::device() const
1514 Q_D(const QPainter);
1515 if (isActive() && d->engine->d_func()->currentClipDevice)
1516 return d->engine->d_func()->currentClipDevice;
1517 return d->original_device;
1521 Returns true if begin() has been called and end() has not yet been
1522 called; otherwise returns false.
1524 \sa begin(), QPaintDevice::paintingActive()
1527 bool QPainter::isActive() const
1529 Q_D(const QPainter);
1534 Initializes the painters pen, background and font to the same as
1535 the given \a paint device.
1539 \sa begin(), {QPainter#Settings}{Settings}
1541 void QPainter::initFrom(const QPaintDevice *device)
1543 Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0");
1546 qWarning("QPainter::initFrom: Painter not active, aborted");
1553 d->extended->penChanged();
1554 } else if (d->engine) {
1555 d->engine->setDirty(QPaintEngine::DirtyPen);
1556 d->engine->setDirty(QPaintEngine::DirtyBrush);
1557 d->engine->setDirty(QPaintEngine::DirtyFont);
1563 Saves the current painter state (pushes the state onto a stack). A
1564 save() must be followed by a corresponding restore(); the end()
1565 function unwinds the stack.
1570 void QPainter::save()
1572 #ifdef QT_DEBUG_DRAW
1573 if (qt_show_painter_debug_output)
1574 printf("QPainter::save()\n");
1578 qWarning("QPainter::save: Painter not active");
1583 d->state = d->extended->createState(d->states.back());
1584 d->extended->setState(d->state);
1586 d->updateState(d->state);
1587 d->state = new QPainterState(d->states.back());
1588 d->engine->state = d->state;
1590 d->states.push_back(d->state);
1594 Restores the current painter state (pops a saved state off the
1600 void QPainter::restore()
1602 #ifdef QT_DEBUG_DRAW
1603 if (qt_show_painter_debug_output)
1604 printf("QPainter::restore()\n");
1607 if (d->states.size()<=1) {
1608 qWarning("QPainter::restore: Unbalanced save/restore");
1610 } else if (!d->engine) {
1611 qWarning("QPainter::restore: Painter not active");
1615 QPainterState *tmp = d->state;
1616 d->states.pop_back();
1617 d->state = d->states.back();
1621 d->checkEmulation();
1622 d->extended->setState(d->state);
1627 // trigger clip update if the clip path/region has changed since
1629 if (!d->state->clipInfo.isEmpty()
1630 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1631 // reuse the tmp state to avoid any extra allocs...
1632 tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1633 tmp->clipOperation = Qt::NoClip;
1634 tmp->clipPath = QPainterPath();
1635 d->engine->updateState(*tmp);
1636 // replay the list of clip states,
1637 for (int i=0; i<d->state->clipInfo.size(); ++i) {
1638 const QPainterClipInfo &info = d->state->clipInfo.at(i);
1639 tmp->matrix = info.matrix;
1640 tmp->matrix *= d->state->redirectionMatrix;
1641 tmp->clipOperation = info.operation;
1642 if (info.clipType == QPainterClipInfo::RectClip) {
1643 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1644 tmp->clipRegion = info.rect;
1645 } else if (info.clipType == QPainterClipInfo::RegionClip) {
1646 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1647 tmp->clipRegion = info.region;
1648 } else { // clipType == QPainterClipInfo::PathClip
1649 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1650 tmp->clipPath = info.path;
1652 d->engine->updateState(*tmp);
1656 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1657 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1658 tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1659 tmp->changeFlags |= QPaintEngine::DirtyTransform;
1662 d->updateState(d->state);
1669 \fn bool QPainter::begin(QPaintDevice *device)
1671 Begins painting the paint \a device and returns true if
1672 successful; otherwise returns false.
1674 Notice that all painter settings (setPen(), setBrush() etc.) are reset
1675 to default values when begin() is called.
1677 The errors that can occur are serious problems, such as these:
1679 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 3
1681 Note that most of the time, you can use one of the constructors
1682 instead of begin(), and that end() is automatically done at
1685 \warning A paint device can only be painted by one painter at a
1688 \warning Painting on a QImage with the format
1689 QImage::Format_Indexed8 is not supported.
1691 \sa end(), QPainter()
1694 static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1703 bool QPainter::begin(QPaintDevice *pd)
1707 if (pd->painters > 0) {
1708 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1712 if (d_ptr->engine) {
1713 qWarning("QPainter::begin: Painter already active");
1717 if (QPainterPrivate::attachPainterPrivate(this, pd))
1722 d->helper_device = pd;
1723 d->original_device = pd;
1725 QPoint redirectionOffset;
1726 QPaintDevice *rpd = pd->redirected(&redirectionOffset);
1730 #ifdef QT_DEBUG_DRAW
1731 if (qt_show_painter_debug_output)
1732 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1735 if (pd->devType() == QInternal::Pixmap)
1736 static_cast<QPixmap *>(pd)->detach();
1737 else if (pd->devType() == QInternal::Image)
1738 static_cast<QImage *>(pd)->detach();
1740 d->engine = pd->paintEngine();
1743 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1749 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1750 if (d->emulationEngine)
1751 d->emulationEngine->real_engine = d->extended;
1753 // Setup new state...
1754 Q_ASSERT(!d->state);
1755 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1756 d->state->painter = this;
1757 d->states.push_back(d->state);
1759 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1760 d->state->brushOrigin = QPointF();
1762 // Slip a painter state into the engine before we do any other operations
1764 d->extended->setState(d->state);
1766 d->engine->state = d->state;
1768 switch (pd->devType()) {
1770 // is this needed any more??
1771 case QInternal::Widget:
1773 const QWidget *widget = static_cast<const QWidget *>(pd);
1776 const bool paintOutsidePaintEvent = widget->testAttribute(Qt::WA_PaintOutsidePaintEvent);
1777 const bool inPaintEvent = widget->testAttribute(Qt::WA_WState_InPaintEvent);
1779 // Adjust offset for alien widgets painting outside the paint event.
1780 if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
1781 && widget->testAttribute(Qt::WA_WState_Created)) {
1782 const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
1783 d->state->redirectionMatrix.translate(offset.x(), offset.y());
1788 case QInternal::Pixmap:
1790 QPixmap *pm = static_cast<QPixmap *>(pd);
1793 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1794 qt_cleanup_painter_state(d);
1798 if (pm->depth() == 1) {
1799 d->state->pen = QPen(Qt::color1);
1800 d->state->brush = QBrush(Qt::color0);
1804 case QInternal::Image:
1806 QImage *img = static_cast<QImage *>(pd);
1808 if (img->isNull()) {
1809 qWarning("QPainter::begin: Cannot paint on a null image");
1810 qt_cleanup_painter_state(d);
1812 } else if (img->format() == QImage::Format_Indexed8) {
1813 // Painting on indexed8 images is not supported.
1814 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1815 qt_cleanup_painter_state(d);
1818 if (img->depth() == 1) {
1819 d->state->pen = QPen(Qt::color1);
1820 d->state->brush = QBrush(Qt::color0);
1827 if (d->state->ww == 0) // For compat with 3.x painter defaults
1828 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1830 d->engine->setPaintDevice(pd);
1832 bool begun = d->engine->begin(pd);
1834 qWarning("QPainter::begin(): Returned false");
1835 if (d->engine->isActive()) {
1838 qt_cleanup_painter_state(d);
1842 d->engine->setActive(begun);
1845 // Copy painter properties from original paint device,
1846 // required for QPixmap::grabWidget()
1847 if (d->original_device->devType() == QInternal::Widget) {
1848 initFrom(d->original_device);
1850 d->state->layoutDirection = Qt::LayoutDirectionAuto;
1851 // make sure we have a font compatible with the paintdevice
1852 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1855 QRect systemRect = d->engine->systemRect();
1856 if (!systemRect.isEmpty()) {
1857 d->state->ww = d->state->vw = systemRect.width();
1858 d->state->wh = d->state->vh = systemRect.height();
1860 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1861 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1864 const QPoint coordinateOffset = d->engine->coordinateOffset();
1865 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1867 Q_ASSERT(d->engine->isActive());
1869 if (!d->state->redirectionMatrix.isIdentity())
1872 Q_ASSERT(d->engine->isActive());
1873 d->state->renderHints = QPainter::TextAntialiasing;
1874 ++d->device->painters;
1876 d->state->emulationSpecifier = 0;
1882 Ends painting. Any resources used while painting are released. You
1883 don't normally need to call this since it is called by the
1886 Returns true if the painter is no longer active; otherwise returns false.
1888 \sa begin(), isActive()
1891 bool QPainter::end()
1893 #ifdef QT_DEBUG_DRAW
1894 if (qt_show_painter_debug_output)
1895 printf("QPainter::end()\n");
1900 qWarning("QPainter::end: Painter not active, aborted");
1901 qt_cleanup_painter_state(d);
1905 if (d->refcount > 1) {
1906 d->detachPainterPrivate(this);
1912 if (d->engine->isActive()) {
1913 ended = d->engine->end();
1916 --d->device->painters;
1917 if (d->device->painters == 0) {
1918 d->engine->setPaintDevice(0);
1919 d->engine->setActive(false);
1923 if (d->states.size() > 1) {
1924 qWarning("QPainter::end: Painter ended with %d saved states",
1928 if (d->engine->autoDestruct()) {
1932 if (d->emulationEngine) {
1933 delete d->emulationEngine;
1934 d->emulationEngine = 0;
1941 qt_cleanup_painter_state(d);
1948 Returns the paint engine that the painter is currently operating
1949 on if the painter is active; otherwise 0.
1953 QPaintEngine *QPainter::paintEngine() const
1955 Q_D(const QPainter);
1962 Flushes the painting pipeline and prepares for the user issuing commands
1963 directly to the underlying graphics context. Must be followed by a call to
1964 endNativePainting().
1966 Note that only the states the underlying paint engine changes will be reset
1967 to their respective default states. The states we reset may change from
1968 release to release. The following states are currently reset in the OpenGL
1972 \i blending is disabled
1973 \i the depth, stencil and scissor tests are disabled
1974 \i the active texture unit is reset to 0
1975 \i the depth mask, depth function and the clear depth are reset to their
1977 \i the stencil mask, stencil operation and stencil function are reset to
1978 their default values
1979 \i the current color is reset to solid white
1982 If, for example, the OpenGL polygon mode is changed by the user inside a
1983 beginNativePaint()/endNativePainting() block, it will not be reset to the
1984 default state by endNativePainting(). Here is an example that shows
1985 intermixing of painter commands and raw OpenGL commands:
1987 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
1989 \sa endNativePainting()
1991 void QPainter::beginNativePainting()
1995 qWarning("QPainter::beginNativePainting: Painter not active");
2000 d->extended->beginNativePainting();
2006 Restores the painter after manually issuing native painting commands. Lets
2007 the painter restore any native state that it relies on before calling any
2008 other painter commands.
2010 \sa beginNativePainting()
2012 void QPainter::endNativePainting()
2014 Q_D(const QPainter);
2016 qWarning("QPainter::beginNativePainting: Painter not active");
2021 d->extended->endNativePainting();
2023 d->engine->syncState();
2027 Returns the font metrics for the painter if the painter is
2028 active. Otherwise, the return value is undefined.
2030 \sa font(), isActive(), {QPainter#Settings}{Settings}
2033 QFontMetrics QPainter::fontMetrics() const
2035 Q_D(const QPainter);
2037 qWarning("QPainter::fontMetrics: Painter not active");
2038 return QFontMetrics(QFont());
2040 return QFontMetrics(d->state->font);
2045 Returns the font info for the painter if the painter is
2046 active. Otherwise, the return value is undefined.
2048 \sa font(), isActive(), {QPainter#Settings}{Settings}
2051 QFontInfo QPainter::fontInfo() const
2053 Q_D(const QPainter);
2055 qWarning("QPainter::fontInfo: Painter not active");
2056 return QFontInfo(QFont());
2058 return QFontInfo(d->state->font);
2064 Returns the opacity of the painter. The default value is
2068 qreal QPainter::opacity() const
2070 Q_D(const QPainter);
2072 qWarning("QPainter::opacity: Painter not active");
2075 return d->state->opacity;
2081 Sets the opacity of the painter to \a opacity. The value should
2082 be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2083 1.0 is fully opaque.
2085 Opacity set on the painter will apply to all drawing operations
2089 void QPainter::setOpacity(qreal opacity)
2094 qWarning("QPainter::setOpacity: Painter not active");
2098 opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2100 if (opacity == d->state->opacity)
2103 d->state->opacity = opacity;
2106 d->extended->opacityChanged();
2108 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2113 Returns the currently set brush origin.
2115 \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2118 QPoint QPainter::brushOrigin() const
2120 Q_D(const QPainter);
2122 qWarning("QPainter::brushOrigin: Painter not active");
2125 return QPointF(d->state->brushOrigin).toPoint();
2129 \fn void QPainter::setBrushOrigin(const QPointF &position)
2131 Sets the brush origin to \a position.
2133 The brush origin specifies the (0, 0) coordinate of the painter's
2136 Note that while the brushOrigin() was necessary to adopt the
2137 parent's background for a widget in Qt 3, this is no longer the
2138 case since the Qt 4 painter doesn't paint the background unless
2139 you explicitly tell it to do so by setting the widget's \l
2140 {QWidget::autoFillBackground}{autoFillBackground} property to
2143 \sa brushOrigin(), {QPainter#Settings}{Settings}
2146 void QPainter::setBrushOrigin(const QPointF &p)
2149 #ifdef QT_DEBUG_DRAW
2150 if (qt_show_painter_debug_output)
2151 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2155 qWarning("QPainter::setBrushOrigin: Painter not active");
2159 d->state->brushOrigin = p;
2162 d->extended->brushOriginChanged();
2166 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2170 \fn void QPainter::setBrushOrigin(const QPoint &position)
2173 Sets the brush's origin to the given \a position.
2177 \fn void QPainter::setBrushOrigin(int x, int y)
2181 Sets the brush's origin to point (\a x, \a y).
2185 \enum QPainter::CompositionMode
2187 Defines the modes supported for digital image compositing.
2188 Composition modes are used to specify how the pixels in one image,
2189 the source, are merged with the pixel in another image, the
2192 Please note that the bitwise raster operation modes, denoted with
2193 a RasterOp prefix, are only natively supported in the X11 and
2194 raster paint engines. This means that the only way to utilize
2195 these modes on the Mac is via a QImage. The RasterOp denoted blend
2196 modes are \e not supported for pens and brushes with alpha
2197 components. Also, turning on the QPainter::Antialiasing render
2198 hint will effectively disable the RasterOp modes.
2201 \image qpainter-compositionmode1.png
2202 \image qpainter-compositionmode2.png
2204 The most common type is SourceOver (often referred to as just
2205 alpha blending) where the source pixel is blended on top of the
2206 destination pixel in such a way that the alpha component of the
2207 source defines the translucency of the pixel.
2209 When the paint device is a QImage, the image format must be set to
2210 \l {QImage::Format}{Format_ARGB32Premultiplied} or
2211 \l {QImage::Format}{Format_ARGB32} for the composition modes to have
2212 any effect. For performance the premultiplied version is the preferred
2215 When a composition mode is set it applies to all painting
2216 operator, pens, brushes, gradients and pixmap/image drawing.
2218 \value CompositionMode_SourceOver This is the default mode. The
2219 alpha of the source is used to blend the pixel on top of the
2222 \value CompositionMode_DestinationOver The alpha of the
2223 destination is used to blend it on top of the source pixels. This
2224 mode is the inverse of CompositionMode_SourceOver.
2226 \value CompositionMode_Clear The pixels in the destination are
2227 cleared (set to fully transparent) independent of the source.
2229 \value CompositionMode_Source The output is the source
2230 pixel. (This means a basic copy operation and is identical to
2231 SourceOver when the source pixel is opaque).
2233 \value CompositionMode_Destination The output is the destination
2234 pixel. This means that the blending has no effect. This mode is
2235 the inverse of CompositionMode_Source.
2237 \value CompositionMode_SourceIn The output is the source, where
2238 the alpha is reduced by that of the destination.
2240 \value CompositionMode_DestinationIn The output is the
2241 destination, where the alpha is reduced by that of the
2242 source. This mode is the inverse of CompositionMode_SourceIn.
2244 \value CompositionMode_SourceOut The output is the source, where
2245 the alpha is reduced by the inverse of destination.
2247 \value CompositionMode_DestinationOut The output is the
2248 destination, where the alpha is reduced by the inverse of the
2249 source. This mode is the inverse of CompositionMode_SourceOut.
2251 \value CompositionMode_SourceAtop The source pixel is blended on
2252 top of the destination, with the alpha of the source pixel reduced
2253 by the alpha of the destination pixel.
2255 \value CompositionMode_DestinationAtop The destination pixel is
2256 blended on top of the source, with the alpha of the destination
2257 pixel is reduced by the alpha of the destination pixel. This mode
2258 is the inverse of CompositionMode_SourceAtop.
2260 \value CompositionMode_Xor The source, whose alpha is reduced with
2261 the inverse of the destination alpha, is merged with the
2262 destination, whose alpha is reduced by the inverse of the source
2263 alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2265 \value CompositionMode_Plus Both the alpha and color of the source
2266 and destination pixels are added together.
2268 \value CompositionMode_Multiply The output is the source color
2269 multiplied by the destination. Multiplying a color with white
2270 leaves the color unchanged, while multiplying a color
2271 with black produces black.
2273 \value CompositionMode_Screen The source and destination colors
2274 are inverted and then multiplied. Screening a color with white
2275 produces white, whereas screening a color with black leaves the
2278 \value CompositionMode_Overlay Multiplies or screens the colors
2279 depending on the destination color. The destination color is mixed
2280 with the source color to reflect the lightness or darkness of the
2283 \value CompositionMode_Darken The darker of the source and
2284 destination colors is selected.
2286 \value CompositionMode_Lighten The lighter of the source and
2287 destination colors is selected.
2289 \value CompositionMode_ColorDodge The destination color is
2290 brightened to reflect the source color. A black source color
2291 leaves the destination color unchanged.
2293 \value CompositionMode_ColorBurn The destination color is darkened
2294 to reflect the source color. A white source color leaves the
2295 destination color unchanged.
2297 \value CompositionMode_HardLight Multiplies or screens the colors
2298 depending on the source color. A light source color will lighten
2299 the destination color, whereas a dark source color will darken the
2302 \value CompositionMode_SoftLight Darkens or lightens the colors
2303 depending on the source color. Similar to
2304 CompositionMode_HardLight.
2306 \value CompositionMode_Difference Subtracts the darker of the
2307 colors from the lighter. Painting with white inverts the
2308 destination color, whereas painting with black leaves the
2309 destination color unchanged.
2311 \value CompositionMode_Exclusion Similar to
2312 CompositionMode_Difference, but with a lower contrast. Painting
2313 with white inverts the destination color, whereas painting with
2314 black leaves the destination color unchanged.
2316 \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2317 the source and destination pixels (src OR dst).
2319 \value RasterOp_SourceAndDestination Does a bitwise AND operation
2320 on the source and destination pixels (src AND dst).
2322 \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2323 on the source and destination pixels (src XOR dst).
2325 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2326 operation on the source and destination pixels ((NOT src) AND (NOT
2329 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2330 operation on the source and destination pixels ((NOT src) OR (NOT
2333 \value RasterOp_NotSourceXorDestination Does a bitwise operation
2334 where the source pixels are inverted and then XOR'ed with the
2335 destination ((NOT src) XOR dst).
2337 \value RasterOp_NotSource Does a bitwise operation where the
2338 source pixels are inverted (NOT src).
2340 \value RasterOp_NotSourceAndDestination Does a bitwise operation
2341 where the source is inverted and then AND'ed with the destination
2342 ((NOT src) AND dst).
2344 \value RasterOp_SourceAndNotDestination Does a bitwise operation
2345 where the source is AND'ed with the inverted destination pixels
2346 (src AND (NOT dst)).
2348 \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2349 Modes}{Composition Modes}, {Image Composition Example}
2353 Sets the composition mode to the given \a mode.
2355 \warning Only a QPainter operating on a QImage fully supports all
2356 composition modes. The RasterOp modes are supported for X11 as
2357 described in compositionMode().
2359 \sa compositionMode()
2361 void QPainter::setCompositionMode(CompositionMode mode)
2365 qWarning("QPainter::setCompositionMode: Painter not active");
2368 if (d->state->composition_mode == mode)
2371 d->state->composition_mode = mode;
2372 d->extended->compositionModeChanged();
2376 if (mode >= QPainter::RasterOp_SourceOrDestination) {
2377 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2378 qWarning("QPainter::setCompositionMode: "
2379 "Raster operation modes not supported on device");
2382 } else if (mode >= QPainter::CompositionMode_Plus) {
2383 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2384 qWarning("QPainter::setCompositionMode: "
2385 "Blend modes not supported on device");
2388 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2389 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2390 qWarning("QPainter::setCompositionMode: "
2391 "PorterDuff modes not supported on device");
2396 d->state->composition_mode = mode;
2397 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2401 Returns the current composition mode.
2403 \sa CompositionMode, setCompositionMode()
2405 QPainter::CompositionMode QPainter::compositionMode() const
2407 Q_D(const QPainter);
2409 qWarning("QPainter::compositionMode: Painter not active");
2410 return QPainter::CompositionMode_SourceOver;
2412 return d->state->composition_mode;
2416 Returns the current background brush.
2418 \sa setBackground(), {QPainter#Settings}{Settings}
2421 const QBrush &QPainter::background() const
2423 Q_D(const QPainter);
2425 qWarning("QPainter::background: Painter not active");
2426 return d->fakeState()->brush;
2428 return d->state->bgBrush;
2433 Returns true if clipping has been set; otherwise returns false.
2435 \sa setClipping(), {QPainter#Clipping}{Clipping}
2438 bool QPainter::hasClipping() const
2440 Q_D(const QPainter);
2442 qWarning("QPainter::hasClipping: Painter not active");
2445 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2450 Enables clipping if \a enable is true, or disables clipping if \a
2453 \sa hasClipping(), {QPainter#Clipping}{Clipping}
2456 void QPainter::setClipping(bool enable)
2459 #ifdef QT_DEBUG_DRAW
2460 if (qt_show_painter_debug_output)
2461 printf("QPainter::setClipping(), enable=%s, was=%s\n",
2462 enable ? "on" : "off",
2463 hasClipping() ? "on" : "off");
2466 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2470 if (hasClipping() == enable)
2473 // we can't enable clipping if we don't have a clip
2475 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2477 d->state->clipEnabled = enable;
2480 d->extended->clipEnabledChanged();
2484 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2485 d->updateState(d->state);
2490 Returns the currently set clip region. Note that the clip region
2491 is given in logical coordinates.
2493 \warning QPainter does not store the combined clip explicitly as
2494 this is handled by the underlying QPaintEngine, so the path is
2495 recreated on demand and transformed to the current logical
2496 coordinate system. This is potentially an expensive operation.
2498 \sa setClipRegion(), clipPath(), setClipping()
2501 QRegion QPainter::clipRegion() const
2503 Q_D(const QPainter);
2505 qWarning("QPainter::clipRegion: Painter not active");
2510 bool lastWasNothing = true;
2513 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2515 // ### Falcon: Use QPainterPath
2516 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2517 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2518 switch (info.clipType) {
2520 case QPainterClipInfo::RegionClip: {
2521 QTransform matrix = (info.matrix * d->invMatrix);
2522 if (lastWasNothing) {
2523 region = info.region * matrix;
2524 lastWasNothing = false;
2527 if (info.operation == Qt::IntersectClip)
2528 region &= info.region * matrix;
2529 else if (info.operation == Qt::UniteClip)
2530 region |= info.region * matrix;
2531 else if (info.operation == Qt::NoClip) {
2532 lastWasNothing = true;
2535 region = info.region * matrix;
2539 case QPainterClipInfo::PathClip: {
2540 QTransform matrix = (info.matrix * d->invMatrix);
2541 if (lastWasNothing) {
2542 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2543 info.path.fillRule());
2544 lastWasNothing = false;
2547 if (info.operation == Qt::IntersectClip) {
2548 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2549 info.path.fillRule());
2550 } else if (info.operation == Qt::UniteClip) {
2551 region |= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2552 info.path.fillRule());
2553 } else if (info.operation == Qt::NoClip) {
2554 lastWasNothing = true;
2557 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2558 info.path.fillRule());
2563 case QPainterClipInfo::RectClip: {
2564 QTransform matrix = (info.matrix * d->invMatrix);
2565 if (lastWasNothing) {
2566 region = QRegion(info.rect) * matrix;
2567 lastWasNothing = false;
2570 if (info.operation == Qt::IntersectClip) {
2571 // Use rect intersection if possible.
2572 if (matrix.type() <= QTransform::TxScale)
2573 region &= matrix.mapRect(info.rect);
2575 region &= matrix.map(QRegion(info.rect));
2576 } else if (info.operation == Qt::UniteClip) {
2577 region |= QRegion(info.rect) * matrix;
2578 } else if (info.operation == Qt::NoClip) {
2579 lastWasNothing = true;
2582 region = QRegion(info.rect) * matrix;
2587 case QPainterClipInfo::RectFClip: {
2588 QTransform matrix = (info.matrix * d->invMatrix);
2589 if (lastWasNothing) {
2590 region = QRegion(info.rectf.toRect()) * matrix;
2591 lastWasNothing = false;
2594 if (info.operation == Qt::IntersectClip) {
2595 // Use rect intersection if possible.
2596 if (matrix.type() <= QTransform::TxScale)
2597 region &= matrix.mapRect(info.rectf.toRect());
2599 region &= matrix.map(QRegion(info.rectf.toRect()));
2600 } else if (info.operation == Qt::UniteClip) {
2601 region |= QRegion(info.rectf.toRect()) * matrix;
2602 } else if (info.operation == Qt::NoClip) {
2603 lastWasNothing = true;
2606 region = QRegion(info.rectf.toRect()) * matrix;
2616 extern QPainterPath qt_regionToPath(const QRegion ®ion);
2619 Returns the currently clip as a path. Note that the clip path is
2620 given in logical coordinates.
2622 \warning QPainter does not store the combined clip explicitly as
2623 this is handled by the underlying QPaintEngine, so the path is
2624 recreated on demand and transformed to the current logical
2625 coordinate system. This is potentially an expensive operation.
2627 \sa setClipPath(), clipRegion(), setClipping()
2629 QPainterPath QPainter::clipPath() const
2631 Q_D(const QPainter);
2633 // ### Since we do not support path intersections and path unions yet,
2634 // we just use clipRegion() here...
2636 qWarning("QPainter::clipPath: Painter not active");
2637 return QPainterPath();
2640 // No clip, return empty
2641 if (d->state->clipInfo.size() == 0) {
2642 return QPainterPath();
2645 // Update inverse matrix, used below.
2647 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2649 // For the simple case avoid conversion.
2650 if (d->state->clipInfo.size() == 1
2651 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2652 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2653 return d->state->clipInfo.at(0).path * matrix;
2655 } else if (d->state->clipInfo.size() == 1
2656 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2657 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2659 path.addRect(d->state->clipInfo.at(0).rect);
2660 return path * matrix;
2662 // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2663 return qt_regionToPath(clipRegion());
2669 Returns the bounding rectangle of the current clip if there is a clip;
2670 otherwise returns an empty rectangle. Note that the clip region is
2671 given in logical coordinates.
2673 The bounding rectangle is not guaranteed to be tight.
2675 \sa setClipRect(), setClipPath(), setClipRegion()
2680 QRectF QPainter::clipBoundingRect() const
2682 Q_D(const QPainter);
2685 qWarning("QPainter::clipBoundingRect: Painter not active");
2689 // Accumulate the bounding box in device space. This is not 100%
2690 // precise, but it fits within the guarantee and it is resonably
2693 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2695 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2697 if (info.clipType == QPainterClipInfo::RectClip)
2699 else if (info.clipType == QPainterClipInfo::RectFClip)
2701 else if (info.clipType == QPainterClipInfo::RegionClip)
2702 r = info.region.boundingRect();
2704 r = info.path.boundingRect();
2706 r = info.matrix.mapRect(r);
2710 else if (info.operation == Qt::IntersectClip)
2712 else if (info.operation == Qt::UniteClip)
2717 // Map the rectangle back into logical space using the inverse
2720 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2722 return d->invMatrix.mapRect(bounds);
2726 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2728 Enables clipping, and sets the clip region to the given \a
2729 rectangle using the given clip \a operation. The default operation
2730 is to replace the current clip rectangle.
2732 Note that the clip rectangle is specified in logical (painter)
2735 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2737 void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2742 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2743 op = Qt::ReplaceClip;
2746 qWarning("QPainter::setClipRect: Painter not active");
2749 qreal right = rect.x() + rect.width();
2750 qreal bottom = rect.y() + rect.height();
2751 qreal pts[] = { rect.x(), rect.y(),
2755 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2756 d->state->clipEnabled = true;
2757 d->extended->clip(vp, op);
2758 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2759 d->state->clipInfo.clear();
2760 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2761 d->state->clipOperation = op;
2765 if (qreal(int(rect.top())) == rect.top()
2766 && qreal(int(rect.bottom())) == rect.bottom()
2767 && qreal(int(rect.left())) == rect.left()
2768 && qreal(int(rect.right())) == rect.right())
2770 setClipRect(rect.toRect(), op);
2774 if (rect.isEmpty()) {
2775 setClipRegion(QRegion(), op);
2781 setClipPath(path, op);
2785 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2788 Enables clipping, and sets the clip region to the given \a rectangle using the given
2791 void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2796 qWarning("QPainter::setClipRect: Painter not active");
2800 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2801 op = Qt::ReplaceClip;
2804 d->state->clipEnabled = true;
2805 d->extended->clip(rect, op);
2806 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2807 d->state->clipInfo.clear();
2808 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2809 d->state->clipOperation = op;
2813 d->state->clipRegion = rect;
2814 d->state->clipOperation = op;
2815 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2816 d->state->clipInfo.clear();
2817 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2818 d->state->clipEnabled = true;
2819 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2820 d->updateState(d->state);
2824 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2826 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2827 with the given \a width and \a height.
2831 \fn void QPainter::setClipRegion(const QRegion ®ion, Qt::ClipOperation operation)
2833 Sets the clip region to the given \a region using the specified clip
2834 \a operation. The default clip operation is to replace the current
2837 Note that the clip region is given in logical coordinates.
2839 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2841 void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2844 #ifdef QT_DEBUG_DRAW
2845 QRect rect = r.boundingRect();
2846 if (qt_show_painter_debug_output)
2847 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2848 r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2851 qWarning("QPainter::setClipRegion: Painter not active");
2855 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2856 op = Qt::ReplaceClip;
2859 d->state->clipEnabled = true;
2860 d->extended->clip(r, op);
2861 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2862 d->state->clipInfo.clear();
2863 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2864 d->state->clipOperation = op;
2868 d->state->clipRegion = r;
2869 d->state->clipOperation = op;
2870 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2871 d->state->clipInfo.clear();
2872 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2873 d->state->clipEnabled = true;
2874 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2875 d->updateState(d->state);
2882 Sets the transformation matrix to \a matrix and enables transformations.
2884 \note It is advisable to use setWorldTransform() instead of this function to
2885 preserve the properties of perspective transformations.
2887 If \a combine is true, then \a matrix is combined with the current
2888 transformation matrix; otherwise \a matrix replaces the current
2889 transformation matrix.
2891 If \a matrix is the identity matrix and \a combine is false, this
2892 function calls setWorldMatrixEnabled(false). (The identity matrix is the
2893 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2896 The following functions can transform the coordinate system without using
2905 They operate on the painter's worldMatrix() and are implemented like this:
2907 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 4
2909 Note that when using setWorldMatrix() function you should always have
2910 \a combine be true when you are drawing into a QPicture. Otherwise
2911 it may not be possible to replay the picture with additional
2912 transformations; using the translate(), scale(), etc. convenience
2915 For more information about the coordinate system, transformations
2916 and window-viewport conversion, see \l {Coordinate System}.
2918 \sa setWorldTransform(), QTransform
2921 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2923 setWorldTransform(QTransform(matrix), combine);
2930 Returns the world transformation matrix.
2932 It is advisable to use worldTransform() because worldMatrix() does not
2933 preserve the properties of perspective transformations.
2935 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2939 const QMatrix &QPainter::worldMatrix() const
2941 Q_D(const QPainter);
2943 qWarning("QPainter::worldMatrix: Painter not active");
2944 return d->fakeState()->transform.toAffine();
2946 return d->state->worldMatrix.toAffine();
2952 Use setWorldTransform() instead.
2954 \sa setWorldTransform()
2957 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
2959 setWorldTransform(QTransform(matrix), combine);
2965 Use worldTransform() instead.
2967 \sa worldTransform()
2970 const QMatrix &QPainter::matrix() const
2972 return worldMatrix();
2980 Returns the transformation matrix combining the current
2981 window/viewport and world transformation.
2983 It is advisable to use combinedTransform() instead of this
2984 function to preserve the properties of perspective transformations.
2986 \sa setWorldTransform(), setWindow(), setViewport()
2988 QMatrix QPainter::combinedMatrix() const
2990 return combinedTransform().toAffine();
2997 Returns the matrix that transforms from logical coordinates to
2998 device coordinates of the platform dependent paint device.
3000 \note It is advisable to use deviceTransform() instead of this
3001 function to preserve the properties of perspective transformations.
3003 This function is \e only needed when using platform painting
3004 commands on the platform dependent handle (Qt::HANDLE), and the
3005 platform does not do transformations nativly.
3007 The QPaintEngine::PaintEngineFeature enum can be queried to
3008 determine whether the platform performs the transformations or
3011 \sa worldMatrix(), QPaintEngine::hasFeature(),
3013 const QMatrix &QPainter::deviceMatrix() const
3015 Q_D(const QPainter);
3017 qWarning("QPainter::deviceMatrix: Painter not active");
3018 return d->fakeState()->transform.toAffine();
3020 return d->state->matrix.toAffine();
3026 Resets any transformations that were made using translate(), scale(),
3027 shear(), rotate(), setWorldMatrix(), setViewport() and
3030 It is advisable to use resetTransform() instead of this function
3031 to preserve the properties of perspective transformations.
3033 \sa {QPainter#Coordinate Transformations}{Coordinate
3037 void QPainter::resetMatrix()
3046 Enables transformations if \a enable is true, or disables
3047 transformations if \a enable is false. The world transformation
3048 matrix is not changed.
3050 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3051 Transformations}{Coordinate Transformations}
3054 void QPainter::setWorldMatrixEnabled(bool enable)
3057 #ifdef QT_DEBUG_DRAW
3058 if (qt_show_painter_debug_output)
3059 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3063 qWarning("QPainter::setMatrixEnabled: Painter not active");
3066 if (enable == d->state->WxF)
3069 d->state->WxF = enable;
3076 Returns true if world transformation is enabled; otherwise returns
3079 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3082 bool QPainter::worldMatrixEnabled() const
3084 Q_D(const QPainter);
3086 qWarning("QPainter::worldMatrixEnabled: Painter not active");
3089 return d->state->WxF;
3095 Use setWorldMatrixEnabled() instead.
3097 \sa setWorldMatrixEnabled()
3100 void QPainter::setMatrixEnabled(bool enable)
3102 setWorldMatrixEnabled(enable);
3108 Use worldMatrixEnabled() instead
3110 \sa worldMatrixEnabled()
3113 bool QPainter::matrixEnabled() const
3115 return worldMatrixEnabled();
3119 Scales the coordinate system by (\a{sx}, \a{sy}).
3121 \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate
3125 void QPainter::scale(qreal sx, qreal sy)
3127 #ifdef QT_DEBUG_DRAW
3128 if (qt_show_painter_debug_output)
3129 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3133 qWarning("QPainter::scale: Painter not active");
3137 d->state->worldMatrix.scale(sx,sy);
3138 d->state->WxF = true;
3143 Shears the coordinate system by (\a{sh}, \a{sv}).
3145 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3149 void QPainter::shear(qreal sh, qreal sv)
3151 #ifdef QT_DEBUG_DRAW
3152 if (qt_show_painter_debug_output)
3153 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3157 qWarning("QPainter::shear: Painter not active");
3161 d->state->worldMatrix.shear(sh, sv);
3162 d->state->WxF = true;
3167 \fn void QPainter::rotate(qreal angle)
3169 Rotates the coordinate system the given \a angle clockwise.
3171 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3175 void QPainter::rotate(qreal a)
3177 #ifdef QT_DEBUG_DRAW
3178 if (qt_show_painter_debug_output)
3179 printf("QPainter::rotate(), angle=%f\n", a);
3183 qWarning("QPainter::rotate: Painter not active");
3187 d->state->worldMatrix.rotate(a);
3188 d->state->WxF = true;
3193 Translates the coordinate system by the given \a offset; i.e. the
3194 given \a offset is added to points.
3196 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3199 void QPainter::translate(const QPointF &offset)
3201 qreal dx = offset.x();
3202 qreal dy = offset.y();
3203 #ifdef QT_DEBUG_DRAW
3204 if (qt_show_painter_debug_output)
3205 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3209 qWarning("QPainter::translate: Painter not active");
3213 d->state->worldMatrix.translate(dx, dy);
3214 d->state->WxF = true;
3219 \fn void QPainter::translate(const QPoint &offset)
3222 Translates the coordinate system by the given \a offset.
3226 \fn void QPainter::translate(qreal dx, qreal dy)
3229 Translates the coordinate system by the vector (\a dx, \a dy).
3233 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3235 Enables clipping, and sets the clip path for the painter to the
3236 given \a path, with the clip \a operation.
3238 Note that the clip path is specified in logical (painter)
3241 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3244 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3246 #ifdef QT_DEBUG_DRAW
3247 if (qt_show_painter_debug_output) {
3248 QRectF b = path.boundingRect();
3249 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3250 path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3256 qWarning("QPainter::setClipPath: Painter not active");
3260 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
3261 op = Qt::ReplaceClip;
3264 d->state->clipEnabled = true;
3265 d->extended->clip(path, op);
3266 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3267 d->state->clipInfo.clear();
3268 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3269 d->state->clipOperation = op;
3273 d->state->clipPath = path;
3274 d->state->clipOperation = op;
3275 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3276 d->state->clipInfo.clear();
3277 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3278 d->state->clipEnabled = true;
3279 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3280 d->updateState(d->state);
3284 Draws the outline (strokes) the path \a path with the pen specified
3287 \sa fillPath(), {QPainter#Drawing}{Drawing}
3289 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3294 qWarning("QPainter::strokePath: Painter not active");
3302 const QGradient *g = qpen_brush(pen).gradient();
3303 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3304 d->extended->stroke(qtVectorPathForPath(path), pen);
3309 QBrush oldBrush = d->state->brush;
3310 QPen oldPen = d->state->pen;
3313 setBrush(Qt::NoBrush);
3323 Fills the given \a path using the given \a brush. The outline is
3326 Alternatively, you can specify a QColor instead of a QBrush; the
3327 QBrush constructor (taking a QColor argument) will automatically
3328 create a solid pattern brush.
3332 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3337 qWarning("QPainter::fillPath: Painter not active");
3345 const QGradient *g = brush.gradient();
3346 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3347 d->extended->fill(qtVectorPathForPath(path), brush);
3352 QBrush oldBrush = d->state->brush;
3353 QPen oldPen = d->state->pen;
3366 Draws the given painter \a path using the current pen for outline
3367 and the current brush for filling.
3371 \o \inlineimage qpainter-path.png
3373 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 5
3376 \sa {painting/painterpaths}{the Painter Paths
3377 example},{demos/deform}{the Vector Deformation demo}
3379 void QPainter::drawPath(const QPainterPath &path)
3381 #ifdef QT_DEBUG_DRAW
3382 QRectF pathBounds = path.boundingRect();
3383 if (qt_show_painter_debug_output)
3384 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3385 path.elementCount(),
3386 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3392 qWarning("QPainter::drawPath: Painter not active");
3397 d->extended->drawPath(path);
3400 d->updateState(d->state);
3402 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3403 d->engine->drawPath(path);
3405 d->draw_helper(path);
3410 \fn void QPainter::drawLine(const QLineF &line)
3412 Draws a line defined by \a line.
3416 \o \inlineimage qpainter-line.png
3418 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 6
3421 \sa drawLines(), drawPolyline(), {Coordinate System}
3425 \fn void QPainter::drawLine(const QLine &line)
3428 Draws a line defined by \a line.
3432 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3435 Draws a line from \a p1 to \a p2.
3439 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3442 Draws a line from \a p1 to \a p2.
3446 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3449 Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3450 current pen position to (\a x2, \a y2).
3454 \fn void QPainter::drawRect(const QRectF &rectangle)
3456 Draws the current \a rectangle with the current pen and brush.
3458 A filled rectangle has a size of \a{rectangle}.size(). A stroked
3459 rectangle has a size of \a{rectangle}.size() plus the pen width.
3463 \o \inlineimage qpainter-rectangle.png
3465 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 7
3468 \sa drawRects(), drawPolygon(), {Coordinate System}
3472 \fn void QPainter::drawRect(const QRect &rectangle)
3476 Draws the current \a rectangle with the current pen and brush.
3480 \fn void QPainter::drawRect(int x, int y, int width, int height)
3484 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3485 with the given \a width and \a height.
3489 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3491 Draws the first \a rectCount of the given \a rectangles using the
3492 current pen and brush.
3496 void QPainter::drawRects(const QRectF *rects, int rectCount)
3498 #ifdef QT_DEBUG_DRAW
3499 if (qt_show_painter_debug_output)
3500 printf("QPainter::drawRects(), count=%d\n", rectCount);
3505 qWarning("QPainter::drawRects: Painter not active");
3513 d->extended->drawRects(rects, rectCount);
3517 d->updateState(d->state);
3519 if (!d->state->emulationSpecifier) {
3520 d->engine->drawRects(rects, rectCount);
3524 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3525 && d->state->matrix.type() == QTransform::TxTranslate) {
3526 for (int i=0; i<rectCount; ++i) {
3527 QRectF r(rects[i].x() + d->state->matrix.dx(),
3528 rects[i].y() + d->state->matrix.dy(),
3531 d->engine->drawRects(&r, 1);
3534 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3535 for (int i=0; i<rectCount; ++i) {
3536 QPainterPath rectPath;
3537 rectPath.addRect(rects[i]);
3538 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3541 QPainterPath rectPath;
3542 for (int i=0; i<rectCount; ++i)
3543 rectPath.addRect(rects[i]);
3544 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3550 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3553 Draws the first \a rectCount of the given \a rectangles using the
3554 current pen and brush.
3556 void QPainter::drawRects(const QRect *rects, int rectCount)
3558 #ifdef QT_DEBUG_DRAW
3559 if (qt_show_painter_debug_output)
3560 printf("QPainter::drawRects(), count=%d\n", rectCount);
3565 qWarning("QPainter::drawRects: Painter not active");
3573 d->extended->drawRects(rects, rectCount);
3577 d->updateState(d->state);
3579 if (!d->state->emulationSpecifier) {
3580 d->engine->drawRects(rects, rectCount);
3584 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3585 && d->state->matrix.type() == QTransform::TxTranslate) {
3586 for (int i=0; i<rectCount; ++i) {
3587 QRectF r(rects[i].x() + d->state->matrix.dx(),
3588 rects[i].y() + d->state->matrix.dy(),
3592 d->engine->drawRects(&r, 1);
3595 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3596 for (int i=0; i<rectCount; ++i) {
3597 QPainterPath rectPath;
3598 rectPath.addRect(rects[i]);
3599 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3602 QPainterPath rectPath;
3603 for (int i=0; i<rectCount; ++i)
3604 rectPath.addRect(rects[i]);
3606 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3612 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3615 Draws the given \a rectangles using the current pen and brush.
3619 \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3623 Draws the given \a rectangles using the current pen and brush.
3627 \fn void QPainter::drawPoint(const QPointF &position)
3629 Draws a single point at the given \a position using the current
3632 \sa {Coordinate System}
3636 \fn void QPainter::drawPoint(const QPoint &position)
3639 Draws a single point at the given \a position using the current
3643 /*! \fn void QPainter::drawPoint(int x, int y)
3647 Draws a single point at position (\a x, \a y).
3651 Draws the first \a pointCount points in the array \a points using
3652 the current pen's color.
3654 \sa {Coordinate System}
3656 void QPainter::drawPoints(const QPointF *points, int pointCount)
3658 #ifdef QT_DEBUG_DRAW
3659 if (qt_show_painter_debug_output)
3660 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3665 qWarning("QPainter::drawPoints: Painter not active");
3669 if (pointCount <= 0)
3673 d->extended->drawPoints(points, pointCount);
3677 d->updateState(d->state);
3679 if (!d->state->emulationSpecifier) {
3680 d->engine->drawPoints(points, pointCount);
3684 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3685 && d->state->matrix.type() == QTransform::TxTranslate) {
3686 // ### use drawPoints function
3687 for (int i=0; i<pointCount; ++i) {
3688 QPointF pt(points[i].x() + d->state->matrix.dx(),
3689 points[i].y() + d->state->matrix.dy());
3690 d->engine->drawPoints(&pt, 1);
3693 QPen pen = d->state->pen;
3694 bool flat_pen = pen.capStyle() == Qt::FlatCap;
3697 pen.setCapStyle(Qt::SquareCap);
3701 for (int i=0; i<pointCount; ++i) {
3702 path.moveTo(points[i].x(), points[i].y());
3703 path.lineTo(points[i].x() + 0.0001, points[i].y());
3705 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3714 Draws the first \a pointCount points in the array \a points using
3715 the current pen's color.
3718 void QPainter::drawPoints(const QPoint *points, int pointCount)
3720 #ifdef QT_DEBUG_DRAW
3721 if (qt_show_painter_debug_output)
3722 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3727 qWarning("QPainter::drawPoints: Painter not active");
3731 if (pointCount <= 0)
3735 d->extended->drawPoints(points, pointCount);
3739 d->updateState(d->state);
3741 if (!d->state->emulationSpecifier) {
3742 d->engine->drawPoints(points, pointCount);
3746 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3747 && d->state->matrix.type() == QTransform::TxTranslate) {
3748 // ### use drawPoints function
3749 for (int i=0; i<pointCount; ++i) {
3750 QPointF pt(points[i].x() + d->state->matrix.dx(),
3751 points[i].y() + d->state->matrix.dy());
3752 d->engine->drawPoints(&pt, 1);
3755 QPen pen = d->state->pen;
3756 bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3759 pen.setCapStyle(Qt::SquareCap);
3763 for (int i=0; i<pointCount; ++i) {
3764 path.moveTo(points[i].x(), points[i].y());
3765 path.lineTo(points[i].x() + 0.0001, points[i].y());
3767 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3774 \fn void QPainter::drawPoints(const QPolygonF &points)
3778 Draws the points in the vector \a points.
3782 \fn void QPainter::drawPoints(const QPolygon &points)
3786 Draws the points in the vector \a points.
3790 \fn void QPainter::drawPoints(const QPolygon &polygon, int index,
3796 Draws \a count points in the vector \a polygon starting on \a index
3797 using the current pen.
3799 Use drawPoints() combined with QPolygon::constData() instead.
3802 QPainter painter(this);
3803 painter.drawPoints(polygon, index, count);
3805 int pointCount = (count == -1) ? polygon.size() - index : count;
3807 QPainter painter(this);
3808 painter.drawPoints(polygon.constData() + index, pointCount);
3813 Sets the background mode of the painter to the given \a mode
3815 Qt::TransparentMode (the default) draws stippled lines and text
3816 without setting the background pixels. Qt::OpaqueMode fills these
3817 space with the current background color.
3819 Note that in order to draw a bitmap or pixmap transparently, you
3820 must use QPixmap::setMask().
3822 \sa backgroundMode(), setBackground(),
3823 {QPainter#Settings}{Settings}
3826 void QPainter::setBackgroundMode(Qt::BGMode mode)
3828 #ifdef QT_DEBUG_DRAW
3829 if (qt_show_painter_debug_output)
3830 printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3835 qWarning("QPainter::setBackgroundMode: Painter not active");
3838 if (d->state->bgMode == mode)
3841 d->state->bgMode = mode;
3843 d->checkEmulation();
3845 d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3850 Returns the current background mode.
3852 \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3854 Qt::BGMode QPainter::backgroundMode() const
3856 Q_D(const QPainter);
3858 qWarning("QPainter::backgroundMode: Painter not active");
3859 return Qt::TransparentMode;
3861 return d->state->bgMode;
3868 Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3872 void QPainter::setPen(const QColor &color)
3874 #ifdef QT_DEBUG_DRAW
3875 if (qt_show_painter_debug_output)
3876 printf("QPainter::setPen(), color=%04x\n", color.rgb());
3880 qWarning("QPainter::setPen: Painter not active");
3884 if (d->state->pen.style() == Qt::SolidLine
3885 && d->state->pen.widthF() == 0
3886 && d->state->pen.isSolid()
3887 && d->state->pen.color() == color)
3890 QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
3892 d->state->pen = pen;
3894 d->extended->penChanged();
3896 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3900 Sets the painter's pen to be the given \a pen.
3902 The \a pen defines how to draw lines and outlines, and it also
3903 defines the text color.
3905 \sa pen(), {QPainter#Settings}{Settings}
3908 void QPainter::setPen(const QPen &pen)
3911 #ifdef QT_DEBUG_DRAW
3912 if (qt_show_painter_debug_output)
3913 printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3914 pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3918 qWarning("QPainter::setPen: Painter not active");
3922 if (d->state->pen == pen)
3925 d->state->pen = pen;
3928 d->checkEmulation();
3929 d->extended->penChanged();
3933 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3939 Sets the painter's pen to have the given \a style, width 0 and
3943 void QPainter::setPen(Qt::PenStyle style)
3947 qWarning("QPainter::setPen: Painter not active");
3951 if (d->state->pen.style() == style
3952 && (style == Qt::NoPen || (d->state->pen.widthF() == 0
3953 && d->state->pen.isSolid()
3954 && d->state->pen.color() == QColor(Qt::black))))
3957 // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
3958 // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
3959 d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
3962 d->extended->penChanged();
3964 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3969 Returns the painter's current pen.
3971 \sa setPen(), {QPainter#Settings}{Settings}
3974 const QPen &QPainter::pen() const
3976 Q_D(const QPainter);
3978 qWarning("QPainter::pen: Painter not active");
3979 return d->fakeState()->pen;
3981 return d->state->pen;
3986 Sets the painter's brush to the given \a brush.
3988 The painter's brush defines how shapes are filled.
3990 \sa brush(), {QPainter#Settings}{Settings}
3993 void QPainter::setBrush(const QBrush &brush)
3995 #ifdef QT_DEBUG_DRAW
3996 if (qt_show_painter_debug_output)
3997 printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
4001 qWarning("QPainter::setBrush: Painter not active");
4005 if (d->state->brush.d == brush.d)
4009 d->state->brush = brush;
4010 d->checkEmulation();
4011 d->extended->brushChanged();
4015 d->state->brush = brush;
4016 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4023 Sets the painter's brush to black color and the specified \a
4027 void QPainter::setBrush(Qt::BrushStyle style)
4031 qWarning("QPainter::setBrush: Painter not active");
4034 if (d->state->brush.style() == style &&
4035 (style == Qt::NoBrush
4036 || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
4038 d->state->brush = QBrush(Qt::black, style);
4040 d->extended->brushChanged();
4042 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4046 Returns the painter's current brush.
4048 \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
4051 const QBrush &QPainter::brush() const
4053 Q_D(const QPainter);
4055 qWarning("QPainter::brush: Painter not active");
4056 return d->fakeState()->brush;
4058 return d->state->brush;
4062 \fn void QPainter::setBackground(const QBrush &brush)
4064 Sets the background brush of the painter to the given \a brush.
4066 The background brush is the brush that is filled in when drawing
4067 opaque text, stippled lines and bitmaps. The background brush has
4068 no effect in transparent background mode (which is the default).
4070 \sa background(), setBackgroundMode(),
4071 {QPainter#Settings}{Settings}
4074 void QPainter::setBackground(const QBrush &bg)
4076 #ifdef QT_DEBUG_DRAW
4077 if (qt_show_painter_debug_output)
4078 printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4083 qWarning("QPainter::setBackground: Painter not active");
4086 d->state->bgBrush = bg;
4088 d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4092 Sets the painter's font to the given \a font.
4094 This font is used by subsequent drawText() functions. The text
4095 color is the same as the pen color.
4097 If you set a font that isn't available, Qt finds a close match.
4098 font() will return what you set using setFont() and fontInfo() returns the
4099 font actually being used (which may be the same).
4101 \sa font(), drawText(), {QPainter#Settings}{Settings}
4104 void QPainter::setFont(const QFont &font)
4108 #ifdef QT_DEBUG_DRAW
4109 if (qt_show_painter_debug_output)
4110 printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4114 qWarning("QPainter::setFont: Painter not active");
4118 d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4120 d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4124 Returns the currently set font used for drawing text.
4126 \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4128 const QFont &QPainter::font() const
4130 Q_D(const QPainter);
4132 qWarning("QPainter::font: Painter not active");
4133 return d->fakeState()->font;
4135 return d->state->font;
4141 Draws the given rectangle \a rect with rounded corners.
4143 The \a xRadius and \a yRadius arguments specify the radii
4144 of the ellipses defining the corners of the rounded rectangle.
4145 When \a mode is Qt::RelativeSize, \a xRadius and
4146 \a yRadius are specified in percentage of half the rectangle's
4147 width and height respectively, and should be in the range
4150 A filled rectangle has a size of rect.size(). A stroked rectangle
4151 has a size of rect.size() plus the pen width.
4155 \o \inlineimage qpainter-roundrect.png
4157 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 8
4160 \sa drawRect(), QPen
4162 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4164 #ifdef QT_DEBUG_DRAW
4165 if (qt_show_painter_debug_output)
4166 printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4173 if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
4179 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4184 path.addRoundedRect(rect, xRadius, yRadius, mode);
4189 \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4190 Qt::SizeMode mode = Qt::AbsoluteSize);
4194 Draws the given rectangle \a rect with rounded corners.
4198 \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4199 Qt::SizeMode mode = Qt::AbsoluteSize);
4203 Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4209 Draws a rectangle \a r with rounded corners.
4211 The \a xRnd and \a yRnd arguments specify how rounded the corners
4212 should be. 0 is angled corners, 99 is maximum roundedness.
4214 A filled rectangle has a size of r.size(). A stroked rectangle
4215 has a size of r.size() plus the pen width.
4217 \sa drawRoundedRect()
4219 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4221 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4226 \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4231 Draws the rectangle \a r with rounded corners.
4237 \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4241 Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4245 \fn void QPainter::drawEllipse(const QRectF &rectangle)
4247 Draws the ellipse defined by the given \a rectangle.
4249 A filled ellipse has a size of \a{rectangle}.\l
4250 {QRect::size()}{size()}. A stroked ellipse has a size of
4251 \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4255 \o \inlineimage qpainter-ellipse.png
4257 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 9
4260 \sa drawPie(), {Coordinate System}
4262 void QPainter::drawEllipse(const QRectF &r)
4264 #ifdef QT_DEBUG_DRAW
4265 if (qt_show_painter_debug_output)
4266 printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4273 QRectF rect(r.normalized());
4276 d->extended->drawEllipse(rect);
4280 d->updateState(d->state);
4281 if (d->state->emulationSpecifier) {
4282 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4283 && d->state->matrix.type() == QTransform::TxTranslate) {
4284 rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4287 path.addEllipse(rect);
4288 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4293 d->engine->drawEllipse(rect);
4297 \fn QPainter::drawEllipse(const QRect &rectangle)
4301 Draws the ellipse defined by the given \a rectangle.
4303 void QPainter::drawEllipse(const QRect &r)
4305 #ifdef QT_DEBUG_DRAW
4306 if (qt_show_painter_debug_output)
4307 printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4314 QRect rect(r.normalized());
4317 d->extended->drawEllipse(rect);
4321 d->updateState(d->state);
4323 if (d->state->emulationSpecifier) {
4324 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4325 && d->state->matrix.type() == QTransform::TxTranslate) {
4326 rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4329 path.addEllipse(rect);
4330 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4335 d->engine->drawEllipse(rect);
4339 \fn QPainter::drawEllipse(int x, int y, int width, int height)
4343 Draws the ellipse defined by the rectangle beginning at (\a{x},
4344 \a{y}) with the given \a width and \a height.
4350 \fn QPainter::drawEllipse(const QPointF ¢er, qreal rx, qreal ry)
4354 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4360 \fn QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)
4364 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4368 \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4370 Draws the arc defined by the given \a rectangle, \a startAngle and
4373 The \a startAngle and \a spanAngle must be specified in 1/16th of
4374 a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4375 values for the angles mean counter-clockwise while negative values
4376 mean the clockwise direction. Zero degrees is at the 3 o'clock
4381 \o \inlineimage qpainter-arc.png
4383 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 10
4386 \sa drawPie(), drawChord(), {Coordinate System}
4389 void QPainter::drawArc(const QRectF &r, int a, int alen)
4391 #ifdef QT_DEBUG_DRAW
4392 if (qt_show_painter_debug_output)
4393 printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4394 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4401 QRectF rect = r.normalized();
4404 path.arcMoveTo(rect, a/16.0);
4405 path.arcTo(rect, a/16.0, alen/16.0);
4406 strokePath(path, d->state->pen);
4409 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4414 Draws the arc defined by the given \a rectangle, \a startAngle and
4419 \fn void QPainter::drawArc(int x, int y, int width, int height,
4420 int startAngle, int spanAngle)
4424 Draws the arc defined by the rectangle beginning at (\a x, \a y)
4425 with the specified \a width and \a height, and the given \a
4426 startAngle and \a spanAngle.
4430 \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4432 Draws a pie defined by the given \a rectangle, \a startAngle and
4435 The pie is filled with the current brush().
4437 The startAngle and spanAngle must be specified in 1/16th of a
4438 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4439 for the angles mean counter-clockwise while negative values mean
4440 the clockwise direction. Zero degrees is at the 3 o'clock
4445 \o \inlineimage qpainter-pie.png
4447 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 11
4450 \sa drawEllipse(), drawChord(), {Coordinate System}
4452 void QPainter::drawPie(const QRectF &r, int a, int alen)
4454 #ifdef QT_DEBUG_DRAW
4455 if (qt_show_painter_debug_output)
4456 printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4457 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4468 if (a < 0) a += (360*16);
4471 QRectF rect = r.normalized();
4474 path.moveTo(rect.center());
4475 path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4476 path.closeSubpath();
4482 \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4485 Draws a pie defined by the given \a rectangle, \a startAngle and
4490 \fn void QPainter::drawPie(int x, int y, int width, int height, int
4491 startAngle, int spanAngle)
4495 Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4496 the specified \a width and \a height, and the given \a startAngle and
4501 \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4503 Draws the chord defined by the given \a rectangle, \a startAngle and
4504 \a spanAngle. The chord is filled with the current brush().
4506 The startAngle and spanAngle must be specified in 1/16th of a
4507 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4508 for the angles mean counter-clockwise while negative values mean
4509 the clockwise direction. Zero degrees is at the 3 o'clock
4514 \o \inlineimage qpainter-chord.png
4516 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 12
4519 \sa drawArc(), drawPie(), {Coordinate System}
4521 void QPainter::drawChord(const QRectF &r, int a, int alen)
4523 #ifdef QT_DEBUG_DRAW
4524 if (qt_show_painter_debug_output)
4525 printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4526 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4533 QRectF rect = r.normalized();
4536 path.arcMoveTo(rect, a/16.0);
4537 path.arcTo(rect, a/16.0, alen/16.0);
4538 path.closeSubpath();
4542 \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4546 Draws the chord defined by the given \a rectangle, \a startAngle and
4551 \fn void QPainter::drawChord(int x, int y, int width, int height, int
4552 startAngle, int spanAngle)
4556 Draws the chord defined by the rectangle beginning at (\a x, \a y)
4557 with the specified \a width and \a height, and the given \a
4558 startAngle and \a spanAngle.
4563 Draws the first \a lineCount lines in the array \a lines
4564 using the current pen.
4566 \sa drawLine(), drawPolyline()
4568 void QPainter::drawLines(const QLineF *lines, int lineCount)
4570 #ifdef QT_DEBUG_DRAW
4571 if (qt_show_painter_debug_output)
4572 printf("QPainter::drawLines(), line count=%d\n", lineCount);
4577 if (!d->engine || lineCount < 1)
4581 d->extended->drawLines(lines, lineCount);
4585 d->updateState(d->state);
4587 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4589 if (lineEmulation) {
4590 if (lineEmulation == QPaintEngine::PrimitiveTransform
4591 && d->state->matrix.type() == QTransform::TxTranslate) {
4592 for (int i = 0; i < lineCount; ++i) {
4593 QLineF line = lines[i];
4594 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4595 d->engine->drawLines(&line, 1);
4598 QPainterPath linePath;
4599 for (int i = 0; i < lineCount; ++i) {
4600 linePath.moveTo(lines[i].p1());
4601 linePath.lineTo(lines[i].p2());
4603 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4607 d->engine->drawLines(lines, lineCount);
4611 \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4614 Draws the first \a lineCount lines in the array \a lines
4615 using the current pen.
4617 void QPainter::drawLines(const QLine *lines, int lineCount)
4619 #ifdef QT_DEBUG_DRAW
4620 if (qt_show_painter_debug_output)
4621 printf("QPainter::drawLine(), line count=%d\n", lineCount);
4626 if (!d->engine || lineCount < 1)
4630 d->extended->drawLines(lines, lineCount);
4634 d->updateState(d->state);
4636 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4638 if (lineEmulation) {
4639 if (lineEmulation == QPaintEngine::PrimitiveTransform
4640 && d->state->matrix.type() == QTransform::TxTranslate) {
4641 for (int i = 0; i < lineCount; ++i) {
4642 QLineF line = lines[i];
4643 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4644 d->engine->drawLines(&line, 1);
4647 QPainterPath linePath;
4648 for (int i = 0; i < lineCount; ++i) {
4649 linePath.moveTo(lines[i].p1());
4650 linePath.lineTo(lines[i].p2());
4652 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4656 d->engine->drawLines(lines, lineCount);
4662 Draws the first \a lineCount lines in the array \a pointPairs
4663 using the current pen. The lines are specified as pairs of points
4664 so the number of entries in \a pointPairs must be at least \a
4667 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4669 Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4671 drawLines((QLineF*)pointPairs, lineCount);
4677 Draws the first \a lineCount lines in the array \a pointPairs
4678 using the current pen.
4680 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4682 Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4684 drawLines((QLine*)pointPairs, lineCount);
4689 \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4692 Draws a line for each pair of points in the vector \a pointPairs
4693 using the current pen. If there is an odd number of points in the
4694 array, the last point will be ignored.
4698 \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4701 Draws a line for each pair of points in the vector \a pointPairs
4702 using the current pen.
4706 \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4709 Draws the set of lines defined by the list \a lines using the
4710 current pen and brush.
4714 \fn void QPainter::drawLines(const QVector<QLine> &lines)
4717 Draws the set of lines defined by the list \a lines using the
4718 current pen and brush.
4722 Draws the polyline defined by the first \a pointCount points in \a
4723 points using the current pen.
4725 Note that unlike the drawPolygon() function the last point is \e
4726 not connected to the first, neither is the polyline filled.
4731 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 13
4734 \sa drawLines(), drawPolygon(), {Coordinate System}
4736 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4738 #ifdef QT_DEBUG_DRAW
4739 if (qt_show_painter_debug_output)
4740 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4744 if (!d->engine || pointCount < 2)
4748 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4752 d->updateState(d->state);
4754 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4756 if (lineEmulation) {
4758 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4759 // && d->state->matrix.type() == QTransform::TxTranslate) {
4761 QPainterPath polylinePath(points[0]);
4762 for (int i=1; i<pointCount; ++i)
4763 polylinePath.lineTo(points[i]);
4764 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4767 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4774 Draws the polyline defined by the first \a pointCount points in \a
4775 points using the current pen.
4777 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4779 #ifdef QT_DEBUG_DRAW
4780 if (qt_show_painter_debug_output)
4781 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4785 if (!d->engine || pointCount < 2)
4789 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4793 d->updateState(d->state);
4795 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4797 if (lineEmulation) {
4799 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4800 // && d->state->matrix.type() == QTransform::TxTranslate) {
4802 QPainterPath polylinePath(points[0]);
4803 for (int i=1; i<pointCount; ++i)
4804 polylinePath.lineTo(points[i]);
4805 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4808 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4813 \fn void QPainter::drawPolyline(const QPolygon &polygon, int index, int
4819 Draws the polyline defined by the \a count lines of the given \a
4820 polygon starting at \a index (\a index defaults to 0).
4822 Use drawPolyline() combined with QPolygon::constData() instead.
4825 QPainter painter(this);
4826 painter.drawPolyline(polygon, index, count);
4828 int pointCount = (count == -1) ? polygon.size() - index : count;
4830 QPainter painter(this);
4831 painter.drawPolyline(polygon.constData() + index, pointCount);
4836 \fn void QPainter::drawPolyline(const QPolygonF &points)
4840 Draws the polyline defined by the given \a points using the
4845 \fn void QPainter::drawPolyline(const QPolygon &points)
4849 Draws the polyline defined by the given \a points using the
4854 Draws the polygon defined by the first \a pointCount points in the
4855 array \a points using the current pen and brush.
4859 \o \inlineimage qpainter-polygon.png
4861 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 14
4864 The first point is implicitly connected to the last point, and the
4865 polygon is filled with the current brush().
4867 If \a fillRule is Qt::WindingFill, the polygon is filled using the
4868 winding fill algorithm. If \a fillRule is Qt::OddEvenFill, the
4869 polygon is filled using the odd-even fill algorithm. See
4870 \l{Qt::FillRule} for a more detailed description of these fill
4873 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
4875 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
4877 #ifdef QT_DEBUG_DRAW
4878 if (qt_show_painter_debug_output)
4879 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4884 if (!d->engine || pointCount < 2)
4888 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4892 d->updateState(d->state);
4894 uint emulationSpecifier = d->state->emulationSpecifier;
4896 if (emulationSpecifier) {
4897 QPainterPath polygonPath(points[0]);
4898 for (int i=1; i<pointCount; ++i)
4899 polygonPath.lineTo(points[i]);
4900 polygonPath.closeSubpath();
4901 polygonPath.setFillRule(fillRule);
4902 d->draw_helper(polygonPath);
4906 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4911 Draws the polygon defined by the first \a pointCount points in the
4914 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
4916 #ifdef QT_DEBUG_DRAW
4917 if (qt_show_painter_debug_output)
4918 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4923 if (!d->engine || pointCount < 2)
4927 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4931 d->updateState(d->state);
4933 uint emulationSpecifier = d->state->emulationSpecifier;
4935 if (emulationSpecifier) {
4936 QPainterPath polygonPath(points[0]);
4937 for (int i=1; i<pointCount; ++i)
4938 polygonPath.lineTo(points[i]);
4939 polygonPath.closeSubpath();
4940 polygonPath.setFillRule(fillRule);
4941 d->draw_helper(polygonPath);
4945 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4948 /*! \fn void QPainter::drawPolygon(const QPolygonF &polygon, bool winding, int index = 0,
4953 Use drawPolygon() combined with QPolygonF::constData() instead.
4956 QPainter painter(this);
4957 painter.drawPolygon(polygon, winding, index, count);
4959 int pointCount = (count == -1) ? polygon.size() - index : count;
4960 int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
4962 QPainter painter(this);
4963 painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
4967 /*! \fn void QPainter::drawPolygon(const QPolygon &polygon, bool winding,
4968 int index = 0, int count = -1)
4973 Use drawPolygon() combined with QPolygon::constData() instead.
4976 QPainter painter(this);
4977 painter.drawPolygon(polygon, winding, index, count);
4979 int pointCount = (count == -1) ? polygon.size() - index : count;
4980 int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
4982 QPainter painter(this);
4983 painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
4987 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
4991 Draws the polygon defined by the given \a points using the fill
4995 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
4999 Draws the polygon defined by the given \a points using the fill
5004 \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
5006 Draws the convex polygon defined by the first \a pointCount points
5007 in the array \a points using the current pen.
5011 \o \inlineimage qpainter-polygon.png
5013 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 15
5016 The first point is implicitly connected to the last point, and the
5017 polygon is filled with the current brush(). If the supplied
5018 polygon is not convex, i.e. it contains at least one angle larger
5019 than 180 degrees, the results are undefined.
5021 On some platforms (e.g. X11), the drawConvexPolygon() function can
5022 be faster than the drawPolygon() function.
5024 \sa drawPolygon(), drawPolyline(), {Coordinate System}
5028 \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
5031 Draws the convex polygon defined by the first \a pointCount points
5032 in the array \a points using the current pen.
5036 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
5040 Draws the convex polygon defined by \a polygon using the current
5045 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
5048 Draws the convex polygon defined by \a polygon using the current
5053 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon, int
5059 Use drawConvexPolygon() combined with QPolygonF::constData()
5063 QPainter painter(this);
5064 painter.drawConvexPolygon(polygon, index, count);
5066 int pointCount = (count == -1) ? polygon.size() - index : count;
5068 QPainter painter(this);
5069 painter.drawConvexPolygon(polygon.constData() + index, pointCount);
5074 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon, int
5080 Use drawConvexPolygon() combined with QPolygon::constData()
5084 QPainter painter(this);
5085 painter.drawConvexPolygon(polygon, index, count);
5087 int pointCount = (count == -1) ? polygon.size() - index : count;
5089 QPainter painter(this);
5090 painter.drawConvexPolygon(polygon.constData() + index, pointCount);
5094 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
5096 #ifdef QT_DEBUG_DRAW
5097 if (qt_show_painter_debug_output)
5098 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5103 if (!d->engine || pointCount < 2)
5107 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5111 d->updateState(d->state);
5113 uint emulationSpecifier = d->state->emulationSpecifier;
5115 if (emulationSpecifier) {
5116 QPainterPath polygonPath(points[0]);
5117 for (int i=1; i<pointCount; ++i)
5118 polygonPath.lineTo(points[i]);
5119 polygonPath.closeSubpath();
5120 polygonPath.setFillRule(Qt::WindingFill);
5121 d->draw_helper(polygonPath);
5125 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5128 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
5130 #ifdef QT_DEBUG_DRAW
5131 if (qt_show_painter_debug_output)
5132 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5137 if (!d->engine || pointCount < 2)
5141 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5145 d->updateState(d->state);
5147 uint emulationSpecifier = d->state->emulationSpecifier;
5149 if (emulationSpecifier) {
5150 QPainterPath polygonPath(points[0]);
5151 for (int i=1; i<pointCount; ++i)
5152 polygonPath.lineTo(points[i]);
5153 polygonPath.closeSubpath();
5154 polygonPath.setFillRule(Qt::WindingFill);
5155 d->draw_helper(polygonPath);
5159 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5162 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5164 return m.inverted().map(QPointF(m.map(p).toPoint()));
5168 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5170 Draws the rectangular portion \a source of the given \a pixmap
5171 into the given \a target in the paint device.
5173 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5178 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 16
5181 If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5182 using the pens color. If backgroundMode is Qt::OpaqueMode, the
5183 "unset" bits are drawn using the color of the background brush; if
5184 backgroundMode is Qt::TransparentMode, the "unset" bits are
5185 transparent. Drawing bitmaps with gradient or texture colors is
5190 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5192 #if defined QT_DEBUG_DRAW
5193 if (qt_show_painter_debug_output)
5194 printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5196 pm.width(), pm.height());
5201 if (!d->engine || pm.isNull())
5205 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5209 d->extended->drawPixmap(p, pm);
5217 int h = pm.height();
5222 // Emulate opaque background for bitmaps
5223 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5224 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5227 d->updateState(d->state);
5229 if ((d->state->matrix.type() > QTransform::TxTranslate
5230 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5231 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5232 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5235 // If there is no rotation involved we have to make sure we use the
5236 // antialiased and not the aliased coordinate system by rounding the coordinates.
5237 if (d->state->matrix.type() <= QTransform::TxScale) {
5238 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5243 setBackgroundMode(Qt::TransparentMode);
5244 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5245 QBrush brush(d->state->pen.color(), pm);
5248 setBrushOrigin(QPointF(0, 0));
5250 drawRect(pm.rect());
5253 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5254 x += d->state->matrix.dx();
5255 y += d->state->matrix.dy();
5257 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5261 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5263 #if defined QT_DEBUG_DRAW
5264 if (qt_show_painter_debug_output)
5265 printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5266 r.x(), r.y(), r.width(), r.height(),
5267 pm.width(), pm.height(),
5268 sr.x(), sr.y(), sr.width(), sr.height());
5272 if (!d->engine || pm.isNull())
5275 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5280 qreal w = r.width();
5281 qreal h = r.height();
5284 qreal sw = sr.width();
5285 qreal sh = sr.height();
5287 // Sanity-check clipping
5289 sw = pm.width() - sx;
5292 sh = pm.height() - sy;
5300 qreal w_ratio = sx * w/sw;
5308 qreal h_ratio = sy * h/sh;
5315 if (sw + sx > pm.width()) {
5316 qreal delta = sw - (pm.width() - sx);
5317 qreal w_ratio = delta * w/sw;
5322 if (sh + sy > pm.height()) {
5323 qreal delta = sh - (pm.height() - sy);
5324 qreal h_ratio = delta * h/sh;
5329 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5333 d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5337 // Emulate opaque background for bitmaps
5338 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5339 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5341 d->updateState(d->state);
5343 if ((d->state->matrix.type() > QTransform::TxTranslate
5344 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5345 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5346 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5347 || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5350 // If there is no rotation involved we have to make sure we use the
5351 // antialiased and not the aliased coordinate system by rounding the coordinates.
5352 if (d->state->matrix.type() <= QTransform::TxScale) {
5353 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5358 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5366 scale(w / sw, h / sh);
5367 setBackgroundMode(Qt::TransparentMode);
5368 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5371 if (sw == pm.width() && sh == pm.height())
5372 brush = QBrush(d->state->pen.color(), pm);
5374 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5379 drawRect(QRectF(0, 0, sw, sh));
5382 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5383 x += d->state->matrix.dx();
5384 y += d->state->matrix.dy();
5386 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5392 \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5393 const QRect &source)
5396 Draws the rectangular portion \a source of the given \a pixmap
5397 into the given \a target in the paint device.
5399 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5403 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5404 const QRectF &source)
5407 Draws the rectangular portion \a source of the given \a pixmap
5408 with its origin at the given \a point.
5412 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5413 const QRect &source)
5417 Draws the rectangular portion \a source of the given \a pixmap
5418 with its origin at the given \a point.
5422 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5425 Draws the given \a pixmap with its origin at the given \a point.
5429 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5432 Draws the given \a pixmap with its origin at the given \a point.
5436 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5440 Draws the given \a pixmap at position (\a{x}, \a{y}).
5444 \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5447 Draws the given \a pixmap into the given \a rectangle.
5449 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5453 \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5454 const QPixmap &pixmap)
5458 Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5459 with the given \a width and \a height.
5463 \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5464 int sx, int sy, int sw, int sh)
5468 Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5469 width \a sw and height \a sh, of the given \a pixmap , at the
5470 point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5471 If sw or sh are equal to zero the width/height of the pixmap
5472 is used and adjusted by the offset sx/sy;
5476 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5477 int sx, int sy, int sw, int sh)
5481 Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5482 pixmap into the paint device.
5484 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5485 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5486 pixmap that is to be drawn. The default is (0, 0).
5488 (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5489 The default, (0, 0) (and negative) means all the way to the
5490 bottom-right of the pixmap.
5493 void QPainter::drawImage(const QPointF &p, const QImage &image)
5497 if (!d->engine || image.isNull())
5501 d->extended->drawImage(p, image);
5508 int w = image.width();
5509 int h = image.height();
5511 d->updateState(d->state);
5513 if (((d->state->matrix.type() > QTransform::TxTranslate)
5514 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5515 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5516 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5519 // If there is no rotation involved we have to make sure we use the
5520 // antialiased and not the aliased coordinate system by rounding the coordinates.
5521 if (d->state->matrix.type() <= QTransform::TxScale) {
5522 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5527 setBackgroundMode(Qt::TransparentMode);
5528 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5529 QBrush brush(image);
5532 setBrushOrigin(QPointF(0, 0));
5534 drawRect(image.rect());
5539 if (d->state->matrix.type() == QTransform::TxTranslate
5540 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5541 x += d->state->matrix.dx();
5542 y += d->state->matrix.dy();
5545 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5548 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5549 Qt::ImageConversionFlags flags)
5553 if (!d->engine || image.isNull())
5556 qreal x = targetRect.x();
5557 qreal y = targetRect.y();
5558 qreal w = targetRect.width();
5559 qreal h = targetRect.height();
5560 qreal sx = sourceRect.x();
5561 qreal sy = sourceRect.y();
5562 qreal sw = sourceRect.width();
5563 qreal sh = sourceRect.height();
5565 // Sanity-check clipping
5567 sw = image.width() - sx;
5570 sh = image.height() - sy;
5578 qreal w_ratio = sx * w/sw;
5586 qreal h_ratio = sy * h/sh;
5593 if (sw + sx > image.width()) {
5594 qreal delta = sw - (image.width() - sx);
5595 qreal w_ratio = delta * w/sw;
5600 if (sh + sy > image.height()) {
5601 qreal delta = sh - (image.height() - sy);
5602 qreal h_ratio = delta * h/sh;
5607 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5611 d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5615 d->updateState(d->state);
5617 if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5618 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5619 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5620 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5623 // If there is no rotation involved we have to make sure we use the
5624 // antialiased and not the aliased coordinate system by rounding the coordinates.
5625 if (d->state->matrix.type() <= QTransform::TxScale) {
5626 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5631 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5638 scale(w / sw, h / sh);
5639 setBackgroundMode(Qt::TransparentMode);
5640 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5641 QBrush brush(image);
5644 setBrushOrigin(QPointF(-sx, -sy));
5646 drawRect(QRectF(0, 0, sw, sh));
5651 if (d->state->matrix.type() == QTransform::TxTranslate
5652 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5653 x += d->state->matrix.dx();
5654 y += d->state->matrix.dy();
5657 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5661 Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5662 edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5663 selected on \a glyphs and at offsets given by the positions in \a glyphs.
5667 \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes()
5669 #if !defined(QT_NO_RAWFONT)
5670 void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
5674 QRawFont font = glyphRun.rawFont();
5675 if (!font.isValid())
5678 QGlyphRunPrivate *glyphRun_d = QGlyphRunPrivate::get(glyphRun);
5680 const quint32 *glyphIndexes = glyphRun_d->glyphIndexData;
5681 const QPointF *glyphPositions = glyphRun_d->glyphPositionData;
5683 int count = qMin(glyphRun_d->glyphIndexDataSize, glyphRun_d->glyphPositionDataSize);
5684 QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5686 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5687 bool supportsTransformations;
5688 if (d->extended != 0) {
5689 supportsTransformations = d->extended->supportsTransformations(fontD->fontEngine->fontDef.pixelSize,
5692 supportsTransformations = d->engine->type() == QPaintEngine::CoreGraphics
5693 || d->state->matrix.isAffine();
5696 for (int i=0; i<count; ++i) {
5697 QPointF processedPosition = position + glyphPositions[i];
5698 if (!supportsTransformations)
5699 processedPosition = d->state->transform().map(processedPosition);
5700 fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5703 d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, font, glyphRun.overline(),
5704 glyphRun.underline(), glyphRun.strikeOut());
5707 void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions,
5709 const QRawFont &font, bool overline, bool underline,
5716 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5717 QFontEngine *fontEngine = fontD->fontEngine;
5722 for (int i=0; i<glyphCount; ++i) {
5723 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5724 if (i == 0 || leftMost > positions[i].x)
5725 leftMost = positions[i].x;
5727 // We don't support glyphs that do not share a common baseline. If this turns out to
5728 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5729 // and do a drawTextItemDecorations call per cluster.
5730 if (i == 0 || baseLine < positions[i].y)
5731 baseLine = positions[i].y;
5733 // We use the advance rather than the actual bounds to match the algorithm in drawText()
5734 if (i == 0 || rightMost < positions[i].x + gm.xoff)
5735 rightMost = positions[i].x + gm.xoff;
5738 QFixed width = rightMost - leftMost;
5740 if (extended != 0 && state->matrix.isAffine()) {
5741 QStaticTextItem staticTextItem;
5742 staticTextItem.color = state->pen.color();
5743 staticTextItem.font = state->font;
5744 staticTextItem.setFontEngine(fontEngine);
5745 staticTextItem.numGlyphs = glyphCount;
5746 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5747 staticTextItem.glyphPositions = positions;
5749 extended->drawStaticTextItem(&staticTextItem);
5751 QTextItemInt textItem;
5752 textItem.fontEngine = fontEngine;
5754 QVarLengthArray<QFixed, 128> advances(glyphCount);
5755 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5756 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5757 qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5758 qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
5759 qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5761 textItem.glyphs.numGlyphs = glyphCount;
5762 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5763 textItem.glyphs.offsets = positions;
5764 textItem.glyphs.advances_x = advances.data();
5765 textItem.glyphs.advances_y = advances.data();
5766 textItem.glyphs.justifications = glyphJustifications.data();
5767 textItem.glyphs.attributes = glyphAttributes.data();
5769 engine->drawTextItem(QPointF(0, 0), textItem);
5772 QTextItemInt::RenderFlags flags;
5774 flags |= QTextItemInt::Underline;
5776 flags |= QTextItemInt::Overline;
5778 flags |= QTextItemInt::StrikeOut;
5780 drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5783 ? QTextCharFormat::SingleUnderline
5784 : QTextCharFormat::NoUnderline),
5785 flags, width.toReal(), QTextCharFormat());
5787 #endif // QT_NO_RAWFONT
5791 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5795 Draws the \a staticText at the \a topLeftPosition.
5797 \note The y-position is used as the top of the font.
5802 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5806 Draws the \a staticText at coordinates \a left and \a top.
5808 \note The y-position is used as the top of the font.
5812 \fn void QPainter::drawText(const QPointF &position, const QString &text)
5814 Draws the given \a text with the currently defined text direction,
5815 beginning at the given \a position.
5817 This function does not handle the newline character (\n), as it cannot
5818 break text into multiple lines, and it cannot display the newline character.
5819 Use the QPainter::drawText() overload that takes a rectangle instead
5820 if you want to draw multiple lines of text with the newline character, or
5821 if you want the text to be wrapped.
5823 By default, QPainter draws text anti-aliased.
5825 \note The y-position is used as the baseline of the font.
5828 void QPainter::drawText(const QPointF &p, const QString &str)
5830 drawText(p, str, 0, 0);
5836 Draws the given \a staticText at the given \a topLeftPosition.
5838 The text will be drawn using the font and the transformation set on the painter. If the
5839 font and/or transformation set on the painter are different from the ones used to initialize
5840 the layout of the QStaticText, then the layout will have to be recalculated. Use
5841 QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5842 it will later be drawn.
5844 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5845 last drawn, then there will be a slight overhead when translating the text to its new position.
5847 \note If the painter's transformation is not affine, then \a staticText will be drawn using
5848 regular calls to drawText(), losing any potential for performance improvement.
5850 \note The y-position is used as the top of the font.
5854 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5857 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5860 QStaticTextPrivate *staticText_d =
5861 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5863 if (font() != staticText_d->font) {
5864 staticText_d->font = font();
5865 staticText_d->needsRelayout = true;
5868 // If we don't have an extended paint engine, or if the painter is projected,
5869 // we go through standard code path
5870 if (d->extended == 0 || !d->state->matrix.isAffine()) {
5871 staticText_d->paintText(topLeftPosition, this);
5875 bool supportsTransformations = d->extended->supportsTransformations(staticText_d->font.pixelSize(),
5877 if (supportsTransformations && !staticText_d->untransformedCoordinates) {
5878 staticText_d->untransformedCoordinates = true;
5879 staticText_d->needsRelayout = true;
5880 } else if (!supportsTransformations && staticText_d->untransformedCoordinates) {
5881 staticText_d->untransformedCoordinates = false;
5882 staticText_d->needsRelayout = true;
5885 // Don't recalculate entire layout because of translation, rather add the dx and dy
5886 // into the position to move each text item the correct distance.
5887 QPointF transformedPosition = topLeftPosition;
5888 if (!staticText_d->untransformedCoordinates)
5889 transformedPosition = transformedPosition * d->state->matrix;
5890 QTransform oldMatrix;
5892 // The translation has been applied to transformedPosition. Remove translation
5893 // component from matrix.
5894 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
5895 qreal m11 = d->state->matrix.m11();
5896 qreal m12 = d->state->matrix.m12();
5897 qreal m13 = d->state->matrix.m13();
5898 qreal m21 = d->state->matrix.m21();
5899 qreal m22 = d->state->matrix.m22();
5900 qreal m23 = d->state->matrix.m23();
5901 qreal m33 = d->state->matrix.m33();
5903 oldMatrix = d->state->matrix;
5904 d->state->matrix.setMatrix(m11, m12, m13,
5909 // If the transform is not identical to the text transform,
5910 // we have to relayout the text (for other transformations than plain translation)
5911 bool staticTextNeedsReinit = staticText_d->needsRelayout;
5912 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
5913 staticText_d->matrix = d->state->matrix;
5914 staticTextNeedsReinit = true;
5917 // Recreate the layout of the static text because the matrix or font has changed
5918 if (staticTextNeedsReinit)
5919 staticText_d->init();
5921 if (transformedPosition != staticText_d->position) { // Translate to actual position
5922 QFixed fx = QFixed::fromReal(transformedPosition.x());
5923 QFixed fy = QFixed::fromReal(transformedPosition.y());
5924 QFixed oldX = QFixed::fromReal(staticText_d->position.x());
5925 QFixed oldY = QFixed::fromReal(staticText_d->position.y());
5926 for (int item=0; item<staticText_d->itemCount;++item) {
5927 QStaticTextItem *textItem = staticText_d->items + item;
5928 for (int i=0; i<textItem->numGlyphs; ++i) {
5929 textItem->glyphPositions[i].x += fx - oldX;
5930 textItem->glyphPositions[i].y += fy - oldY;
5932 textItem->userDataNeedsUpdate = true;
5935 staticText_d->position = transformedPosition;
5938 QPen oldPen = d->state->pen;
5939 QColor currentColor = oldPen.color();
5940 for (int i=0; i<staticText_d->itemCount; ++i) {
5941 QStaticTextItem *item = staticText_d->items + i;
5942 if (item->color.isValid() && currentColor != item->color) {
5943 setPen(item->color);
5944 currentColor = item->color;
5946 d->extended->drawStaticTextItem(item);
5948 qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
5949 item->numGlyphs, item->fontEngine(), staticText_d->font,
5952 if (currentColor != oldPen.color())
5955 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
5956 d->state->matrix = oldMatrix;
5962 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
5964 #ifdef QT_DEBUG_DRAW
5965 if (qt_show_painter_debug_output)
5966 printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
5971 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
5974 if (tf & Qt::TextBypassShaping) {
5975 // Skip harfbuzz complex shaping, shape using glyph advances only
5976 int len = str.length();
5977 int numGlyphs = len;
5978 QVarLengthGlyphLayoutArray glyphs(len);
5979 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
5980 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
5981 glyphs.resize(numGlyphs);
5982 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
5983 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
5986 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
5987 drawTextItem(p, gf);
5991 QStackTextEngine engine(str, d->state->font);
5992 engine.option.setTextDirection(d->state->layoutDirection);
5993 if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
5994 engine.ignoreBidi = true;
5995 engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
5999 line.length = str.length();
6000 engine.shapeLine(line);
6002 int nItems = engine.layoutData->items.size();
6003 QVarLengthArray<int> visualOrder(nItems);
6004 QVarLengthArray<uchar> levels(nItems);
6005 for (int i = 0; i < nItems; ++i)
6006 levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
6007 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
6009 if (justificationPadding > 0) {
6010 engine.option.setAlignment(Qt::AlignJustify);
6011 engine.forceJustification = true;
6012 // this works because justify() is only interested in the difference between width and textWidth
6013 line.width = justificationPadding;
6014 engine.justify(line);
6016 QFixed x = QFixed::fromReal(p.x());
6018 for (int i = 0; i < nItems; ++i) {
6019 int item = visualOrder[i];
6020 const QScriptItem &si = engine.layoutData->items.at(item);
6021 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
6025 QFont f = engine.font(si);
6026 QTextItemInt gf(si, &f);
6027 gf.glyphs = engine.shapedGlyphs(&si);
6028 gf.chars = engine.layoutData->string.unicode() + si.position;
6029 gf.num_chars = engine.length(item);
6030 if (engine.forceJustification) {
6031 for (int j=0; j<gf.glyphs.numGlyphs; ++j)
6032 gf.width += gf.glyphs.effectiveAdvance(j);
6034 gf.width = si.width;
6036 gf.logClusters = engine.logClusters(&si);
6038 drawTextItem(QPointF(x.toReal(), p.y()), gf);
6044 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
6046 #ifdef QT_DEBUG_DRAW
6047 if (qt_show_painter_debug_output)
6048 printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
6049 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6054 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6058 d->updateState(d->state);
6061 qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
6063 *br = bounds.toAlignedRect();
6067 \fn void QPainter::drawText(const QPoint &position, const QString &text)
6071 Draws the given \a text with the currently defined text direction,
6072 beginning at the given \a position.
6074 By default, QPainter draws text anti-aliased.
6076 \note The y-position is used as the baseline of the font.
6081 \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
6084 Draws the given \a text within the provided \a rectangle.
6088 \o \inlineimage qpainter-text.png
6090 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 17
6093 The \a boundingRect (if not null) is set to the what the bounding rectangle
6094 should be in order to enclose the whole text. The \a flags argument is a bitwise
6095 OR of the following flags:
6107 \o Qt::TextSingleLine
6108 \o Qt::TextExpandTabs
6109 \o Qt::TextShowMnemonic
6111 \o Qt::TextIncludeTrailingSpaces
6114 \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
6116 By default, QPainter draws text anti-aliased.
6118 \note The y-coordinate of \a rectangle is used as the top of the font.
6120 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
6122 #ifdef QT_DEBUG_DRAW
6123 if (qt_show_painter_debug_output)
6124 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
6125 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6130 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6134 d->updateState(d->state);
6136 qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
6140 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
6143 Draws the given \a text within the provided \a rectangle according
6144 to the specified \a flags. The \a boundingRect (if not null) is set to
6145 the what the bounding rectangle should be in order to enclose the whole text.
6147 By default, QPainter draws text anti-aliased.
6149 \note The y-coordinate of \a rectangle is used as the top of the font.
6153 \fn void QPainter::drawText(int x, int y, const QString &text)
6157 Draws the given \a text at position (\a{x}, \a{y}), using the painter's
6158 currently defined text direction.
6160 By default, QPainter draws text anti-aliased.
6162 \note The y-position is used as the baseline of the font.
6167 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6168 const QString &text, QRect *boundingRect)
6172 Draws the given \a text within the rectangle with origin (\a{x},
6173 \a{y}), \a width and \a height.
6175 The \a boundingRect (if not null) is set to the actual bounding
6176 rectangle of the output. The \a flags argument is a bitwise OR of
6177 the following flags:
6188 \o Qt::TextSingleLine
6189 \o Qt::TextExpandTabs
6190 \o Qt::TextShowMnemonic
6194 By default, QPainter draws text anti-aliased.
6196 \note The y-position is used as the top of the font.
6198 \sa Qt::AlignmentFlag, Qt::TextFlag
6202 \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6203 const QTextOption &option)
6206 Draws the given \a text in the \a rectangle specified using the \a option
6207 to control its positioning and orientation.
6209 By default, QPainter draws text anti-aliased.
6211 \note The y-coordinate of \a rectangle is used as the top of the font.
6213 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6215 #ifdef QT_DEBUG_DRAW
6216 if (qt_show_painter_debug_output)
6217 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6218 r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6223 if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6227 d->updateState(d->state);
6229 qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6233 \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6240 \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6245 Draws the text item \a ti at position \a p.
6249 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6254 Draws the text item \a ti at position \a p.
6256 This method ignores the painters background mode and
6257 color. drawText and qt_format_text have to do it themselves, as
6258 only they know the extents of the complete string.
6260 It ignores the font set on the painter as the text item has one of its own.
6262 The underline and strikeout parameters of the text items font are
6263 ignored aswell. You'll need to pass in the correct flags to get
6264 underlining and strikeout.
6267 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6269 const qreal radiusBase = qMax(qreal(1), maxRadius);
6271 QString key = QLatin1Literal("WaveUnderline-")
6272 % pen.color().name()
6273 % HexString<qreal>(radiusBase);
6276 if (QPixmapCache::find(key, pixmap))
6279 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6280 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6281 const int radius = qFloor(radiusBase);
6288 while (xs < width) {
6291 path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6294 pixmap = QPixmap(width, radius * 2);
6295 pixmap.fill(Qt::transparent);
6298 wavePen.setCapStyle(Qt::SquareCap);
6300 // This is to protect against making the line too fat, as happens on Mac OS X
6301 // due to it having a rather thick width for the regular underline.
6302 const qreal maxPenWidth = .8 * radius;
6303 if (wavePen.widthF() > maxPenWidth)
6304 wavePen.setWidth(maxPenWidth);
6306 QPainter imgPainter(&pixmap);
6307 imgPainter.setPen(wavePen);
6308 imgPainter.setRenderHint(QPainter::Antialiasing);
6309 imgPainter.translate(0, radius);
6310 imgPainter.drawPath(path);
6313 QPixmapCache::insert(key, pixmap);
6318 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
6319 QTextCharFormat::UnderlineStyle underlineStyle,
6320 QTextItem::RenderFlags flags, qreal width,
6321 const QTextCharFormat &charFormat)
6323 if (underlineStyle == QTextCharFormat::NoUnderline
6324 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6327 const QPen oldPen = painter->pen();
6328 const QBrush oldBrush = painter->brush();
6329 painter->setBrush(Qt::NoBrush);
6331 pen.setStyle(Qt::SolidLine);
6332 pen.setWidthF(fe->lineThickness().toReal());
6333 pen.setCapStyle(Qt::FlatCap);
6335 QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6337 const qreal underlineOffset = fe->underlinePosition().toReal();
6338 // deliberately ceil the offset to avoid the underline coming too close to
6339 // the text above it.
6340 const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
6341 const qreal underlinePos = pos.y() + qCeil(underlineOffset) - aliasedCoordinateDelta;
6343 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6344 underlineStyle = QTextCharFormat::SpellCheckUnderline; // ### Qt5 QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle));
6347 if (underlineStyle == QTextCharFormat::WaveUnderline) {
6349 painter->translate(0, pos.y() + 1);
6351 QColor uc = charFormat.underlineColor();
6355 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6356 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6357 const int descent = (int) fe->descent().toReal();
6359 painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6360 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6362 } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6363 QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos);
6365 QColor uc = charFormat.underlineColor();
6369 pen.setStyle((Qt::PenStyle)(underlineStyle));
6370 painter->setPen(pen);
6371 painter->drawLine(underLine);
6374 pen.setStyle(Qt::SolidLine);
6375 pen.setColor(oldPen.color());
6377 if (flags & QTextItem::StrikeOut) {
6378 QLineF strikeOutLine = line;
6379 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6380 painter->setPen(pen);
6381 painter->drawLine(strikeOutLine);
6384 if (flags & QTextItem::Overline) {
6385 QLineF overLine = line;
6386 overLine.translate(0., - fe->ascent().toReal());
6387 painter->setPen(pen);
6388 painter->drawLine(overLine);
6391 painter->setPen(oldPen);
6392 painter->setBrush(oldBrush);
6395 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6396 const QFixedPoint *positions, int glyphCount,
6397 QFontEngine *fontEngine, const QFont &font,
6398 const QTextCharFormat &charFormat)
6400 if (!(font.underline() || font.strikeOut() || font.overline()))
6406 for (int i=0; i<glyphCount; ++i) {
6407 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6408 if (i == 0 || leftMost > positions[i].x)
6409 leftMost = positions[i].x;
6411 // We don't support glyphs that do not share a common baseline. If this turns out to
6412 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6413 // and do a drawTextItemDecorations call per cluster.
6414 if (i == 0 || baseLine < positions[i].y)
6415 baseLine = positions[i].y;
6417 // We use the advance rather than the actual bounds to match the algorithm in drawText()
6418 if (i == 0 || rightMost < positions[i].x + gm.xoff)
6419 rightMost = positions[i].x + gm.xoff;
6422 QFixed width = rightMost - leftMost;
6423 QTextItem::RenderFlags flags = 0;
6425 if (font.underline())
6426 flags |= QTextItem::Underline;
6427 if (font.overline())
6428 flags |= QTextItem::Overline;
6429 if (font.strikeOut())
6430 flags |= QTextItem::StrikeOut;
6432 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6434 font.underline() ? QTextCharFormat::SingleUnderline
6435 : QTextCharFormat::NoUnderline, flags,
6436 width.toReal(), charFormat);
6439 void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
6441 #ifdef QT_DEBUG_DRAW
6442 if (qt_show_painter_debug_output)
6443 printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6444 p.x(), p.y(), qPrintable(_ti.text()));
6453 qt_painter_thread_test(d->device->devType(),
6455 QFontDatabase::supportsThreadedFontRendering());
6458 QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6460 if (!d->extended && d->state->bgMode == Qt::OpaqueMode) {
6461 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6462 fillRect(rect, d->state->bgBrush);
6465 if (pen().style() == Qt::NoPen)
6468 const RenderHints oldRenderHints = d->state->renderHints;
6469 if (!d->state->renderHints & QPainter::Antialiasing && d->state->matrix.type() >= QTransform::TxScale) {
6470 // draw antialias decoration (underline/overline/strikeout) with
6474 const QTransform &m = d->state->matrix;
6475 if (d->state->matrix.type() < QTransform::TxShear) {
6476 bool isPlain90DegreeRotation =
6477 (qFuzzyIsNull(m.m11())
6478 && qFuzzyIsNull(m.m12() - qreal(1))
6479 && qFuzzyIsNull(m.m21() + qreal(1))
6480 && qFuzzyIsNull(m.m22())
6483 (qFuzzyIsNull(m.m11() + qreal(1))
6484 && qFuzzyIsNull(m.m12())
6485 && qFuzzyIsNull(m.m21())
6486 && qFuzzyIsNull(m.m22() + qreal(1))
6489 (qFuzzyIsNull(m.m11())
6490 && qFuzzyIsNull(m.m12() + qreal(1))
6491 && qFuzzyIsNull(m.m21() - qreal(1))
6492 && qFuzzyIsNull(m.m22())
6495 aa = !isPlain90DegreeRotation;
6498 setRenderHint(QPainter::Antialiasing, true);
6502 d->updateState(d->state);
6504 if (!ti.glyphs.numGlyphs) {
6506 } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6507 QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6509 const QGlyphLayout &glyphs = ti.glyphs;
6510 int which = glyphs.glyphs[0] >> 24;
6517 for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6518 const int e = glyphs.glyphs[end] >> 24;
6523 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6525 // set the high byte to zero and calc the width
6526 for (i = start; i < end; ++i) {
6527 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6528 ti2.width += ti.glyphs.effectiveAdvance(i);
6531 d->engine->drawTextItem(QPointF(x, y), ti2);
6533 // reset the high byte for all glyphs and advance to the next sub-string
6534 const int hi = which << 24;
6535 for (i = start; i < end; ++i) {
6536 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6538 x += ti2.width.toReal();
6545 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6547 // set the high byte to zero and calc the width
6548 for (i = start; i < end; ++i) {
6549 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6550 ti2.width += ti.glyphs.effectiveAdvance(i);
6554 d->extended->drawTextItem(QPointF(x, y), ti2);
6556 d->engine->drawTextItem(QPointF(x,y), ti2);
6558 // reset the high byte for all glyphs
6559 const int hi = which << 24;
6560 for (i = start; i < end; ++i)
6561 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6565 d->extended->drawTextItem(p, ti);
6567 d->engine->drawTextItem(p, ti);
6569 drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(),
6572 if (d->state->renderHints != oldRenderHints) {
6573 d->state->renderHints = oldRenderHints;
6575 d->extended->renderHintsChanged();
6577 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
6582 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6584 Returns the bounding rectangle of the \a text as it will appear
6585 when drawn inside the given \a rectangle with the specified \a
6586 flags using the currently set font(); i.e the function tells you
6587 where the drawText() function will draw when given the same
6590 If the \a text does not fit within the given \a rectangle using
6591 the specified \a flags, the function returns the required
6594 The \a flags argument is a bitwise OR of the following flags:
6603 \o Qt::TextSingleLine
6604 \o Qt::TextExpandTabs
6605 \o Qt::TextShowMnemonic
6607 \o Qt::TextIncludeTrailingSpaces
6609 If several of the horizontal or several of the vertical alignment
6610 flags are set, the resulting alignment is undefined.
6612 \sa drawText(), Qt::Alignment, Qt::TextFlag
6616 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6617 const QString &text)
6621 Returns the bounding rectangle of the \a text as it will appear
6622 when drawn inside the given \a rectangle with the specified \a
6623 flags using the currently set font().
6627 \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6628 const QString &text);
6632 Returns the bounding rectangle of the given \a text as it will
6633 appear when drawn inside the rectangle beginning at the point
6634 (\a{x}, \a{y}) with width \a w and height \a h.
6636 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6639 return QRect(rect.x(),rect.y(), 0,0);
6641 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6647 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6650 return QRectF(rect.x(),rect.y(), 0,0);
6652 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6657 \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6658 const QString &text, const QTextOption &option)
6662 Instead of specifying flags as a bitwise OR of the
6663 Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6664 an \a option argument. The QTextOption class provides a
6665 description of general rich text properties.
6669 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6673 if (!d->engine || text.length() == 0)
6674 return QRectF(r.x(),r.y(), 0,0);
6677 qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6682 \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6684 Draws a tiled \a pixmap, inside the given \a rectangle with its
6685 origin at the given \a position.
6687 Calling drawTiledPixmap() is similar to calling drawPixmap()
6688 several times to fill (tile) an area with a pixmap, but is
6689 potentially much more efficient depending on the underlying window
6694 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6696 #ifdef QT_DEBUG_DRAW
6697 if (qt_show_painter_debug_output)
6698 printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6699 r.x(), r.y(), r.width(), r.height(),
6700 pixmap.width(), pixmap.height(),
6705 if (!d->engine || pixmap.isNull() || r.isEmpty())
6709 qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6712 qreal sw = pixmap.width();
6713 qreal sh = pixmap.height();
6717 sx = qRound(sw) - qRound(-sx) % qRound(sw);
6719 sx = qRound(sx) % qRound(sw);
6721 sy = qRound(sh) - -qRound(sy) % qRound(sh);
6723 sy = qRound(sy) % qRound(sh);
6727 d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6731 if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6732 fillRect(r, d->state->bgBrush);
6734 d->updateState(d->state);
6735 if ((d->state->matrix.type() > QTransform::TxTranslate
6736 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6737 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6740 setBackgroundMode(Qt::TransparentMode);
6741 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6742 setBrush(QBrush(d->state->pen.color(), pixmap));
6745 // If there is no rotation involved we have to make sure we use the
6746 // antialiased and not the aliased coordinate system by rounding the coordinates.
6747 if (d->state->matrix.type() <= QTransform::TxScale) {
6748 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6750 if (d->state->matrix.type() <= QTransform::TxTranslate) {
6755 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6756 drawRect(QRectF(p, r.size()));
6758 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6767 if (d->state->matrix.type() == QTransform::TxTranslate
6768 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6769 x += d->state->matrix.dx();
6770 y += d->state->matrix.dy();
6773 d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6777 \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6778 const QPoint &position = QPoint())
6781 Draws a tiled \a pixmap, inside the given \a rectangle with its
6782 origin at the given \a position.
6786 \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6787 QPixmap &pixmap, int sx, int sy);
6790 Draws a tiled \a pixmap in the specified rectangle.
6792 (\a{x}, \a{y}) specifies the top-left point in the paint device
6793 that is to be drawn onto; with the given \a width and \a
6794 height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6795 pixmap that is to be drawn; this defaults to (0, 0).
6798 #ifndef QT_NO_PICTURE
6801 \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6803 Replays the given \a picture at the given \a point.
6805 The QPicture class is a paint device that records and replays
6806 QPainter commands. A picture serializes the painter commands to an
6807 IO device in a platform-independent format. Everything that can be
6808 painted on a widget or pixmap can also be stored in a picture.
6810 This function does exactly the same as QPicture::play() when
6811 called with \a point = QPoint(0, 0).
6816 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 18
6819 \sa QPicture::play()
6822 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6830 d->updateState(d->state);
6834 const_cast<QPicture *>(&picture)->play(this);
6839 \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6842 Replays the given \a picture at the given \a point.
6846 \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6849 Draws the given \a picture at point (\a x, \a y).
6852 #endif // QT_NO_PICTURE
6855 \fn void QPainter::eraseRect(const QRectF &rectangle)
6857 Erases the area inside the given \a rectangle. Equivalent to
6859 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 19
6863 void QPainter::eraseRect(const QRectF &r)
6867 fillRect(r, d->state->bgBrush);
6870 static inline bool needsResolving(const QBrush &brush)
6872 Qt::BrushStyle s = brush.style();
6873 return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
6874 s == Qt::ConicalGradientPattern) &&
6875 brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
6879 \fn void QPainter::eraseRect(const QRect &rectangle)
6882 Erases the area inside the given \a rectangle.
6886 \fn void QPainter::eraseRect(int x, int y, int width, int height)
6889 Erases the area inside the rectangle beginning at (\a x, \a y)
6890 with the given \a width and \a height.
6895 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
6898 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6899 width and \a height, using the brush \a style specified.
6905 \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
6908 Fills the given \a rectangle with the brush \a style specified.
6914 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
6917 Fills the given \a rectangle with the brush \a style specified.
6923 \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
6925 Fills the given \a rectangle with the \a brush specified.
6927 Alternatively, you can specify a QColor instead of a QBrush; the
6928 QBrush constructor (taking a QColor argument) will automatically
6929 create a solid pattern brush.
6933 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
6941 const QGradient *g = brush.gradient();
6942 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6943 d->extended->fillRect(r, brush);
6948 QPen oldPen = pen();
6949 QBrush oldBrush = this->brush();
6951 if (brush.style() == Qt::SolidPattern) {
6952 d->colorBrush.setStyle(Qt::SolidPattern);
6953 d->colorBrush.setColor(brush.color());
6954 setBrush(d->colorBrush);
6965 \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
6968 Fills the given \a rectangle with the specified \a brush.
6971 void QPainter::fillRect(const QRect &r, const QBrush &brush)
6979 const QGradient *g = brush.gradient();
6980 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6981 d->extended->fillRect(r, brush);
6986 QPen oldPen = pen();
6987 QBrush oldBrush = this->brush();
6989 if (brush.style() == Qt::SolidPattern) {
6990 d->colorBrush.setStyle(Qt::SolidPattern);
6991 d->colorBrush.setColor(brush.color());
6992 setBrush(d->colorBrush);
7005 \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
7008 Fills the given \a rectangle with the \a color specified.
7012 void QPainter::fillRect(const QRect &r, const QColor &color)
7020 d->extended->fillRect(r, color);
7024 fillRect(r, QBrush(color));
7029 \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
7032 Fills the given \a rectangle with the \a color specified.
7036 void QPainter::fillRect(const QRectF &r, const QColor &color)
7044 d->extended->fillRect(r, color);
7048 fillRect(r, QBrush(color));
7052 \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
7056 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7057 width and \a height, using the given \a brush.
7061 \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
7065 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7066 width and \a height, using the given \a color.
7072 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
7076 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7077 width and \a height, using the given \a color.
7083 \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
7087 Fills the given \a rectangle with the specified \a color.
7093 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
7097 Fills the given \a rectangle with the specified \a color.
7103 Sets the given render \a hint on the painter if \a on is true;
7104 otherwise clears the render hint.
7106 \sa setRenderHints(), renderHints(), {QPainter#Rendering
7107 Quality}{Rendering Quality}
7109 void QPainter::setRenderHint(RenderHint hint, bool on)
7111 #ifdef QT_DEBUG_DRAW
7112 if (qt_show_painter_debug_output)
7113 printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
7117 static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
7118 if (hint == QPainter::Antialiasing && antialiasingDisabled)
7122 setRenderHints(hint, on);
7128 Sets the given render \a hints on the painter if \a on is true;
7129 otherwise clears the render hints.
7131 \sa setRenderHint(), renderHints(), {QPainter#Rendering
7132 Quality}{Rendering Quality}
7135 void QPainter::setRenderHints(RenderHints hints, bool on)
7140 qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7145 d->state->renderHints |= hints;
7147 d->state->renderHints &= ~hints;
7150 d->extended->renderHintsChanged();
7152 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7156 Returns a flag that specifies the rendering hints that are set for
7159 \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7161 QPainter::RenderHints QPainter::renderHints() const
7163 Q_D(const QPainter);
7168 return d->state->renderHints;
7172 \fn bool QPainter::testRenderHint(RenderHint hint) const
7175 Returns true if \a hint is set; otherwise returns false.
7177 \sa renderHints(), setRenderHint()
7181 Returns true if view transformation is enabled; otherwise returns
7184 \sa setViewTransformEnabled(), worldTransform()
7187 bool QPainter::viewTransformEnabled() const
7189 Q_D(const QPainter);
7191 qWarning("QPainter::viewTransformEnabled: Painter not active");
7194 return d->state->VxF;
7198 \fn void QPainter::setWindow(const QRect &rectangle)
7200 Sets the painter's window to the given \a rectangle, and enables
7201 view transformations.
7203 The window rectangle is part of the view transformation. The
7204 window specifies the logical coordinate system. Its sister, the
7205 viewport(), specifies the device coordinate system.
7207 The default window rectangle is the same as the device's
7210 \sa window(), viewTransformEnabled(), {Coordinate
7211 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7215 \fn void QPainter::setWindow(int x, int y, int width, int height)
7218 Sets the painter's window to the rectangle beginning at (\a x, \a
7219 y) and the given \a width and \a height.
7222 void QPainter::setWindow(const QRect &r)
7224 #ifdef QT_DEBUG_DRAW
7225 if (qt_show_painter_debug_output)
7226 printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7232 qWarning("QPainter::setWindow: Painter not active");
7236 d->state->wx = r.x();
7237 d->state->wy = r.y();
7238 d->state->ww = r.width();
7239 d->state->wh = r.height();
7241 d->state->VxF = true;
7246 Returns the window rectangle.
7248 \sa setWindow(), setViewTransformEnabled()
7251 QRect QPainter::window() const
7253 Q_D(const QPainter);
7255 qWarning("QPainter::window: Painter not active");
7258 return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7262 \fn void QPainter::setViewport(const QRect &rectangle)
7264 Sets the painter's viewport rectangle to the given \a rectangle,
7265 and enables view transformations.
7267 The viewport rectangle is part of the view transformation. The
7268 viewport specifies the device coordinate system. Its sister, the
7269 window(), specifies the logical coordinate system.
7271 The default viewport rectangle is the same as the device's
7274 \sa viewport(), viewTransformEnabled() {Coordinate
7275 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7279 \fn void QPainter::setViewport(int x, int y, int width, int height)
7282 Sets the painter's viewport rectangle to be the rectangle
7283 beginning at (\a x, \a y) with the given \a width and \a height.
7286 void QPainter::setViewport(const QRect &r)
7288 #ifdef QT_DEBUG_DRAW
7289 if (qt_show_painter_debug_output)
7290 printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7296 qWarning("QPainter::setViewport: Painter not active");
7300 d->state->vx = r.x();
7301 d->state->vy = r.y();
7302 d->state->vw = r.width();
7303 d->state->vh = r.height();
7305 d->state->VxF = true;
7310 Returns the viewport rectangle.
7312 \sa setViewport(), setViewTransformEnabled()
7315 QRect QPainter::viewport() const
7317 Q_D(const QPainter);
7319 qWarning("QPainter::viewport: Painter not active");
7322 return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7325 /*! \fn bool QPainter::hasViewXForm() const
7328 Use viewTransformEnabled() instead.
7331 /*! \fn bool QPainter::hasWorldXForm() const
7334 Use worldMatrixEnabled() instead.
7337 /*! \fn void QPainter::resetXForm()
7340 Use resetTransform() instead.
7343 /*! \fn void QPainter::setViewXForm(bool enabled)
7346 Use setViewTransformEnabled() instead.
7349 /*! \fn void QPainter::setWorldXForm(bool enabled)
7352 Use setWorldMatrixEnabled() instead.
7355 Enables view transformations if \a enable is true, or disables
7356 view transformations if \a enable is false.
7358 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7359 Conversion}{Window-Viewport Conversion}
7362 void QPainter::setViewTransformEnabled(bool enable)
7364 #ifdef QT_DEBUG_DRAW
7365 if (qt_show_painter_debug_output)
7366 printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7372 qWarning("QPainter::setViewTransformEnabled: Painter not active");
7376 if (enable == d->state->VxF)
7379 d->state->VxF = enable;
7388 Please use QWidget::render() instead.
7390 Redirects all paint commands for the given paint \a device, to the
7391 \a replacement device. The optional point \a offset defines an
7392 offset within the source device.
7394 The redirection will not be effective until the begin() function
7395 has been called; make sure to call end() for the given \a
7396 device's painter (if any) before redirecting. Call
7397 restoreRedirected() to restore the previous redirection.
7399 \warning Making use of redirections in the QPainter API implies
7400 that QPainter::begin() and QPaintDevice destructors need to hold
7401 a mutex for a short period. This can impact performance. Use of
7402 QWidget::render is strongly encouraged.
7404 \sa redirected(), restoreRedirected()
7406 void QPainter::setRedirected(const QPaintDevice *device,
7407 QPaintDevice *replacement,
7408 const QPoint &offset)
7410 Q_ASSERT(device != 0);
7412 qWarning() << "QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead";
7420 Using QWidget::render() obsoletes the use of this function.
7422 Restores the previous redirection for the given \a device after a
7423 call to setRedirected().
7425 \warning Making use of redirections in the QPainter API implies
7426 that QPainter::begin() and QPaintDevice destructors need to hold
7427 a mutex for a short period. This can impact performance. Use of
7428 QWidget::render is strongly encouraged.
7432 void QPainter::restoreRedirected(const QPaintDevice *device)
7434 qWarning() << "QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead";
7442 Using QWidget::render() obsoletes the use of this function.
7444 Returns the replacement for given \a device. The optional out
7445 parameter \a offset returns the offset within the replaced device.
7447 \warning Making use of redirections in the QPainter API implies
7448 that QPainter::begin() and QPaintDevice destructors need to hold
7449 a mutex for a short period. This can impact performance. Use of
7450 QWidget::render is strongly encouraged.
7452 \sa setRedirected(), restoreRedirected()
7454 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7459 void qt_format_text(const QFont &fnt, const QRectF &_r,
7460 int tf, const QString& str, QRectF *brect,
7461 int tabstops, int *ta, int tabarraylen,
7464 qt_format_text(fnt, _r,
7466 tabstops, ta, tabarraylen,
7469 void qt_format_text(const QFont &fnt, const QRectF &_r,
7470 int tf, const QTextOption *option, const QString& str, QRectF *brect,
7471 int tabstops, int *ta, int tabarraylen,
7475 Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
7478 tf |= option->alignment();
7479 if (option->wrapMode() != QTextOption::NoWrap)
7480 tf |= Qt::TextWordWrap;
7482 if (option->flags() & QTextOption::IncludeTrailingSpaces)
7483 tf |= Qt::TextIncludeTrailingSpaces;
7485 if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
7486 tf |= Qt::TextExpandTabs;
7489 // we need to copy r here to protect against the case (&r == brect).
7492 bool dontclip = (tf & Qt::TextDontClip);
7493 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
7494 bool singleline = (tf & Qt::TextSingleLine);
7495 bool showmnemonic = (tf & Qt::TextShowMnemonic);
7496 bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
7498 Qt::LayoutDirection layout_direction;
7499 if (tf & Qt::TextForceLeftToRight)
7500 layout_direction = Qt::LeftToRight;
7501 else if (tf & Qt::TextForceRightToLeft)
7502 layout_direction = Qt::RightToLeft;
7504 layout_direction = option->textDirection();
7506 layout_direction = painter->layoutDirection();
7508 layout_direction = Qt::LeftToRight;
7510 tf = QGuiApplicationPrivate::visualAlignment(layout_direction, QFlag(tf));
7512 bool isRightToLeft = layout_direction == Qt::RightToLeft;
7513 bool expandtabs = ((tf & Qt::TextExpandTabs) &&
7514 (((tf & Qt::AlignLeft) && !isRightToLeft) ||
7515 ((tf & Qt::AlignRight) && isRightToLeft)));
7518 tf |= Qt::TextDontPrint;
7520 uint maxUnderlines = 0;
7521 int numUnderlines = 0;
7522 QVarLengthArray<int, 32> underlinePositions(1);
7524 QFontMetricsF fm(fnt);
7527 start_lengthVariant:
7528 bool hasMoreLengthVariants = false;
7529 // compatible behaviour to the old implementation. Replace
7531 int old_offset = offset;
7532 for (; offset < text.length(); offset++) {
7533 QChar chr = text.at(offset);
7534 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
7535 text[offset] = QLatin1Char(' ');
7536 } else if (chr == QLatin1Char('\n')) {
7537 text[offset] = QChar::LineSeparator;
7538 } else if (chr == QLatin1Char('&')) {
7540 } else if (chr == QLatin1Char('\t')) {
7542 text[offset] = QLatin1Char(' ');
7543 } else if (!tabarraylen && !tabstops) {
7544 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
7546 } else if (chr == QChar(ushort(0x9c))) {
7547 // string with multiple length variants
7548 hasMoreLengthVariants = true;
7553 int length = offset - old_offset;
7554 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
7555 underlinePositions.resize(maxUnderlines + 1);
7557 QChar *cout = text.data() + old_offset;
7561 if (*cin == QLatin1Char('&')) {
7567 if (*cin != QLatin1Char('&') && !hidemnmemonic)
7568 underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
7577 // no need to do extra work for underlines if we don't paint
7578 if (tf & Qt::TextDontPrint)
7581 underlinePositions[numUnderlines] = -1;
7585 QString finalText = text.mid(old_offset, length);
7586 QStackTextEngine engine(finalText, fnt);
7588 engine.option = *option;
7591 if (engine.option.tabStop() < 0 && tabstops > 0)
7592 engine.option.setTabStop(tabstops);
7594 if (engine.option.tabs().isEmpty() && ta) {
7596 for (int i = 0; i < tabarraylen; i++)
7597 tabs.append(qreal(ta[i]));
7598 engine.option.setTabArray(tabs);
7601 engine.option.setTextDirection(layout_direction);
7602 if (tf & Qt::AlignJustify)
7603 engine.option.setAlignment(Qt::AlignJustify);
7605 engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
7607 if (!option && (tf & Qt::TextWrapAnywhere))
7608 engine.option.setWrapMode(QTextOption::WrapAnywhere);
7610 if (tf & Qt::TextJustificationForced)
7611 engine.forceJustification = true;
7612 QTextLayout textLayout(&engine);
7613 textLayout.setCacheEnabled(true);
7614 textLayout.engine()->underlinePositions = underlinePositions.data();
7616 if (finalText.isEmpty()) {
7617 height = fm.height();
7619 tf |= Qt::TextDontPrint;
7621 qreal lineWidth = 0x01000000;
7622 if (wordwrap || (tf & Qt::TextJustificationForced))
7623 lineWidth = qMax<qreal>(0, r.width());
7625 tf |= Qt::TextIncludeTrailingSpaces;
7626 textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
7627 textLayout.beginLayout();
7629 qreal leading = fm.leading();
7633 QTextLine l = textLayout.createLine();
7637 l.setLineWidth(lineWidth);
7639 l.setPosition(QPointF(0., height));
7640 height += l.height();
7641 width = qMax(width, l.naturalTextWidth());
7642 if (!dontclip && !brect && height >= r.height())
7645 textLayout.endLayout();
7650 if (tf & Qt::AlignBottom) {
7651 yoff = r.height() - height;
7652 } else if (tf & Qt::AlignVCenter) {
7653 yoff = (r.height() - height)/2;
7655 QTransform::TransformationType type = painter->transform().type();
7656 if (type <= QTransform::TxScale) {
7657 // do the rounding manually to work around inconsistencies
7658 // in the paint engines when drawing on floating point offsets
7659 const qreal scale = painter->transform().m22();
7661 yoff = -qRound(-yoff * scale) / scale;
7665 if (tf & Qt::AlignRight) {
7666 xoff = r.width() - width;
7667 } else if (tf & Qt::AlignHCenter) {
7668 xoff = (r.width() - width)/2;
7670 QTransform::TransformationType type = painter->transform().type();
7671 if (type <= QTransform::TxScale) {
7672 // do the rounding manually to work around inconsistencies
7673 // in the paint engines when drawing on floating point offsets
7674 const qreal scale = painter->transform().m11();
7676 xoff = qRound(xoff * scale) / scale;
7680 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
7682 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
7684 goto start_lengthVariant;
7689 if (!(tf & Qt::TextDontPrint)) {
7690 bool restore = false;
7691 if (!dontclip && !r.contains(bounds)) {
7694 painter->setClipRect(r, Qt::IntersectClip);
7697 for (int i = 0; i < textLayout.lineCount(); i++) {
7698 QTextLine line = textLayout.lineAt(i);
7700 qreal advance = line.horizontalAdvance();
7702 if (tf & Qt::AlignRight) {
7703 QTextEngine *eng = textLayout.engine();
7704 xoff = r.width() - advance -
7705 eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
7707 else if (tf & Qt::AlignHCenter)
7708 xoff = (r.width() - advance) / 2;
7710 line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
7720 Sets the layout direction used by the painter when drawing text,
7721 to the specified \a direction.
7723 The default is Qt::LayoutDirectionAuto, which will implicitly determine the
7724 direction from the text drawn.
7726 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
7728 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
7732 d->state->layoutDirection = direction;
7736 Returns the layout direction used by the painter when drawing text.
7738 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
7740 Qt::LayoutDirection QPainter::layoutDirection() const
7742 Q_D(const QPainter);
7743 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
7746 QPainterState::QPainterState(const QPainterState *s)
7747 : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
7748 pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
7749 clipRegion(s->clipRegion), clipPath(s->clipPath),
7750 clipOperation(s->clipOperation),
7751 renderHints(s->renderHints), clipInfo(s->clipInfo),
7752 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
7753 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
7754 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
7755 opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
7756 clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
7757 layoutDirection(s->layoutDirection),
7758 composition_mode(s->composition_mode),
7759 emulationSpecifier(s->emulationSpecifier), changeFlags(0)
7761 dirtyFlags = s->dirtyFlags;
7764 QPainterState::QPainterState()
7765 : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
7767 wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
7768 opacity(1), WxF(false), VxF(false), clipEnabled(true),
7769 bgMode(Qt::TransparentMode), painter(0),
7770 layoutDirection(QGuiApplication::layoutDirection()),
7771 composition_mode(QPainter::CompositionMode_SourceOver),
7772 emulationSpecifier(0), changeFlags(0)
7777 QPainterState::~QPainterState()
7781 void QPainterState::init(QPainter *p) {
7782 bgBrush = Qt::white;
7783 bgMode = Qt::TransparentMode;
7787 wx = wy = ww = wh = 0;
7788 vx = vy = vw = vh = 0;
7791 brushOrigin = QPointF(0, 0);
7793 font = deviceFont = QFont();
7794 clipRegion = QRegion();
7795 clipPath = QPainterPath();
7796 clipOperation = Qt::NoClip;
7798 worldMatrix.reset();
7800 layoutDirection = QGuiApplication::layoutDirection();
7801 composition_mode = QPainter::CompositionMode_SourceOver;
7802 emulationSpecifier = 0;
7810 \fn void QPainter::setBackgroundColor(const QColor &color)
7812 Use setBackground() instead.
7816 \fn const QColor &QPainter::backgroundColor() const
7818 Use background() and QBrush::color() instead.
7821 QColor myColor = backgroundColor();
7823 QColor myColor = background().color();
7826 Note that the background can be a complex brush such as a texture
7831 \fn void QPainter::drawText(int x, int y, const QString &text, int pos, int length)
7834 Use drawText() combined with QString::mid() instead.
7837 QPainter painter(this);
7838 painter.drawText(x, y, text, pos, length);
7840 QPainter painter(this);
7841 painter.drawText(x, y, text.mid(pos, length));
7846 \fn void QPainter::drawText(const QPoint &point, const QString &text, int pos, int length)
7849 Use drawText() combined with QString::mid() instead.
7852 QPainter painter(this);
7853 painter.drawText(point, text, pos, length);
7855 QPainter painter(this);
7856 painter.drawText(point, text.mid(pos, length));
7861 \fn void QPainter::drawText(int x, int y, const QString &text, int length)
7864 Use drawText() combined with QString::left() instead.
7867 QPainter painter(this);
7868 painter.drawText(x, y, text, length);
7870 QPainter painter(this);
7871 painter.drawText(x, y, text.left(length));
7876 \fn void QPainter::drawText(const QPoint &point, const QString &text, int length)
7879 Use drawText() combined with QString::left() instead.
7882 QPainter painter(this);
7883 painter.drawText(point, text, length);
7885 QPainter painter(this);
7886 painter.drawText(point, text.left(length));
7891 \fn bool QPainter::begin(QPaintDevice *device, const QWidget *init)
7894 Use begin() instead.
7896 If the paint \a device is a QWidget, QPainter is initialized after
7897 the widget's settings automatically. Otherwise, you must call the
7898 initFrom() function to initialize the painters pen, background and
7899 font to the same as any given widget.
7902 QPainter painter(this);
7903 painter.begin(device, init);
7905 QPainter painter(this);
7906 painter.begin(device);
7907 painter.initFrom(init);
7912 \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
7913 Qt::ImageConversionFlags flags)
7915 Draws the rectangular portion \a source of the given \a image
7916 into the \a target rectangle in the paint device.
7918 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7920 If the image needs to be modified to fit in a lower-resolution
7921 result (e.g. converting from 32-bit to 8-bit), use the \a flags to
7922 specify how you would prefer this to happen.
7927 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 20
7934 \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
7935 Qt::ImageConversionFlags flags)
7938 Draws the rectangular portion \a source of the given \a image
7939 into the \a target rectangle in the paint device.
7941 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7945 \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
7949 Draws the given \a image at the given \a point.
7953 \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
7957 Draws the given \a image at the given \a point.
7961 \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
7962 Qt::ImageConversionFlags flags = 0)
7966 Draws the rectangular portion \a source of the given \a image with
7967 its origin at the given \a point.
7971 \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
7972 Qt::ImageConversionFlags flags = 0)
7975 Draws the rectangular portion \a source of the given \a image with
7976 its origin at the given \a point.
7980 \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
7984 Draws the given \a image into the given \a rectangle.
7986 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7990 \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
7994 Draws the given \a image into the given \a rectangle.
7996 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8000 \fn void QPainter::drawImage(int x, int y, const QImage &image,
8001 int sx, int sy, int sw, int sh,
8002 Qt::ImageConversionFlags flags)
8005 Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
8008 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
8009 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
8010 image that is to be drawn. The default is (0, 0).
8012 (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
8013 The default, (0, 0) (and negative) means all the way to the
8014 bottom-right of the image.
8018 \fn void QPainter::redirect(QPaintDevice *pdev, QPaintDevice *replacement)
8020 Use setRedirected() instead.
8024 \fn QPaintDevice *QPainter::redirect(QPaintDevice *pdev)
8026 Use redirected() instead.
8030 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
8031 const QString &text, int length)
8034 Returns the bounding rectangle for the given \a length of the \a
8035 text constrained by the provided \a rectangle.
8037 Use boundingRect() combined with QString::left() instead.
8040 QRect rectangle = boundingRect(rect, flags, text, length);
8042 QRect rectangle = boundingRect(rect, flags, text.left(length));
8047 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text,
8048 int length, QRect *br)
8051 Use drawText() combined with QString::left() instead.
8054 QPainter painter(this);
8055 painter.drawText(rectangle, flags, text, length, br );
8057 QPainter painter(this);
8058 painter.drawText(rectangle, flags, text.left(length), br );
8063 \fn QRect QPainter::boundingRect(int x, int y, int width, int height, int flags,
8064 const QString &text, int length);
8068 Returns the bounding rectangle for the given \a length of the \a
8069 text constrained by the rectangle that begins at point (\a{x},
8070 \a{y}) with the given \a width and \a height.
8072 Use boundingRect() combined with QString::left() instead.
8075 QRect rectangle = boundingRect(x, y, width, height, flags, text, length);
8077 QRect rectangle = boundingRect(x, y, width, height, flags, text.left(length));
8082 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
8083 const QString &text, int length, QRect *br)
8087 Use drawText() combined with QString::left() instead.
8090 QPainter painter(this);
8091 painter.drawText(x, y, width, height, flags, text, length, br );
8093 QPainter painter(this);
8094 painter.drawText(x, y, width, height, flags, text.left(length), br );
8100 \class QPaintEngineState
8103 \brief The QPaintEngineState class provides information about the
8104 active paint engine's current state.
8107 QPaintEngineState records which properties that have changed since
8108 the last time the paint engine was updated, as well as their
8111 Which properties that have changed can at any time be retrieved
8112 using the state() function. This function returns an instance of
8113 the QPaintEngine::DirtyFlags type which stores an OR combination
8114 of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
8115 enum defines whether a property has changed since the last update
8118 If a property is marked with a dirty flag, its current value can
8119 be retrieved using the corresponding get function:
8124 \header \o Property Flag \o Current Property Value
8125 \row \o QPaintEngine::DirtyBackground \o backgroundBrush()
8126 \row \o QPaintEngine::DirtyBackgroundMode \o backgroundMode()
8127 \row \o QPaintEngine::DirtyBrush \o brush()
8128 \row \o QPaintEngine::DirtyBrushOrigin \o brushOrigin()
8129 \row \o QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
8131 \row \o QPaintEngine::DirtyClipPath \o clipPath()
8132 \row \o QPaintEngine::DirtyClipRegion \o clipRegion()
8133 \row \o QPaintEngine::DirtyCompositionMode \o compositionMode()
8134 \row \o QPaintEngine::DirtyFont \o font()
8135 \row \o QPaintEngine::DirtyTransform \o transform()
8136 \row \o QPaintEngine::DirtyClipEnabled \o isClipEnabled()
8137 \row \o QPaintEngine::DirtyPen \o pen()
8138 \row \o QPaintEngine::DirtyHints \o renderHints()
8141 The QPaintEngineState class also provide the painter() function
8142 which returns a pointer to the painter that is currently updating
8145 An instance of this class, representing the current state of the
8146 active paint engine, is passed as argument to the
8147 QPaintEngine::updateState() function. The only situation in which
8148 you will have to use this class directly is when implementing your
8156 \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
8158 Returns a combination of flags identifying the set of properties
8159 that need to be updated when updating the paint engine's state
8160 (i.e. during a call to the QPaintEngine::updateState() function).
8162 \sa QPaintEngine::updateState()
8167 Returns the pen in the current paint engine state.
8169 This variable should only be used when the state() returns a
8170 combination which includes the QPaintEngine::DirtyPen flag.
8172 \sa state(), QPaintEngine::updateState()
8175 QPen QPaintEngineState::pen() const
8177 return static_cast<const QPainterState *>(this)->pen;
8181 Returns the brush in the current paint engine state.
8183 This variable should only be used when the state() returns a
8184 combination which includes the QPaintEngine::DirtyBrush flag.
8186 \sa state(), QPaintEngine::updateState()
8189 QBrush QPaintEngineState::brush() const
8191 return static_cast<const QPainterState *>(this)->brush;
8195 Returns the brush origin in the current paint engine state.
8197 This variable should only be used when the state() returns a
8198 combination which includes the QPaintEngine::DirtyBrushOrigin flag.
8200 \sa state(), QPaintEngine::updateState()
8203 QPointF QPaintEngineState::brushOrigin() const
8205 return static_cast<const QPainterState *>(this)->brushOrigin;
8209 Returns the background brush in the current paint engine state.
8211 This variable should only be used when the state() returns a
8212 combination which includes the QPaintEngine::DirtyBackground flag.
8214 \sa state(), QPaintEngine::updateState()
8217 QBrush QPaintEngineState::backgroundBrush() const
8219 return static_cast<const QPainterState *>(this)->bgBrush;
8223 Returns the background mode in the current paint engine
8226 This variable should only be used when the state() returns a
8227 combination which includes the QPaintEngine::DirtyBackgroundMode flag.
8229 \sa state(), QPaintEngine::updateState()
8232 Qt::BGMode QPaintEngineState::backgroundMode() const
8234 return static_cast<const QPainterState *>(this)->bgMode;
8238 Returns the font in the current paint engine
8241 This variable should only be used when the state() returns a
8242 combination which includes the QPaintEngine::DirtyFont flag.
8244 \sa state(), QPaintEngine::updateState()
8247 QFont QPaintEngineState::font() const
8249 return static_cast<const QPainterState *>(this)->font;
8256 Returns the matrix in the current paint engine
8259 \note It is advisable to use transform() instead of this function to
8260 preserve the properties of perspective transformations.
8262 This variable should only be used when the state() returns a
8263 combination which includes the QPaintEngine::DirtyTransform flag.
8265 \sa state(), QPaintEngine::updateState()
8268 QMatrix QPaintEngineState::matrix() const
8270 const QPainterState *st = static_cast<const QPainterState *>(this);
8272 return st->matrix.toAffine();
8278 Returns the matrix in the current paint engine state.
8280 This variable should only be used when the state() returns a
8281 combination which includes the QPaintEngine::DirtyTransform flag.
8283 \sa state(), QPaintEngine::updateState()
8287 QTransform QPaintEngineState::transform() const
8289 const QPainterState *st = static_cast<const QPainterState *>(this);
8296 Returns the clip operation in the current paint engine
8299 This variable should only be used when the state() returns a
8300 combination which includes either the QPaintEngine::DirtyClipPath
8301 or the QPaintEngine::DirtyClipRegion flag.
8303 \sa state(), QPaintEngine::updateState()
8306 Qt::ClipOperation QPaintEngineState::clipOperation() const
8308 return static_cast<const QPainterState *>(this)->clipOperation;
8314 Returns whether the coordinate of the fill have been specified
8315 as bounded by the current rendering operation and have to be
8316 resolved (about the currently rendered primitive).
8318 bool QPaintEngineState::brushNeedsResolving() const
8320 const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
8321 return needsResolving(brush);
8328 Returns whether the coordinate of the stroke have been specified
8329 as bounded by the current rendering operation and have to be
8330 resolved (about the currently rendered primitive).
8332 bool QPaintEngineState::penNeedsResolving() const
8334 const QPen &pen = static_cast<const QPainterState *>(this)->pen;
8335 return needsResolving(pen.brush());
8339 Returns the clip region in the current paint engine state.
8341 This variable should only be used when the state() returns a
8342 combination which includes the QPaintEngine::DirtyClipRegion flag.
8344 \sa state(), QPaintEngine::updateState()
8347 QRegion QPaintEngineState::clipRegion() const
8349 return static_cast<const QPainterState *>(this)->clipRegion;
8353 Returns the clip path in the current paint engine state.
8355 This variable should only be used when the state() returns a
8356 combination which includes the QPaintEngine::DirtyClipPath flag.
8358 \sa state(), QPaintEngine::updateState()
8361 QPainterPath QPaintEngineState::clipPath() const
8363 return static_cast<const QPainterState *>(this)->clipPath;
8367 Returns whether clipping is enabled or not in the current paint
8370 This variable should only be used when the state() returns a
8371 combination which includes the QPaintEngine::DirtyClipEnabled
8374 \sa state(), QPaintEngine::updateState()
8377 bool QPaintEngineState::isClipEnabled() const
8379 return static_cast<const QPainterState *>(this)->clipEnabled;
8383 Returns the render hints in the current paint engine state.
8385 This variable should only be used when the state() returns a
8386 combination which includes the QPaintEngine::DirtyHints
8389 \sa state(), QPaintEngine::updateState()
8392 QPainter::RenderHints QPaintEngineState::renderHints() const
8394 return static_cast<const QPainterState *>(this)->renderHints;
8398 Returns the composition mode in the current paint engine state.
8400 This variable should only be used when the state() returns a
8401 combination which includes the QPaintEngine::DirtyCompositionMode
8404 \sa state(), QPaintEngine::updateState()
8407 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8409 return static_cast<const QPainterState *>(this)->composition_mode;
8414 Returns a pointer to the painter currently updating the paint
8418 QPainter *QPaintEngineState::painter() const
8420 return static_cast<const QPainterState *>(this)->painter;
8427 Returns the opacity in the current paint engine state.
8430 qreal QPaintEngineState::opacity() const
8432 return static_cast<const QPainterState *>(this)->opacity;
8438 Sets the world transformation matrix.
8439 If \a combine is true, the specified \a transform is combined with
8440 the current matrix; otherwise it replaces the current matrix.
8442 \sa transform() setWorldTransform()
8445 void QPainter::setTransform(const QTransform &transform, bool combine )
8447 setWorldTransform(transform, combine);
8451 Returns the world transformation matrix.
8453 \sa worldTransform()
8456 const QTransform & QPainter::transform() const
8458 return worldTransform();
8463 Returns the matrix that transforms from logical coordinates to
8464 device coordinates of the platform dependent paint device.
8466 This function is \e only needed when using platform painting
8467 commands on the platform dependent handle (Qt::HANDLE), and the
8468 platform does not do transformations nativly.
8470 The QPaintEngine::PaintEngineFeature enum can be queried to
8471 determine whether the platform performs the transformations or
8474 \sa worldTransform(), QPaintEngine::hasFeature(),
8477 const QTransform & QPainter::deviceTransform() const
8479 Q_D(const QPainter);
8481 qWarning("QPainter::deviceTransform: Painter not active");
8482 return d->fakeState()->transform;
8484 return d->state->matrix;
8489 Resets any transformations that were made using translate(),
8490 scale(), shear(), rotate(), setWorldTransform(), setViewport()
8493 \sa {Coordinate Transformations}
8496 void QPainter::resetTransform()
8499 #ifdef QT_DEBUG_DRAW
8500 if (qt_show_painter_debug_output)
8501 printf("QPainter::resetMatrix()\n");
8504 qWarning("QPainter::resetMatrix: Painter not active");
8508 d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins
8509 d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
8510 d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
8511 d->state->worldMatrix = QTransform();
8512 setMatrixEnabled(false);
8513 setViewTransformEnabled(false);
8515 d->extended->transformChanged();
8517 d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
8521 Sets the world transformation matrix.
8522 If \a combine is true, the specified \a matrix is combined with the current matrix;
8523 otherwise it replaces the current matrix.
8525 \sa transform(), setTransform()
8528 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
8533 qWarning("QPainter::setWorldTransform: Painter not active");
8538 d->state->worldMatrix = matrix * d->state->worldMatrix; // combines
8540 d->state->worldMatrix = matrix; // set new matrix
8542 d->state->WxF = true;
8547 Returns the world transformation matrix.
8550 const QTransform & QPainter::worldTransform() const
8552 Q_D(const QPainter);
8554 qWarning("QPainter::worldTransform: Painter not active");
8555 return d->fakeState()->transform;
8557 return d->state->worldMatrix;
8561 Returns the transformation matrix combining the current
8562 window/viewport and world transformation.
8564 \sa setWorldTransform(), setWindow(), setViewport()
8567 QTransform QPainter::combinedTransform() const
8569 Q_D(const QPainter);
8571 qWarning("QPainter::combinedTransform: Painter not active");
8572 return QTransform();
8574 return d->state->worldMatrix * d->viewTransform();
8580 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
8581 at multiple positions with different scale, rotation and opacity. \a
8582 fragments is an array of \a fragmentCount elements specifying the
8583 parameters used to draw each pixmap fragment. The \a hints
8584 parameter can be used to pass in drawing hints.
8586 This function is potentially faster than multiple calls to drawPixmap(),
8587 since the backend can optimize state changes.
8589 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
8592 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
8593 const QPixmap &pixmap, PixmapFragmentHints hints)
8597 if (!d->engine || pixmap.isNull())
8601 for (int i = 0; i < fragmentCount; ++i) {
8602 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8603 fragments[i].width, fragments[i].height);
8604 if (!(QRectF(pixmap.rect()).contains(sourceRect)))
8605 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
8609 if (d->engine->isExtended()) {
8610 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
8612 qreal oldOpacity = opacity();
8613 QTransform oldTransform = transform();
8615 for (int i = 0; i < fragmentCount; ++i) {
8616 QTransform transform = oldTransform;
8619 if (fragments[i].rotation == 0) {
8620 xOffset = fragments[i].x;
8621 yOffset = fragments[i].y;
8623 transform.translate(fragments[i].x, fragments[i].y);
8624 transform.rotate(fragments[i].rotation);
8626 setOpacity(oldOpacity * fragments[i].opacity);
8627 setTransform(transform);
8629 qreal w = fragments[i].scaleX * fragments[i].width;
8630 qreal h = fragments[i].scaleY * fragments[i].height;
8631 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8632 fragments[i].width, fragments[i].height);
8633 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
8636 setOpacity(oldOpacity);
8637 setTransform(oldTransform);
8643 \class QPainter::PixmapFragment
8645 \brief This class is used in conjunction with the
8646 QPainter::drawPixmapFragments() function to specify how a pixmap, or
8647 sub-rect of a pixmap, is drawn.
8649 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
8650 as a source rectangle within the pixmap passed into the
8651 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
8652 width and \a height are used to calculate the target rectangle that is
8653 drawn. \a x and \a y denotes the center of the target rectangle. The \a
8654 width and \a height in the target rectangle is scaled by the \a scaleX and
8655 \a scaleY values. The resulting target rectangle is then rotated \a
8656 rotation degrees around the \a x, \a y center point.
8658 \sa QPainter::drawPixmapFragments()
8664 This is a convenience function that returns a QPainter::PixmapFragment that is
8665 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
8666 rotation, \a opacity parameters.
8669 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
8670 qreal scaleX, qreal scaleY, qreal rotation,
8673 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
8674 sourceRect.height(), scaleX, scaleY, rotation, opacity};
8679 \variable QPainter::PixmapFragment::x
8680 \brief the x coordinate of center point in the target rectangle.
8684 \variable QPainter::PixmapFragment::y
8685 \brief the y coordinate of the center point in the target rectangle.
8689 \variable QPainter::PixmapFragment::sourceLeft
8690 \brief the left coordinate of the source rectangle.
8694 \variable QPainter::PixmapFragment::sourceTop
8695 \brief the top coordinate of the source rectangle.
8699 \variable QPainter::PixmapFragment::width
8701 \brief the width of the source rectangle and is used to calculate the width
8702 of the target rectangle.
8706 \variable QPainter::PixmapFragment::height
8708 \brief the height of the source rectangle and is used to calculate the
8709 height of the target rectangle.
8713 \variable QPainter::PixmapFragment::scaleX
8714 \brief the horizontal scale of the target rectangle.
8718 \variable QPainter::PixmapFragment::scaleY
8719 \brief the vertical scale of the target rectangle.
8723 \variable QPainter::PixmapFragment::rotation
8725 \brief the rotation of the target rectangle in degrees. The target
8726 rectangle is rotated after it has been scaled.
8730 \variable QPainter::PixmapFragment::opacity
8732 \brief the opacity of the target rectangle, where 0.0 is fully transparent
8733 and 1.0 is fully opaque.
8739 \enum QPainter::PixmapFragmentHint
8741 \value OpaqueHint Indicates that the pixmap fragments to be drawn are
8742 opaque. Opaque fragments are potentially faster to draw.
8744 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
8747 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
8749 p->draw_helper(path, operation);
8752 /*! \fn Display *QPaintDevice::x11Display() const
8753 Use QX11Info::display() instead.
8756 Display *display = widget->x11Display();
8758 Display *display = QX11Info::display();
8761 \sa QWidget::x11Info(), QX11Info::display()
8764 /*! \fn int QPaintDevice::x11Screen() const
8765 Use QX11Info::screen() instead.
8768 int screen = widget->x11Screen();
8770 int screen = widget->x11Info().screen();
8773 \sa QWidget::x11Info(), QPixmap::x11Info()
8776 /*! \fn void *QPaintDevice::x11Visual() const
8777 Use QX11Info::visual() instead.
8780 void *visual = widget->x11Visual();
8782 void *visual = widget->x11Info().visual();
8785 \sa QWidget::x11Info(), QPixmap::x11Info()
8788 /*! \fn int QPaintDevice::x11Depth() const
8789 Use QX11Info::depth() instead.
8792 int depth = widget->x11Depth();
8794 int depth = widget->x11Info().depth();
8797 \sa QWidget::x11Info(), QPixmap::x11Info()
8800 /*! \fn int QPaintDevice::x11Cells() const
8801 Use QX11Info::cells() instead.
8804 int cells = widget->x11Cells();
8806 int cells = widget->x11Info().cells();
8809 \sa QWidget::x11Info(), QPixmap::x11Info()
8812 /*! \fn Qt::HANDLE QPaintDevice::x11Colormap() const
8813 Use QX11Info::colormap() instead.
8816 unsigned long screen = widget->x11Colormap();
8818 unsigned long screen = widget->x11Info().colormap();
8821 \sa QWidget::x11Info(), QPixmap::x11Info()
8824 /*! \fn bool QPaintDevice::x11DefaultColormap() const
8825 Use QX11Info::defaultColormap() instead.
8828 bool isDefault = widget->x11DefaultColormap();
8830 bool isDefault = widget->x11Info().defaultColormap();
8833 \sa QWidget::x11Info(), QPixmap::x11Info()
8836 /*! \fn bool QPaintDevice::x11DefaultVisual() const
8837 Use QX11Info::defaultVisual() instead.
8840 bool isDefault = widget->x11DefaultVisual();
8842 bool isDefault = widget->x11Info().defaultVisual();
8845 \sa QWidget::x11Info(), QPixmap::x11Info()
8848 /*! \fn void *QPaintDevice::x11AppVisual(int screen)
8849 Use QX11Info::visual() instead.
8852 void *visual = QPaintDevice::x11AppVisual(screen);
8854 void *visual = qApp->x11Info(screen).visual();
8857 \sa QWidget::x11Info(), QPixmap::x11Info()
8860 /*! \fn Qt::HANDLE QPaintDevice::x11AppColormap(int screen)
8861 Use QX11Info::colormap() instead.
8864 unsigned long colormap = QPaintDevice::x11AppColormap(screen);
8866 unsigned long colormap = qApp->x11Info(screen).colormap();
8869 \sa QWidget::x11Info(), QPixmap::x11Info()
8872 /*! \fn Display *QPaintDevice::x11AppDisplay()
8873 Use QX11Info::display() instead.
8876 Display *display = QPaintDevice::x11AppDisplay();
8878 Display *display = qApp->x11Info().display();
8881 \sa QWidget::x11Info(), QPixmap::x11Info()
8884 /*! \fn int QPaintDevice::x11AppScreen()
8885 Use QX11Info::screen() instead.
8888 int screen = QPaintDevice::x11AppScreen();
8890 int screen = qApp->x11Info().screen();
8893 \sa QWidget::x11Info(), QPixmap::x11Info()
8896 /*! \fn int QPaintDevice::x11AppDepth(int screen)
8897 Use QX11Info::depth() instead.
8900 int depth = QPaintDevice::x11AppDepth(screen);
8902 int depth = qApp->x11Info(screen).depth();
8905 \sa QWidget::x11Info(), QPixmap::x11Info()
8908 /*! \fn int QPaintDevice::x11AppCells(int screen)
8909 Use QX11Info::cells() instead.
8912 int cells = QPaintDevice::x11AppCells(screen);
8914 int cells = qApp->x11Info(screen).cells();
8917 \sa QWidget::x11Info(), QPixmap::x11Info()
8920 /*! \fn Qt::HANDLE QPaintDevice::x11AppRootWindow(int screen)
8921 Use QX11Info::appRootWindow() instead.
8924 unsigned long window = QPaintDevice::x11AppRootWindow(screen);
8926 unsigned long window = qApp->x11Info(screen).appRootWindow();
8929 \sa QWidget::x11Info(), QPixmap::x11Info()
8932 /*! \fn bool QPaintDevice::x11AppDefaultColormap(int screen)
8933 Use QX11Info::defaultColormap() instead.
8936 bool isDefault = QPaintDevice::x11AppDefaultColormap(screen);
8938 bool isDefault = qApp->x11Info(screen).defaultColormap();
8941 \sa QWidget::x11Info(), QPixmap::x11Info()
8944 /*! \fn bool QPaintDevice::x11AppDefaultVisual(int screen)
8945 Use QX11Info::defaultVisual() instead.
8948 bool isDefault = QPaintDevice::x11AppDefaultVisual(screen);
8950 bool isDefault = qApp->x11Info(screen).defaultVisual();
8953 \sa QWidget::x11Info(), QPixmap::x11Info()
8956 /*! \fn void QPaintDevice::x11SetAppDpiX(int dpi, int screen)
8957 Use QX11Info::setAppDpiX() instead.
8960 /*! \fn void QPaintDevice::x11SetAppDpiY(int dpi, int screen)
8961 Use QX11Info::setAppDpiY() instead.
8964 /*! \fn int QPaintDevice::x11AppDpiX(int screen)
8965 Use QX11Info::appDpiX() instead.
8968 bool isDefault = QPaintDevice::x11AppDpiX(screen);
8970 bool isDefault = qApp->x11Info(screen).appDpiX();
8973 \sa QWidget::x11Info(), QPixmap::x11Info()
8976 /*! \fn int QPaintDevice::x11AppDpiY(int screen)
8977 Use QX11Info::appDpiY() instead.
8980 bool isDefault = QPaintDevice::x11AppDpiY(screen);
8982 bool isDefault = qApp->x11Info(screen).appDpiY();
8985 \sa QWidget::x11Info(), QPixmap::x11Info()
8988 /*! \fn HDC QPaintDevice::getDC() const
8992 /*! \fn void QPaintDevice::releaseDC(HDC) const
8996 /*! \fn QWSDisplay *QPaintDevice::qwsDisplay()