1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
50 #include "qpaintdevice.h"
51 #include "qpaintengine.h"
53 #include "qpainter_p.h"
54 #include "qpainterpath.h"
56 #include "qpixmapcache.h"
58 #include "qtextlayout.h"
60 #include "qvarlengtharray.h"
61 #include "qstatictext.h"
62 #include "qglyphrun.h"
64 #include <qpa/qplatformtheme.h>
66 #include <private/qfontengine_p.h>
67 #include <private/qpaintengine_p.h>
68 #include <private/qemulationpaintengine_p.h>
69 #include <private/qpainterpath_p.h>
70 #include <private/qtextengine_p.h>
71 #include <private/qpaintengine_raster_p.h>
72 #include <private/qmath_p.h>
73 #include <private/qstatictext_p.h>
74 #include <private/qglyphrun_p.h>
75 #include <private/qhexstring_p.h>
76 #include <private/qguiapplication_p.h>
77 #include <private/qrawfont_p.h>
81 #define QGradient_StretchToDevice 0x10000000
82 #define QPaintEngine_OpaqueBackground 0x40000000
84 // #define QT_DEBUG_DRAW
86 bool qt_show_painter_debug_output = true;
89 extern QPixmap qt_pixmapForBrush(int style, bool invert);
91 void qt_format_text(const QFont &font,
92 const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
93 int tabstops, int* tabarray, int tabarraylen,
95 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
96 QTextCharFormat::UnderlineStyle underlineStyle,
97 QTextItem::RenderFlags flags, qreal width,
98 const QTextCharFormat &charFormat);
99 // Helper function to calculate left most position, width and flags for decoration drawing
100 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
101 const QFixedPoint *positions, int glyphCount,
102 QFontEngine *fontEngine, const QFont &font,
103 const QTextCharFormat &charFormat);
105 static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush)
107 switch (brush.style()) {
108 case Qt::LinearGradientPattern:
109 case Qt::RadialGradientPattern:
110 case Qt::ConicalGradientPattern:
111 return brush.gradient()->coordinateMode();
115 return QGradient::LogicalMode;
118 /* Returns true if the gradient requires stretch to device...*/
119 static inline bool check_gradient(const QBrush &brush)
121 return coordinateMode(brush) == QGradient::StretchToDeviceMode;
124 extern bool qHasPixmapTexture(const QBrush &);
126 static inline bool is_brush_transparent(const QBrush &brush) {
127 Qt::BrushStyle s = brush.style();
128 bool brushBitmap = qHasPixmapTexture(brush)
129 ? brush.texture().isQBitmap()
130 : (brush.textureImage().depth() == 1);
131 return ((s >= Qt::Dense1Pattern && s <= Qt::DiagCrossPattern)
132 || (s == Qt::TexturePattern && brushBitmap));
135 static inline bool is_pen_transparent(const QPen &pen) {
136 return pen.style() > Qt::SolidLine || is_brush_transparent(pen.brush());
139 /* Discards the emulation flags that are not relevant for line drawing
140 and returns the result
142 static inline uint line_emulation(uint emulation)
144 return emulation & (QPaintEngine::PrimitiveTransform
145 | QPaintEngine::AlphaBlend
146 | QPaintEngine::Antialiasing
147 | QPaintEngine::BrushStroke
148 | QPaintEngine::ConstantOpacity
149 | QGradient_StretchToDevice
150 | QPaintEngine::ObjectBoundingModeGradients
151 | QPaintEngine_OpaqueBackground);
155 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
158 case QInternal::Image:
159 case QInternal::Printer:
160 case QInternal::Picture:
161 // can be drawn onto these devices safely from any thread
165 if (!extraCondition && QThread::currentThread() != qApp->thread()) {
166 qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
175 void QPainterPrivate::checkEmulation()
178 if (extended->flags() & QPaintEngineEx::DoNotEmulate)
181 bool doEmulation = false;
182 if (state->bgMode == Qt::OpaqueMode)
185 const QGradient *bg = state->brush.gradient();
186 if (bg && bg->coordinateMode() > QGradient::LogicalMode)
189 const QGradient *pg = qpen_brush(state->pen).gradient();
190 if (pg && pg->coordinateMode() > QGradient::LogicalMode)
194 if (extended != emulationEngine) {
195 if (!emulationEngine)
196 emulationEngine = new QEmulationPaintEngine(extended);
197 extended = emulationEngine;
198 extended->setState(state);
200 } else if (emulationEngine == extended) {
201 extended = emulationEngine->real_engine;
206 QPainterPrivate::~QPainterPrivate()
208 delete emulationEngine;
209 for (int i=0; i<states.size(); ++i)
217 QTransform QPainterPrivate::viewTransform() const
220 qreal scaleW = qreal(state->vw)/qreal(state->ww);
221 qreal scaleH = qreal(state->vh)/qreal(state->wh);
222 return QTransform(scaleW, 0, 0, scaleH,
223 state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
231 Returns true if using a shared painter; otherwise false.
233 bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
238 QPainter *sp = pdev->sharedPainter();
242 // Save the current state of the shared painter and assign
243 // the current d_ptr to the shared painter's d_ptr.
245 if (!sp->d_ptr->d_ptrs) {
246 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
247 // redirections within the same paintEvent(), which should be enough
248 // in 99% of all cases). E.g: A renders B which renders C which renders D.
249 sp->d_ptr->d_ptrs_size = 4;
250 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
251 Q_CHECK_PTR(sp->d_ptr->d_ptrs);
252 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
253 // However, to support corner cases we grow the array dynamically if needed.
254 sp->d_ptr->d_ptrs_size <<= 1;
255 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
256 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
258 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
260 q->d_ptr.reset(sp->d_ptr.data());
262 Q_ASSERT(q->d_ptr->state);
264 // Now initialize the painter with correct widget properties.
267 pdev->redirected(&offset);
268 offset += q->d_ptr->engine->coordinateOffset();
270 // Update system rect.
271 q->d_ptr->state->ww = q->d_ptr->state->vw = pdev->width();
272 q->d_ptr->state->wh = q->d_ptr->state->vh = pdev->height();
275 if (q->d_ptr->state->WxF) {
276 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix;
277 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
278 q->d_ptr->state->worldMatrix = QTransform();
279 q->d_ptr->state->WxF = false;
281 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
283 q->d_ptr->updateMatrix();
285 QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
286 if (enginePrivate->currentClipDevice == pdev) {
287 enginePrivate->systemStateChanged();
291 // Update system transform and clip.
292 enginePrivate->currentClipDevice = pdev;
293 enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
297 void QPainterPrivate::detachPainterPrivate(QPainter *q)
299 Q_ASSERT(refcount > 1);
302 QPainterPrivate *original = d_ptrs[--refcount - 1];
304 inDestructor = false;
306 original->inDestructor = true;
307 } else if (!original) {
308 original = new QPainterPrivate(q);
311 d_ptrs[refcount - 1] = 0;
314 q->d_ptr.reset(original);
316 if (emulationEngine) {
317 extended = emulationEngine->real_engine;
318 delete emulationEngine;
324 void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op)
327 if (qt_show_painter_debug_output) {
328 printf("QPainter::drawHelper\n");
332 if (originalPath.isEmpty())
335 QPaintEngine::PaintEngineFeatures gradientStretch =
336 QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
337 | QPaintEngine::ObjectBoundingModeGradients);
339 const bool mustEmulateObjectBoundingModeGradients = extended
340 || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients)
341 && !engine->hasFeature(QPaintEngine::PatternTransform));
343 if (!(state->emulationSpecifier & ~gradientStretch)
344 && !mustEmulateObjectBoundingModeGradients) {
345 drawStretchedGradient(originalPath, op);
347 } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {
348 drawOpaqueBackground(originalPath, op);
354 qreal strokeOffsetX = 0, strokeOffsetY = 0;
356 QPainterPath path = originalPath * state->matrix;
357 QRectF pathBounds = path.boundingRect();
359 bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
361 qreal penWidth = state->pen.widthF();
366 // In case of complex xform
367 if (state->matrix.type() > QTransform::TxScale) {
368 QPainterPathStroker stroker;
369 stroker.setWidth(penWidth);
370 stroker.setJoinStyle(state->pen.joinStyle());
371 stroker.setCapStyle(state->pen.capStyle());
372 QPainterPath stroke = stroker.createStroke(originalPath);
373 strokeBounds = (stroke * state->matrix).boundingRect();
375 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);
376 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);
382 if (!strokeBounds.isEmpty()) {
383 absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
385 absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
386 .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
389 if (q->hasClipping()) {
390 bool hasPerspectiveTransform = false;
391 for (int i = 0; i < state->clipInfo.size(); ++i) {
392 const QPainterClipInfo &info = state->clipInfo.at(i);
393 if (info.matrix.type() == QTransform::TxProject) {
394 hasPerspectiveTransform = true;
398 // avoid mapping QRegions with perspective transforms
399 if (!hasPerspectiveTransform) {
400 // The trick with txinv and invMatrix is done in order to
401 // avoid transforming the clip to logical coordinates, and
402 // then back to device coordinates. This is a problem with
403 // QRegion/QRect based clips, since they use integer
404 // coordinates and converting to/from logical coordinates will
406 bool old_txinv = txinv;
407 QTransform old_invMatrix = invMatrix;
409 invMatrix = QTransform();
410 QPainterPath clipPath = q->clipPath();
411 QRectF r = clipPath.boundingRect().intersected(absPathRect);
412 absPathRect = r.toAlignedRect();
414 invMatrix = old_invMatrix;
418 // qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
419 // devMinX, devMinY, device->width(), device->height());
420 // qDebug() << " - matrix" << state->matrix;
421 // qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
422 // qDebug() << " - path.bounds" << path.boundingRect();
424 if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
427 QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
432 p.d_ptr->helper_device = helper_device;
434 p.setOpacity(state->opacity);
435 p.translate(-absPathRect.x(), -absPathRect.y());
436 p.setTransform(state->matrix, true);
437 p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
438 p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
439 p.setBackground(state->bgBrush);
440 p.setBackgroundMode(state->bgMode);
441 p.setBrushOrigin(state->brushOrigin);
443 p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);
444 p.setRenderHint(QPainter::SmoothPixmapTransform,
445 state->renderHints & QPainter::SmoothPixmapTransform);
447 p.drawPath(originalPath);
450 static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0;
451 if (do_fallback_overlay) {
452 QImage block(8, 8, QImage::Format_ARGB32_Premultiplied);
454 pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
455 pt.drawLine(0, 0, 8, 8);
458 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
460 p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
467 state->matrix = QTransform();
469 extended->transformChanged();
471 state->dirtyFlags |= QPaintEngine::DirtyTransform;
474 engine->drawImage(absPathRect,
476 QRectF(0, 0, absPathRect.width(), absPathRect.height()),
477 Qt::OrderedDither | Qt::OrderedAlphaDither);
481 void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op)
485 q->setBackgroundMode(Qt::TransparentMode);
487 if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
488 q->fillPath(path, state->bgBrush.color());
489 q->fillPath(path, state->brush);
492 if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
493 q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
494 q->strokePath(path, state->pen);
497 q->setBackgroundMode(Qt::OpaqueMode);
500 static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
502 Q_ASSERT(brush.style() >= Qt::LinearGradientPattern
503 && brush.style() <= Qt::ConicalGradientPattern);
505 QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
506 boundingRect.x(), boundingRect.y());
508 QGradient g = *brush.gradient();
509 g.setCoordinateMode(QGradient::LogicalMode);
512 b.setTransform(gradientToUser * b.transform());
516 void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op)
520 const qreal sw = helper_device->width();
521 const qreal sh = helper_device->height();
523 bool changedPen = false;
524 bool changedBrush = false;
525 bool needsFill = false;
527 const QPen pen = state->pen;
528 const QBrush brush = state->brush;
530 const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
531 const QGradient::CoordinateMode brushMode = coordinateMode(brush);
535 // Draw the xformed fill if the brush is a stretch gradient.
536 if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
537 if (brushMode == QGradient::StretchToDeviceMode) {
538 q->setPen(Qt::NoPen);
539 changedPen = pen.style() != Qt::NoPen;
543 const qreal isw = 1.0 / sw;
544 const qreal ish = 1.0 / sh;
545 QTransform inv(isw, 0, 0, ish, 0, 0);
546 engine->drawPath(path * inv);
551 if (brushMode == QGradient::ObjectBoundingMode) {
552 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
553 boundingRect = path.boundingRect();
554 q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
560 if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
561 // Draw the xformed outline if the pen is a stretch gradient.
562 if (penMode == QGradient::StretchToDeviceMode) {
563 q->setPen(Qt::NoPen);
568 engine->drawPath(path);
572 q->setBrush(pen.brush());
576 QPainterPathStroker stroker;
577 stroker.setDashPattern(pen.style());
578 stroker.setWidth(pen.widthF());
579 stroker.setJoinStyle(pen.joinStyle());
580 stroker.setCapStyle(pen.capStyle());
581 stroker.setMiterLimit(pen.miterLimit());
582 QPainterPath stroke = stroker.createStroke(path);
584 const qreal isw = 1.0 / sw;
585 const qreal ish = 1.0 / sh;
586 QTransform inv(isw, 0, 0, ish, 0, 0);
587 engine->drawPath(stroke * inv);
590 if (!needsFill && brush.style() != Qt::NoBrush) {
591 q->setBrush(Qt::NoBrush);
595 if (penMode == QGradient::ObjectBoundingMode) {
596 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
598 // avoid computing the bounding rect twice
599 if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
600 boundingRect = path.boundingRect();
603 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect));
606 } else if (changedPen) {
612 engine->drawPath(path);
614 } else if (needsFill) {
615 if (pen.style() != Qt::NoPen) {
616 q->setPen(Qt::NoPen);
621 engine->drawPath(path);
631 void QPainterPrivate::updateMatrix()
633 state->matrix = state->WxF ? state->worldMatrix : QTransform();
635 state->matrix *= viewTransform();
637 txinv = false; // no inverted matrix
638 state->matrix *= state->redirectionMatrix;
640 extended->transformChanged();
642 state->dirtyFlags |= QPaintEngine::DirtyTransform;
644 // printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
645 // qDebug() << " --- using matrix" << state->matrix << redirection_offset;
649 void QPainterPrivate::updateInvMatrix()
651 Q_ASSERT(txinv == false);
652 txinv = true; // creating inverted matrix
653 invMatrix = state->matrix.inverted();
656 extern bool qt_isExtendedRadialGradient(const QBrush &brush);
658 void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
661 bool linearGradient = false;
662 bool radialGradient = false;
663 bool extendedRadialGradient = false;
664 bool conicalGradient = false;
665 bool patternBrush = false;
667 bool complexXform = false;
671 // Pen and brush properties (we have to check both if one changes because the
672 // one that's unchanged can still be in a state which requires emulation)
673 if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) {
674 // Check Brush stroke emulation
675 if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke))
676 s->emulationSpecifier |= QPaintEngine::BrushStroke;
678 s->emulationSpecifier &= ~QPaintEngine::BrushStroke;
682 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
683 Qt::BrushStyle brushStyle = qbrush_style(s->brush);
684 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
685 alpha = (penBrushStyle != Qt::NoBrush
686 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
687 && !penBrush.isOpaque())
688 || (brushStyle != Qt::NoBrush
689 && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
690 && !s->brush.isOpaque());
691 linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
692 (brushStyle == Qt::LinearGradientPattern));
693 radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
694 (brushStyle == Qt::RadialGradientPattern));
695 extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
696 conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
697 (brushStyle == Qt::ConicalGradientPattern));
698 patternBrush = (((penBrushStyle > Qt::SolidPattern
699 && penBrushStyle < Qt::LinearGradientPattern)
700 || penBrushStyle == Qt::TexturePattern) ||
701 ((brushStyle > Qt::SolidPattern
702 && brushStyle < Qt::LinearGradientPattern)
703 || brushStyle == Qt::TexturePattern));
705 bool penTextureAlpha = false;
706 if (penBrush.style() == Qt::TexturePattern)
707 penTextureAlpha = qHasPixmapTexture(penBrush)
708 ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
709 : penBrush.textureImage().hasAlphaChannel();
710 bool brushTextureAlpha = false;
711 if (s->brush.style() == Qt::TexturePattern) {
712 brushTextureAlpha = qHasPixmapTexture(s->brush)
713 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
714 : s->brush.textureImage().hasAlphaChannel();
716 if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
717 || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
718 && !engine->hasFeature(QPaintEngine::MaskedBrush))
719 s->emulationSpecifier |= QPaintEngine::MaskedBrush;
721 s->emulationSpecifier &= ~QPaintEngine::MaskedBrush;
724 if (s->state() & (QPaintEngine::DirtyHints
725 | QPaintEngine::DirtyOpacity
726 | QPaintEngine::DirtyBackgroundMode)) {
734 qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
736 " - linearGradient: %d\n"
737 " - radialGradient: %d\n"
738 " - conicalGradient: %d\n"
739 " - patternBrush: %d\n"
748 uint(s->renderHints),
753 if (s->state() & QPaintEngine::DirtyTransform) {
754 xform = !s->matrix.isIdentity();
755 complexXform = !s->matrix.isAffine();
756 } else if (s->matrix.type() >= QTransform::TxTranslate) {
758 complexXform = !s->matrix.isAffine();
761 const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone);
762 const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone);
764 const bool patternXform = patternBrush && (xform || brushXform || penXform);
766 // Check alphablending
767 if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend))
768 s->emulationSpecifier |= QPaintEngine::AlphaBlend;
770 s->emulationSpecifier &= ~QPaintEngine::AlphaBlend;
772 // Linear gradient emulation
773 if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill))
774 s->emulationSpecifier |= QPaintEngine::LinearGradientFill;
776 s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
778 // Radial gradient emulation
779 if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
780 s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
782 s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
784 // Conical gradient emulation
785 if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
786 s->emulationSpecifier |= QPaintEngine::ConicalGradientFill;
788 s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill;
791 if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
792 s->emulationSpecifier |= QPaintEngine::PatternBrush;
794 s->emulationSpecifier &= ~QPaintEngine::PatternBrush;
797 if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform))
798 s->emulationSpecifier |= QPaintEngine::PatternTransform;
800 s->emulationSpecifier &= ~QPaintEngine::PatternTransform;
803 if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform))
804 s->emulationSpecifier |= QPaintEngine::PrimitiveTransform;
806 s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform;
808 // Perspective XForms
809 if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform))
810 s->emulationSpecifier |= QPaintEngine::PerspectiveTransform;
812 s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform;
815 if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity))
816 s->emulationSpecifier |= QPaintEngine::ConstantOpacity;
818 s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity;
820 bool gradientStretch = false;
821 bool objectBoundingMode = false;
822 if (linearGradient || conicalGradient || radialGradient) {
823 QGradient::CoordinateMode brushMode = coordinateMode(s->brush);
824 QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush());
826 gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
827 gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
829 objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
830 objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
833 s->emulationSpecifier |= QGradient_StretchToDevice;
835 s->emulationSpecifier &= ~QGradient_StretchToDevice;
837 if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
838 s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients;
840 s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients;
842 // Opaque backgrounds...
843 if (s->bgMode == Qt::OpaqueMode &&
844 (is_pen_transparent(s->pen) || is_brush_transparent(s->brush)))
845 s->emulationSpecifier |= QPaintEngine_OpaqueBackground;
847 s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground;
850 //won't be correct either way because the device can already have
851 // something rendered to it in which case subsequent emulation
852 // on a fully transparent qimage and then blitting the results
853 // won't produce correct results
855 if (state->composition_mode > QPainter::CompositionMode_Xor &&
856 !engine->hasFeature(QPaintEngine::BlendModes))
857 s->emulationSpecifier |= QPaintEngine::BlendModes;
859 s->emulationSpecifier &= ~QPaintEngine::BlendModes;
863 void QPainterPrivate::updateStateImpl(QPainterState *newState)
865 // ### we might have to call QPainter::begin() here...
866 if (!engine->state) {
867 engine->state = newState;
868 engine->setDirty(QPaintEngine::AllDirty);
871 if (engine->state->painter() != newState->painter)
872 // ### this could break with clip regions vs paths.
873 engine->setDirty(QPaintEngine::AllDirty);
875 // Upon restore, revert all changes since last save
876 else if (engine->state != newState)
877 newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
879 // We need to store all changes made so that restore can deal with them
881 newState->changeFlags |= newState->dirtyFlags;
883 updateEmulationSpecifier(newState);
885 // Unset potential dirty background mode
886 newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode
887 | QPaintEngine::DirtyBackground);
889 engine->state = newState;
890 engine->updateState(*newState);
891 engine->clearDirty(QPaintEngine::AllDirty);
895 void QPainterPrivate::updateState(QPainterState *newState)
899 engine->state = newState;
901 } else if (newState->state() || engine->state!=newState) {
902 bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
903 && newState->pen.widthF() == 0;
904 if (setNonCosmeticPen) {
905 // Override the default pen's cosmetic state if the
906 // NonCosmeticDefaultPen render hint is used.
907 QPen oldPen = newState->pen;
908 newState->pen.setWidth(1);
909 newState->pen.setCosmetic(false);
910 newState->dirtyFlags |= QPaintEngine::DirtyPen;
912 updateStateImpl(newState);
914 // Restore the state pen back to its default to preserve visible
916 newState->pen = oldPen;
918 updateStateImpl(newState);
926 \brief The QPainter class performs low-level painting on widgets and
933 QPainter provides highly optimized functions to do most of the
934 drawing GUI programs require. It can draw everything from simple
935 lines to complex shapes like pies and chords. It can also draw
936 aligned text and pixmaps. Normally, it draws in a "natural"
937 coordinate system, but it can also do view and world
938 transformation. QPainter can operate on any object that inherits
939 the QPaintDevice class.
941 The common use of QPainter is inside a widget's paint event:
942 Construct and customize (e.g. set the pen or the brush) the
943 painter. Then draw. Remember to destroy the QPainter object after
944 drawing. For example:
946 \snippet code/src_gui_painting_qpainter.cpp 0
948 The core functionality of QPainter is drawing, but the class also
949 provide several functions that allows you to customize QPainter's
950 settings and its rendering quality, and others that enable
951 clipping. In addition you can control how different shapes are
952 merged together by specifying the painter's composition mode.
954 The isActive() function indicates whether the painter is active. A
955 painter is activated by the begin() function and the constructor
956 that takes a QPaintDevice argument. The end() function, and the
957 destructor, deactivates it.
959 Together with the QPaintDevice and QPaintEngine classes, QPainter
960 form the basis for Qt's paint system. QPainter is the class used
961 to perform drawing operations. QPaintDevice represents a device
962 that can be painted on using a QPainter. QPaintEngine provides the
963 interface that the painter uses to draw onto different types of
964 devices. If the painter is active, device() returns the paint
965 device on which the painter paints, and paintEngine() returns the
966 paint engine that the painter is currently operating on. For more
967 information, see the \l {Paint System}.
969 Sometimes it is desirable to make someone else paint on an unusual
970 QPaintDevice. QPainter supports a static function to do this,
973 \warning When the paintdevice is a widget, QPainter can only be
974 used inside a paintEvent() function or in a function called by
981 There are several settings that you can customize to make QPainter
982 draw according to your preferences:
986 \li font() is the font used for drawing text. If the painter
987 isActive(), you can retrieve information about the currently set
988 font, and its metrics, using the fontInfo() and fontMetrics()
989 functions respectively.
991 \li brush() defines the color or pattern that is used for filling
994 \li pen() defines the color or stipple that is used for drawing
997 \li backgroundMode() defines whether there is a background() or
998 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
1000 \li background() only applies when backgroundMode() is \l
1001 Qt::OpaqueMode and pen() is a stipple. In that case, it
1002 describes the color of the background pixels in the stipple.
1004 \li brushOrigin() defines the origin of the tiled brushes, normally
1005 the origin of widget's background.
1007 \li viewport(), window(), worldTransform() make up the painter's coordinate
1008 transformation system. For more information, see the \l
1009 {Coordinate Transformations} section and the \l {Coordinate
1010 System} documentation.
1012 \li hasClipping() tells whether the painter clips at all. (The paint
1013 device clips, too.) If the painter clips, it clips to clipRegion().
1015 \li layoutDirection() defines the layout direction used by the
1016 painter when drawing text.
1018 \li worldMatrixEnabled() tells whether world transformation is enabled.
1020 \li viewTransformEnabled() tells whether view transformation is
1025 Note that some of these settings mirror settings in some paint
1026 devices, e.g. QWidget::font(). The QPainter::begin() function (or
1027 equivalently the QPainter constructor) copies these attributes
1028 from the paint device.
1030 You can at any time save the QPainter's state by calling the
1031 save() function which saves all the available settings on an
1032 internal stack. The restore() function pops them back.
1036 QPainter provides functions to draw most primitives: drawPoint(),
1037 drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1038 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1039 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
1040 convenience functions, drawRects() and drawLines(), draw the given
1041 number of rectangles or lines in the given array of \l
1042 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1045 The QPainter class also provides the fillRect() function which
1046 fills the given QRect, with the given QBrush, and the eraseRect()
1047 function that erases the area inside the given rectangle.
1049 All of these functions have both integer and floating point
1054 \li \inlineimage qpainter-basicdrawing.png
1056 \b {Basic Drawing Example}
1058 The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1059 display basic graphics primitives in a variety of styles using the
1064 If you need to draw a complex shape, especially if you need to do
1065 so repeatedly, consider creating a QPainterPath and drawing it
1071 \b {Painter Paths example}
1073 The QPainterPath class provides a container for painting
1074 operations, enabling graphical shapes to be constructed and
1077 The \l {painting/painterpaths}{Painter Paths} example shows how
1078 painter paths can be used to build complex shapes for rendering.
1080 \li \inlineimage qpainter-painterpaths.png
1083 QPainter also provides the fillPath() function which fills the
1084 given QPainterPath with the given QBrush, and the strokePath()
1085 function that draws the outline of the given path (i.e. strokes
1088 See also the \l {painting/deform}{Vector Deformation} example which
1089 shows how to use advanced vector techniques to draw text using a
1090 QPainterPath, the \l {painting/gradients}{Gradients} example which shows
1091 the different types of gradients that are available in Qt, and the \l
1092 {painting/pathstroke}{Path Stroking} example which shows Qt's built-in
1093 dash patterns and shows how custom patterns can be used to extend
1094 the range of available patterns.
1098 \li \l {painting/deform}{Vector Deformation}
1099 \li \l {painting/gradients}{Gradients}
1100 \li \l {painting/pathstroke}{Path Stroking}
1102 \li \inlineimage qpainter-vectordeformation.png
1103 \li \inlineimage qpainter-gradients.png
1104 \li \inlineimage qpainter-pathstroking.png
1108 There are functions to draw pixmaps/images, namely drawPixmap(),
1109 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1110 produce the same result, except that drawPixmap() is faster
1111 on-screen while drawImage() may be faster on a QPrinter or other
1114 Text drawing is done using drawText(). When you need
1115 fine-grained positioning, boundingRect() tells you where a given
1116 drawText() command will draw.
1118 There is a drawPicture() function that draws the contents of an
1119 entire QPicture. The drawPicture() function is the only function
1120 that disregards all the painter's settings as QPicture has its own
1123 \section1 Rendering Quality
1125 To get the optimal rendering result using QPainter, you should use
1126 the platform independent QImage as paint device; i.e. using QImage
1127 will ensure that the result has an identical pixel representation
1130 The QPainter class also provides a means of controlling the
1131 rendering quality through its RenderHint enum and the support for
1132 floating point precision: All the functions for drawing primitives
1133 has a floating point version. These are often used in combination
1134 with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1138 \li \inlineimage qpainter-concentriccircles.png
1140 \b {Concentric Circles Example}
1142 The \l {painting/concentriccircles}{Concentric Circles} example
1143 shows the improved rendering quality that can be obtained using
1144 floating point precision and anti-aliasing when drawing custom
1147 The application's main window displays several widgets which are
1148 drawn using the various combinations of precision and
1153 The RenderHint enum specifies flags to QPainter that may or may
1154 not be respected by any given engine. \l
1155 {RenderHint}{QPainter::Antialiasing} indicates that the engine
1156 should antialias edges of primitives if possible, \l
1157 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1158 should antialias text if possible, and the \l
1159 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1160 engine should use a smooth pixmap transformation algorithm.
1161 \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
1162 indicating that the engine should use fragment programs and offscreen
1163 rendering for antialiasing.
1165 The renderHints() function returns a flag that specifies the
1166 rendering hints that are set for this painter. Use the
1167 setRenderHint() function to set or clear the currently set
1170 \section1 Coordinate Transformations
1172 Normally, the QPainter operates on the device's own coordinate
1173 system (usually pixels), but QPainter has good support for
1174 coordinate transformations.
1178 \li nop \li rotate() \li scale() \li translate()
1180 \li \inlineimage qpainter-clock.png
1181 \li \inlineimage qpainter-rotation.png
1182 \li \inlineimage qpainter-scale.png
1183 \li \inlineimage qpainter-translation.png
1186 The most commonly used transformations are scaling, rotation,
1187 translation and shearing. Use the scale() function to scale the
1188 coordinate system by a given offset, the rotate() function to
1189 rotate it clockwise and translate() to translate it (i.e. adding a
1190 given offset to the points). You can also twist the coordinate
1191 system around the origin using the shear() function. See the \l
1192 {painting/affine}{Affine Transformations} example for a visualization of
1193 a sheared coordinate system.
1195 See also the \l {painting/transformations}{Transformations}
1196 example which shows how transformations influence the way that
1197 QPainter renders graphics primitives. In particular it shows how
1198 the order of transformations affects the result.
1203 \b {Affine Transformations Example}
1205 The \l {painting/affine}{Affine Transformations} example shows Qt's
1206 ability to perform affine transformations on painting
1207 operations. The demo also allows the user to experiment with the
1208 transformation operations and see the results immediately.
1210 \li \inlineimage qpainter-affinetransformations.png
1213 All the tranformation operations operate on the transformation
1214 worldTransform(). A matrix transforms a point in the plane to another
1215 point. For more information about the transformation matrix, see
1216 the \l {Coordinate System} and QTransform documentation.
1218 The setWorldTransform() function can replace or add to the currently
1219 set worldTransform(). The resetTransform() function resets any
1220 transformations that were made using translate(), scale(),
1221 shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1222 functions. The deviceTransform() returns the matrix that transforms
1223 from logical coordinates to device coordinates of the platform
1224 dependent paint device. The latter function is only needed when
1225 using platform painting commands on the platform dependent handle,
1226 and the platform does not do transformations nativly.
1228 When drawing with QPainter, we specify points using logical
1229 coordinates which then are converted into the physical coordinates
1230 of the paint device. The mapping of the logical coordinates to the
1231 physical coordinates are handled by QPainter's combinedTransform(), a
1232 combination of viewport() and window() and worldTransform(). The
1233 viewport() represents the physical coordinates specifying an
1234 arbitrary rectangle, the window() describes the same rectangle in
1235 logical coordinates, and the worldTransform() is identical with the
1236 transformation matrix.
1238 See also \l {Coordinate System}
1242 QPainter can clip any drawing operation to a rectangle, a region,
1243 or a vector path. The current clip is available using the
1244 functions clipRegion() and clipPath(). Whether paths or regions are
1245 preferred (faster) depends on the underlying paintEngine(). For
1246 example, the QImage paint engine prefers paths while the X11 paint
1247 engine prefers regions. Setting a clip is done in the painters
1248 logical coordinates.
1250 After QPainter's clipping, the paint device may also clip. For
1251 example, most widgets clip away the pixels used by child widgets,
1252 and most printers clip away an area near the edges of the paper.
1253 This additional clipping is not reflected by the return value of
1254 clipRegion() or hasClipping().
1256 \section1 Composition Modes
1257 \target Composition Modes
1259 QPainter provides the CompositionMode enum which defines the
1260 Porter-Duff rules for digital image compositing; it describes a
1261 model for combining the pixels in one image, the source, with the
1262 pixels in another image, the destination.
1264 The two most common forms of composition are \l
1265 {QPainter::CompositionMode}{Source} and \l
1266 {QPainter::CompositionMode}{SourceOver}. \l
1267 {QPainter::CompositionMode}{Source} is used to draw opaque objects
1268 onto a paint device. In this mode, each pixel in the source
1269 replaces the corresponding pixel in the destination. In \l
1270 {QPainter::CompositionMode}{SourceOver} composition mode, the
1271 source object is transparent and is drawn on top of the
1274 Note that composition transformation operates pixelwise. For that
1275 reason, there is a difference between using the graphic primitive
1276 itself and its bounding rectangle: The bounding rect contains
1277 pixels with alpha == 0 (i.e the pixels surrounding the
1278 primitive). These pixels will overwrite the other image's pixels,
1279 affectively clearing those, while the primitive only overwrites
1284 \li \inlineimage qpainter-compositiondemo.png
1287 \b {Composition Modes Example}
1289 The \l {painting/composition}{Composition Modes} example, available in
1290 Qt's examples directory, allows you to experiment with the various
1291 composition modes and see the results immediately.
1295 \section1 Limitations
1298 If you are using coordinates with Qt's raster-based paint engine, it is
1299 important to note that, while coordinates greater than +/- 2\sup 15 can
1300 be used, any painting performed with coordinates outside this range is not
1301 guaranteed to be shown; the drawing may be clipped. This is due to the
1302 use of \c{short int} in the implementation.
1304 The outlines generated by Qt's stroker are only an approximation when dealing
1305 with curved shapes. It is in most cases impossible to represent the outline of
1306 a bezier curve segment using another bezier curve segment, and so Qt approximates
1307 the curve outlines by using several smaller curves. For performance reasons there
1308 is a limit to how many curves Qt uses for these outlines, and thus when using
1309 large pen widths or scales the outline error increases. To generate outlines with
1310 smaller errors it is possible to use the QPainterPathStroker class, which has the
1311 setCurveThreshold member function which let's the user specify the error tolerance.
1312 Another workaround is to convert the paths to polygons first and then draw the
1315 \section1 Performance
1317 QPainter is a rich framework that allows developers to do a great
1318 variety of graphical operations, such as gradients, composition
1319 modes and vector graphics. And QPainter can do this across a
1320 variety of different hardware and software stacks. Naturally the
1321 underlying combination of hardware and software has some
1322 implications for performance, and ensuring that every single
1323 operation is fast in combination with all the various combinations
1324 of composition modes, brushes, clipping, transformation, etc, is
1325 close to an impossible task because of the number of
1326 permutations. As a compromise we have selected a subset of the
1327 QPainter API and backends, where performance is guaranteed to be as
1328 good as we can sensibly get it for the given combination of
1329 hardware and software.
1331 The backends we focus on as high-performance engines are:
1335 \li Raster - This backend implements all rendering in pure software
1336 and is always used to render into QImages. For optimal performance
1337 only use the format types QImage::Format_ARGB32_Premultiplied,
1338 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1339 including QImage::Format_ARGB32, has significantly worse
1340 performance. This engine is used by default for QWidget and QPixmap.
1342 \li OpenGL 2.0 (ES) - This backend is the primary backend for
1343 hardware accelerated graphics. It can be run on desktop machines
1344 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1345 specification. This includes most graphics chips produced in the
1346 last couple of years. The engine can be enabled by using QPainter
1347 onto a QOpenGLWidget or by passing \c {-graphicssystem opengl} on the
1348 command line when the underlying system supports it.
1350 \li OpenVG - This backend implements the Khronos standard for 2D
1351 and Vector Graphics. It is primarily for embedded devices with
1352 hardware support for OpenVG. The engine can be enabled by
1353 passing \c {-graphicssystem openvg} on the command line when
1354 the underlying system supports it.
1358 These operations are:
1362 \li Simple transformations, meaning translation and scaling, pluss
1363 0, 90, 180, 270 degree rotations.
1365 \li \c drawPixmap() in combination with simple transformations and
1366 opacity with non-smooth transformation mode
1367 (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1369 \li Rectangle fills with solid color, two-color linear gradients
1370 and simple transforms.
1372 \li Rectangular clipping with simple transformations and intersect
1375 \li Composition Modes \c QPainter::CompositionMode_Source and
1376 QPainter::CompositionMode_SourceOver
1378 \li Rounded rectangle filling using solid color and two-color
1379 linear gradients fills.
1381 \li 3x3 patched pixmaps, via qDrawBorderPixmap.
1385 This list gives an indication of which features to safely use in
1386 an application where performance is critical. For certain setups,
1387 other operations may be fast too, but before making extensive use
1388 of them, it is recommended to benchmark and verify them on the
1389 system where the software will run in the end. There are also
1390 cases where expensive operations are ok to use, for instance when
1391 the result is cached in a QPixmap.
1393 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
1394 {Drawing Utility Functions}
1398 \enum QPainter::RenderHint
1400 Renderhints are used to specify flags to QPainter that may or
1401 may not be respected by any given engine.
1403 \value Antialiasing Indicates that the engine should antialias
1404 edges of primitives if possible.
1406 \value TextAntialiasing Indicates that the engine should antialias
1407 text if possible. To forcibly disable antialiasing for text, do not
1408 use this hint. Instead, set QFont::NoAntialias on your font's style
1411 \value SmoothPixmapTransform Indicates that the engine should use
1412 a smooth pixmap transformation algorithm (such as bilinear) rather
1413 than nearest neighbor.
1415 \value HighQualityAntialiasing An OpenGL-specific rendering hint
1416 indicating that the engine should use fragment programs and offscreen
1417 rendering for antialiasing.
1419 \value NonCosmeticDefaultPen The engine should interpret pens with a width
1420 of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
1421 pen with a width of 1.
1423 \sa renderHints(), setRenderHint(), {QPainter#Rendering
1424 Quality}{Rendering Quality}, {Concentric Circles Example}
1429 Constructs a painter.
1434 QPainter::QPainter()
1435 : d_ptr(new QPainterPrivate(this))
1440 \fn QPainter::QPainter(QPaintDevice *device)
1442 Constructs a painter that begins painting the paint \a device
1445 This constructor is convenient for short-lived painters, e.g. in a
1446 QWidget::paintEvent() and should be used only once. The
1447 constructor calls begin() for you and the QPainter destructor
1448 automatically calls end().
1450 Here's an example using begin() and end():
1451 \snippet code/src_gui_painting_qpainter.cpp 1
1453 The same example using this constructor:
1454 \snippet code/src_gui_painting_qpainter.cpp 2
1456 Since the constructor cannot provide feedback when the initialization
1457 of the painter failed you should rather use begin() and end() to paint
1458 on external devices, e.g. printers.
1463 QPainter::QPainter(QPaintDevice *pd)
1467 if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1468 d_ptr.reset(new QPainterPrivate(this));
1475 Destroys the painter.
1477 QPainter::~QPainter()
1479 d_ptr->inDestructor = true;
1483 else if (d_ptr->refcount > 1)
1484 d_ptr->detachPainterPrivate(this);
1486 // don't throw anything in the destructor.
1489 // Make sure we haven't messed things up.
1490 Q_ASSERT(d_ptr->inDestructor);
1491 d_ptr->inDestructor = false;
1492 Q_ASSERT(d_ptr->refcount == 1);
1494 free(d_ptr->d_ptrs);
1499 Returns the paint device on which this painter is currently
1500 painting, or 0 if the painter is not active.
1505 QPaintDevice *QPainter::device() const
1507 Q_D(const QPainter);
1508 if (isActive() && d->engine->d_func()->currentClipDevice)
1509 return d->engine->d_func()->currentClipDevice;
1510 return d->original_device;
1514 Returns true if begin() has been called and end() has not yet been
1515 called; otherwise returns false.
1517 \sa begin(), QPaintDevice::paintingActive()
1520 bool QPainter::isActive() const
1522 Q_D(const QPainter);
1527 Initializes the painters pen, background and font to the same as
1528 the given \a paint device.
1532 \sa begin(), {QPainter#Settings}{Settings}
1534 void QPainter::initFrom(const QPaintDevice *device)
1536 Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0");
1539 qWarning("QPainter::initFrom: Painter not active, aborted");
1546 d->extended->penChanged();
1547 } else if (d->engine) {
1548 d->engine->setDirty(QPaintEngine::DirtyPen);
1549 d->engine->setDirty(QPaintEngine::DirtyBrush);
1550 d->engine->setDirty(QPaintEngine::DirtyFont);
1556 Saves the current painter state (pushes the state onto a stack). A
1557 save() must be followed by a corresponding restore(); the end()
1558 function unwinds the stack.
1563 void QPainter::save()
1565 #ifdef QT_DEBUG_DRAW
1566 if (qt_show_painter_debug_output)
1567 printf("QPainter::save()\n");
1571 qWarning("QPainter::save: Painter not active");
1576 d->state = d->extended->createState(d->states.back());
1577 d->extended->setState(d->state);
1579 d->updateState(d->state);
1580 d->state = new QPainterState(d->states.back());
1581 d->engine->state = d->state;
1583 d->states.push_back(d->state);
1587 Restores the current painter state (pops a saved state off the
1593 void QPainter::restore()
1595 #ifdef QT_DEBUG_DRAW
1596 if (qt_show_painter_debug_output)
1597 printf("QPainter::restore()\n");
1600 if (d->states.size()<=1) {
1601 qWarning("QPainter::restore: Unbalanced save/restore");
1603 } else if (!d->engine) {
1604 qWarning("QPainter::restore: Painter not active");
1608 QPainterState *tmp = d->state;
1609 d->states.pop_back();
1610 d->state = d->states.back();
1614 d->checkEmulation();
1615 d->extended->setState(d->state);
1620 // trigger clip update if the clip path/region has changed since
1622 if (!d->state->clipInfo.isEmpty()
1623 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1624 // reuse the tmp state to avoid any extra allocs...
1625 tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1626 tmp->clipOperation = Qt::NoClip;
1627 tmp->clipPath = QPainterPath();
1628 d->engine->updateState(*tmp);
1629 // replay the list of clip states,
1630 for (int i=0; i<d->state->clipInfo.size(); ++i) {
1631 const QPainterClipInfo &info = d->state->clipInfo.at(i);
1632 tmp->matrix = info.matrix;
1633 tmp->matrix *= d->state->redirectionMatrix;
1634 tmp->clipOperation = info.operation;
1635 if (info.clipType == QPainterClipInfo::RectClip) {
1636 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1637 tmp->clipRegion = info.rect;
1638 } else if (info.clipType == QPainterClipInfo::RegionClip) {
1639 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1640 tmp->clipRegion = info.region;
1641 } else { // clipType == QPainterClipInfo::PathClip
1642 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1643 tmp->clipPath = info.path;
1645 d->engine->updateState(*tmp);
1649 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1650 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1651 tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1652 tmp->changeFlags |= QPaintEngine::DirtyTransform;
1655 d->updateState(d->state);
1662 \fn bool QPainter::begin(QPaintDevice *device)
1664 Begins painting the paint \a device and returns true if
1665 successful; otherwise returns false.
1667 Notice that all painter settings (setPen(), setBrush() etc.) are reset
1668 to default values when begin() is called.
1670 The errors that can occur are serious problems, such as these:
1672 \snippet code/src_gui_painting_qpainter.cpp 3
1674 Note that most of the time, you can use one of the constructors
1675 instead of begin(), and that end() is automatically done at
1678 \warning A paint device can only be painted by one painter at a
1681 \warning Painting on a QImage with the format
1682 QImage::Format_Indexed8 is not supported.
1684 \sa end(), QPainter()
1687 static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1696 bool QPainter::begin(QPaintDevice *pd)
1700 if (pd->painters > 0) {
1701 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1705 if (d_ptr->engine) {
1706 qWarning("QPainter::begin: Painter already active");
1710 if (QPainterPrivate::attachPainterPrivate(this, pd))
1715 d->helper_device = pd;
1716 d->original_device = pd;
1718 QPoint redirectionOffset;
1719 QPaintDevice *rpd = pd->redirected(&redirectionOffset);
1723 #ifdef QT_DEBUG_DRAW
1724 if (qt_show_painter_debug_output)
1725 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1728 if (pd->devType() == QInternal::Pixmap)
1729 static_cast<QPixmap *>(pd)->detach();
1730 else if (pd->devType() == QInternal::Image)
1731 static_cast<QImage *>(pd)->detach();
1733 d->engine = pd->paintEngine();
1736 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1742 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1743 if (d->emulationEngine)
1744 d->emulationEngine->real_engine = d->extended;
1746 // Setup new state...
1747 Q_ASSERT(!d->state);
1748 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1749 d->state->painter = this;
1750 d->states.push_back(d->state);
1752 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1753 d->state->brushOrigin = QPointF();
1755 // Slip a painter state into the engine before we do any other operations
1757 d->extended->setState(d->state);
1759 d->engine->state = d->state;
1761 switch (pd->devType()) {
1762 case QInternal::Pixmap:
1764 QPixmap *pm = static_cast<QPixmap *>(pd);
1767 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1768 qt_cleanup_painter_state(d);
1772 if (pm->depth() == 1) {
1773 d->state->pen = QPen(Qt::color1);
1774 d->state->brush = QBrush(Qt::color0);
1778 case QInternal::Image:
1780 QImage *img = static_cast<QImage *>(pd);
1782 if (img->isNull()) {
1783 qWarning("QPainter::begin: Cannot paint on a null image");
1784 qt_cleanup_painter_state(d);
1786 } else if (img->format() == QImage::Format_Indexed8) {
1787 // Painting on indexed8 images is not supported.
1788 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1789 qt_cleanup_painter_state(d);
1792 if (img->depth() == 1) {
1793 d->state->pen = QPen(Qt::color1);
1794 d->state->brush = QBrush(Qt::color0);
1801 if (d->state->ww == 0) // For compat with 3.x painter defaults
1802 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1804 d->engine->setPaintDevice(pd);
1806 bool begun = d->engine->begin(pd);
1808 qWarning("QPainter::begin(): Returned false");
1809 if (d->engine->isActive()) {
1812 qt_cleanup_painter_state(d);
1816 d->engine->setActive(begun);
1819 // Copy painter properties from original paint device,
1820 // required for QPixmap::grabWidget()
1821 if (d->original_device->devType() == QInternal::Widget) {
1822 initFrom(d->original_device);
1824 d->state->layoutDirection = Qt::LayoutDirectionAuto;
1825 // make sure we have a font compatible with the paintdevice
1826 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1829 QRect systemRect = d->engine->systemRect();
1830 if (!systemRect.isEmpty()) {
1831 d->state->ww = d->state->vw = systemRect.width();
1832 d->state->wh = d->state->vh = systemRect.height();
1834 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1835 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1838 const QPoint coordinateOffset = d->engine->coordinateOffset();
1839 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1841 Q_ASSERT(d->engine->isActive());
1843 if (!d->state->redirectionMatrix.isIdentity())
1846 Q_ASSERT(d->engine->isActive());
1847 d->state->renderHints = QPainter::TextAntialiasing;
1848 ++d->device->painters;
1850 d->state->emulationSpecifier = 0;
1856 Ends painting. Any resources used while painting are released. You
1857 don't normally need to call this since it is called by the
1860 Returns true if the painter is no longer active; otherwise returns false.
1862 \sa begin(), isActive()
1865 bool QPainter::end()
1867 #ifdef QT_DEBUG_DRAW
1868 if (qt_show_painter_debug_output)
1869 printf("QPainter::end()\n");
1874 qWarning("QPainter::end: Painter not active, aborted");
1875 qt_cleanup_painter_state(d);
1879 if (d->refcount > 1) {
1880 d->detachPainterPrivate(this);
1886 if (d->engine->isActive()) {
1887 ended = d->engine->end();
1890 --d->device->painters;
1891 if (d->device->painters == 0) {
1892 d->engine->setPaintDevice(0);
1893 d->engine->setActive(false);
1897 if (d->states.size() > 1) {
1898 qWarning("QPainter::end: Painter ended with %d saved states",
1902 if (d->engine->autoDestruct()) {
1906 if (d->emulationEngine) {
1907 delete d->emulationEngine;
1908 d->emulationEngine = 0;
1915 qt_cleanup_painter_state(d);
1922 Returns the paint engine that the painter is currently operating
1923 on if the painter is active; otherwise 0.
1927 QPaintEngine *QPainter::paintEngine() const
1929 Q_D(const QPainter);
1936 Flushes the painting pipeline and prepares for the user issuing commands
1937 directly to the underlying graphics context. Must be followed by a call to
1938 endNativePainting().
1940 Note that only the states the underlying paint engine changes will be reset
1941 to their respective default states. The states we reset may change from
1942 release to release. The following states are currently reset in the OpenGL
1946 \li blending is disabled
1947 \li the depth, stencil and scissor tests are disabled
1948 \li the active texture unit is reset to 0
1949 \li the depth mask, depth function and the clear depth are reset to their
1951 \li the stencil mask, stencil operation and stencil function are reset to
1952 their default values
1953 \li the current color is reset to solid white
1956 If, for example, the OpenGL polygon mode is changed by the user inside a
1957 beginNativePaint()/endNativePainting() block, it will not be reset to the
1958 default state by endNativePainting(). Here is an example that shows
1959 intermixing of painter commands and raw OpenGL commands:
1961 \snippet code/src_gui_painting_qpainter.cpp 21
1963 \sa endNativePainting()
1965 void QPainter::beginNativePainting()
1969 qWarning("QPainter::beginNativePainting: Painter not active");
1974 d->extended->beginNativePainting();
1980 Restores the painter after manually issuing native painting commands. Lets
1981 the painter restore any native state that it relies on before calling any
1982 other painter commands.
1984 \sa beginNativePainting()
1986 void QPainter::endNativePainting()
1988 Q_D(const QPainter);
1990 qWarning("QPainter::beginNativePainting: Painter not active");
1995 d->extended->endNativePainting();
1997 d->engine->syncState();
2001 Returns the font metrics for the painter if the painter is
2002 active. Otherwise, the return value is undefined.
2004 \sa font(), isActive(), {QPainter#Settings}{Settings}
2007 QFontMetrics QPainter::fontMetrics() const
2009 Q_D(const QPainter);
2011 qWarning("QPainter::fontMetrics: Painter not active");
2012 return QFontMetrics(QFont());
2014 return QFontMetrics(d->state->font);
2019 Returns the font info for the painter if the painter is
2020 active. Otherwise, the return value is undefined.
2022 \sa font(), isActive(), {QPainter#Settings}{Settings}
2025 QFontInfo QPainter::fontInfo() const
2027 Q_D(const QPainter);
2029 qWarning("QPainter::fontInfo: Painter not active");
2030 return QFontInfo(QFont());
2032 return QFontInfo(d->state->font);
2038 Returns the opacity of the painter. The default value is
2042 qreal QPainter::opacity() const
2044 Q_D(const QPainter);
2046 qWarning("QPainter::opacity: Painter not active");
2049 return d->state->opacity;
2055 Sets the opacity of the painter to \a opacity. The value should
2056 be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2057 1.0 is fully opaque.
2059 Opacity set on the painter will apply to all drawing operations
2063 void QPainter::setOpacity(qreal opacity)
2068 qWarning("QPainter::setOpacity: Painter not active");
2072 opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2074 if (opacity == d->state->opacity)
2077 d->state->opacity = opacity;
2080 d->extended->opacityChanged();
2082 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2087 Returns the currently set brush origin.
2089 \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2092 QPoint QPainter::brushOrigin() const
2094 Q_D(const QPainter);
2096 qWarning("QPainter::brushOrigin: Painter not active");
2099 return QPointF(d->state->brushOrigin).toPoint();
2103 \fn void QPainter::setBrushOrigin(const QPointF &position)
2105 Sets the brush origin to \a position.
2107 The brush origin specifies the (0, 0) coordinate of the painter's
2110 Note that while the brushOrigin() was necessary to adopt the
2111 parent's background for a widget in Qt 3, this is no longer the
2112 case since the Qt 4 painter doesn't paint the background unless
2113 you explicitly tell it to do so by setting the widget's \l
2114 {QWidget::autoFillBackground}{autoFillBackground} property to
2117 \sa brushOrigin(), {QPainter#Settings}{Settings}
2120 void QPainter::setBrushOrigin(const QPointF &p)
2123 #ifdef QT_DEBUG_DRAW
2124 if (qt_show_painter_debug_output)
2125 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2129 qWarning("QPainter::setBrushOrigin: Painter not active");
2133 d->state->brushOrigin = p;
2136 d->extended->brushOriginChanged();
2140 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2144 \fn void QPainter::setBrushOrigin(const QPoint &position)
2147 Sets the brush's origin to the given \a position.
2151 \fn void QPainter::setBrushOrigin(int x, int y)
2155 Sets the brush's origin to point (\a x, \a y).
2159 \enum QPainter::CompositionMode
2161 Defines the modes supported for digital image compositing.
2162 Composition modes are used to specify how the pixels in one image,
2163 the source, are merged with the pixel in another image, the
2166 Please note that the bitwise raster operation modes, denoted with
2167 a RasterOp prefix, are only natively supported in the X11 and
2168 raster paint engines. This means that the only way to utilize
2169 these modes on the Mac is via a QImage. The RasterOp denoted blend
2170 modes are \e not supported for pens and brushes with alpha
2171 components. Also, turning on the QPainter::Antialiasing render
2172 hint will effectively disable the RasterOp modes.
2175 \image qpainter-compositionmode1.png
2176 \image qpainter-compositionmode2.png
2178 The most common type is SourceOver (often referred to as just
2179 alpha blending) where the source pixel is blended on top of the
2180 destination pixel in such a way that the alpha component of the
2181 source defines the translucency of the pixel.
2183 When the paint device is a QImage, the image format must be set to
2184 \l {QImage::Format}{Format_ARGB32_Premultiplied} or
2185 \l {QImage::Format}{Format_ARGB32} for the composition modes to have
2186 any effect. For performance the premultiplied version is the preferred
2189 When a composition mode is set it applies to all painting
2190 operator, pens, brushes, gradients and pixmap/image drawing.
2192 \value CompositionMode_SourceOver This is the default mode. The
2193 alpha of the source is used to blend the pixel on top of the
2196 \value CompositionMode_DestinationOver The alpha of the
2197 destination is used to blend it on top of the source pixels. This
2198 mode is the inverse of CompositionMode_SourceOver.
2200 \value CompositionMode_Clear The pixels in the destination are
2201 cleared (set to fully transparent) independent of the source.
2203 \value CompositionMode_Source The output is the source
2204 pixel. (This means a basic copy operation and is identical to
2205 SourceOver when the source pixel is opaque).
2207 \value CompositionMode_Destination The output is the destination
2208 pixel. This means that the blending has no effect. This mode is
2209 the inverse of CompositionMode_Source.
2211 \value CompositionMode_SourceIn The output is the source, where
2212 the alpha is reduced by that of the destination.
2214 \value CompositionMode_DestinationIn The output is the
2215 destination, where the alpha is reduced by that of the
2216 source. This mode is the inverse of CompositionMode_SourceIn.
2218 \value CompositionMode_SourceOut The output is the source, where
2219 the alpha is reduced by the inverse of destination.
2221 \value CompositionMode_DestinationOut The output is the
2222 destination, where the alpha is reduced by the inverse of the
2223 source. This mode is the inverse of CompositionMode_SourceOut.
2225 \value CompositionMode_SourceAtop The source pixel is blended on
2226 top of the destination, with the alpha of the source pixel reduced
2227 by the alpha of the destination pixel.
2229 \value CompositionMode_DestinationAtop The destination pixel is
2230 blended on top of the source, with the alpha of the destination
2231 pixel is reduced by the alpha of the destination pixel. This mode
2232 is the inverse of CompositionMode_SourceAtop.
2234 \value CompositionMode_Xor The source, whose alpha is reduced with
2235 the inverse of the destination alpha, is merged with the
2236 destination, whose alpha is reduced by the inverse of the source
2237 alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2239 \value CompositionMode_Plus Both the alpha and color of the source
2240 and destination pixels are added together.
2242 \value CompositionMode_Multiply The output is the source color
2243 multiplied by the destination. Multiplying a color with white
2244 leaves the color unchanged, while multiplying a color
2245 with black produces black.
2247 \value CompositionMode_Screen The source and destination colors
2248 are inverted and then multiplied. Screening a color with white
2249 produces white, whereas screening a color with black leaves the
2252 \value CompositionMode_Overlay Multiplies or screens the colors
2253 depending on the destination color. The destination color is mixed
2254 with the source color to reflect the lightness or darkness of the
2257 \value CompositionMode_Darken The darker of the source and
2258 destination colors is selected.
2260 \value CompositionMode_Lighten The lighter of the source and
2261 destination colors is selected.
2263 \value CompositionMode_ColorDodge The destination color is
2264 brightened to reflect the source color. A black source color
2265 leaves the destination color unchanged.
2267 \value CompositionMode_ColorBurn The destination color is darkened
2268 to reflect the source color. A white source color leaves the
2269 destination color unchanged.
2271 \value CompositionMode_HardLight Multiplies or screens the colors
2272 depending on the source color. A light source color will lighten
2273 the destination color, whereas a dark source color will darken the
2276 \value CompositionMode_SoftLight Darkens or lightens the colors
2277 depending on the source color. Similar to
2278 CompositionMode_HardLight.
2280 \value CompositionMode_Difference Subtracts the darker of the
2281 colors from the lighter. Painting with white inverts the
2282 destination color, whereas painting with black leaves the
2283 destination color unchanged.
2285 \value CompositionMode_Exclusion Similar to
2286 CompositionMode_Difference, but with a lower contrast. Painting
2287 with white inverts the destination color, whereas painting with
2288 black leaves the destination color unchanged.
2290 \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2291 the source and destination pixels (src OR dst).
2293 \value RasterOp_SourceAndDestination Does a bitwise AND operation
2294 on the source and destination pixels (src AND dst).
2296 \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2297 on the source and destination pixels (src XOR dst).
2299 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2300 operation on the source and destination pixels ((NOT src) AND (NOT
2303 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2304 operation on the source and destination pixels ((NOT src) OR (NOT
2307 \value RasterOp_NotSourceXorDestination Does a bitwise operation
2308 where the source pixels are inverted and then XOR'ed with the
2309 destination ((NOT src) XOR dst).
2311 \value RasterOp_NotSource Does a bitwise operation where the
2312 source pixels are inverted (NOT src).
2314 \value RasterOp_NotSourceAndDestination Does a bitwise operation
2315 where the source is inverted and then AND'ed with the destination
2316 ((NOT src) AND dst).
2318 \value RasterOp_SourceAndNotDestination Does a bitwise operation
2319 where the source is AND'ed with the inverted destination pixels
2320 (src AND (NOT dst)).
2322 \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2323 Modes}{Composition Modes}, {Image Composition Example}
2327 Sets the composition mode to the given \a mode.
2329 \warning Only a QPainter operating on a QImage fully supports all
2330 composition modes. The RasterOp modes are supported for X11 as
2331 described in compositionMode().
2333 \sa compositionMode()
2335 void QPainter::setCompositionMode(CompositionMode mode)
2339 qWarning("QPainter::setCompositionMode: Painter not active");
2342 if (d->state->composition_mode == mode)
2345 d->state->composition_mode = mode;
2346 d->extended->compositionModeChanged();
2350 if (mode >= QPainter::RasterOp_SourceOrDestination) {
2351 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2352 qWarning("QPainter::setCompositionMode: "
2353 "Raster operation modes not supported on device");
2356 } else if (mode >= QPainter::CompositionMode_Plus) {
2357 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2358 qWarning("QPainter::setCompositionMode: "
2359 "Blend modes not supported on device");
2362 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2363 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2364 qWarning("QPainter::setCompositionMode: "
2365 "PorterDuff modes not supported on device");
2370 d->state->composition_mode = mode;
2371 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2375 Returns the current composition mode.
2377 \sa CompositionMode, setCompositionMode()
2379 QPainter::CompositionMode QPainter::compositionMode() const
2381 Q_D(const QPainter);
2383 qWarning("QPainter::compositionMode: Painter not active");
2384 return QPainter::CompositionMode_SourceOver;
2386 return d->state->composition_mode;
2390 Returns the current background brush.
2392 \sa setBackground(), {QPainter#Settings}{Settings}
2395 const QBrush &QPainter::background() const
2397 Q_D(const QPainter);
2399 qWarning("QPainter::background: Painter not active");
2400 return d->fakeState()->brush;
2402 return d->state->bgBrush;
2407 Returns true if clipping has been set; otherwise returns false.
2409 \sa setClipping(), {QPainter#Clipping}{Clipping}
2412 bool QPainter::hasClipping() const
2414 Q_D(const QPainter);
2416 qWarning("QPainter::hasClipping: Painter not active");
2419 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2424 Enables clipping if \a enable is true, or disables clipping if \a
2427 \sa hasClipping(), {QPainter#Clipping}{Clipping}
2430 void QPainter::setClipping(bool enable)
2433 #ifdef QT_DEBUG_DRAW
2434 if (qt_show_painter_debug_output)
2435 printf("QPainter::setClipping(), enable=%s, was=%s\n",
2436 enable ? "on" : "off",
2437 hasClipping() ? "on" : "off");
2440 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2444 if (hasClipping() == enable)
2447 // we can't enable clipping if we don't have a clip
2449 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2451 d->state->clipEnabled = enable;
2454 d->extended->clipEnabledChanged();
2458 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2459 d->updateState(d->state);
2464 Returns the currently set clip region. Note that the clip region
2465 is given in logical coordinates.
2467 \warning QPainter does not store the combined clip explicitly as
2468 this is handled by the underlying QPaintEngine, so the path is
2469 recreated on demand and transformed to the current logical
2470 coordinate system. This is potentially an expensive operation.
2472 \sa setClipRegion(), clipPath(), setClipping()
2475 QRegion QPainter::clipRegion() const
2477 Q_D(const QPainter);
2479 qWarning("QPainter::clipRegion: Painter not active");
2484 bool lastWasNothing = true;
2487 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2489 // ### Falcon: Use QPainterPath
2490 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2491 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2492 switch (info.clipType) {
2494 case QPainterClipInfo::RegionClip: {
2495 QTransform matrix = (info.matrix * d->invMatrix);
2496 if (lastWasNothing) {
2497 region = info.region * matrix;
2498 lastWasNothing = false;
2501 if (info.operation == Qt::IntersectClip)
2502 region &= info.region * matrix;
2503 else if (info.operation == Qt::NoClip) {
2504 lastWasNothing = true;
2507 region = info.region * matrix;
2511 case QPainterClipInfo::PathClip: {
2512 QTransform matrix = (info.matrix * d->invMatrix);
2513 if (lastWasNothing) {
2514 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2515 info.path.fillRule());
2516 lastWasNothing = false;
2519 if (info.operation == Qt::IntersectClip) {
2520 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2521 info.path.fillRule());
2522 } else if (info.operation == Qt::NoClip) {
2523 lastWasNothing = true;
2526 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2527 info.path.fillRule());
2532 case QPainterClipInfo::RectClip: {
2533 QTransform matrix = (info.matrix * d->invMatrix);
2534 if (lastWasNothing) {
2535 region = QRegion(info.rect) * matrix;
2536 lastWasNothing = false;
2539 if (info.operation == Qt::IntersectClip) {
2540 // Use rect intersection if possible.
2541 if (matrix.type() <= QTransform::TxScale)
2542 region &= matrix.mapRect(info.rect);
2544 region &= matrix.map(QRegion(info.rect));
2545 } else if (info.operation == Qt::NoClip) {
2546 lastWasNothing = true;
2549 region = QRegion(info.rect) * matrix;
2554 case QPainterClipInfo::RectFClip: {
2555 QTransform matrix = (info.matrix * d->invMatrix);
2556 if (lastWasNothing) {
2557 region = QRegion(info.rectf.toRect()) * matrix;
2558 lastWasNothing = false;
2561 if (info.operation == Qt::IntersectClip) {
2562 // Use rect intersection if possible.
2563 if (matrix.type() <= QTransform::TxScale)
2564 region &= matrix.mapRect(info.rectf.toRect());
2566 region &= matrix.map(QRegion(info.rectf.toRect()));
2567 } else if (info.operation == Qt::NoClip) {
2568 lastWasNothing = true;
2571 region = QRegion(info.rectf.toRect()) * matrix;
2581 extern QPainterPath qt_regionToPath(const QRegion ®ion);
2584 Returns the currently clip as a path. Note that the clip path is
2585 given in logical coordinates.
2587 \warning QPainter does not store the combined clip explicitly as
2588 this is handled by the underlying QPaintEngine, so the path is
2589 recreated on demand and transformed to the current logical
2590 coordinate system. This is potentially an expensive operation.
2592 \sa setClipPath(), clipRegion(), setClipping()
2594 QPainterPath QPainter::clipPath() const
2596 Q_D(const QPainter);
2598 // ### Since we do not support path intersections and path unions yet,
2599 // we just use clipRegion() here...
2601 qWarning("QPainter::clipPath: Painter not active");
2602 return QPainterPath();
2605 // No clip, return empty
2606 if (d->state->clipInfo.size() == 0) {
2607 return QPainterPath();
2610 // Update inverse matrix, used below.
2612 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2614 // For the simple case avoid conversion.
2615 if (d->state->clipInfo.size() == 1
2616 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2617 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2618 return d->state->clipInfo.at(0).path * matrix;
2620 } else if (d->state->clipInfo.size() == 1
2621 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2622 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2624 path.addRect(d->state->clipInfo.at(0).rect);
2625 return path * matrix;
2627 // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2628 return qt_regionToPath(clipRegion());
2634 Returns the bounding rectangle of the current clip if there is a clip;
2635 otherwise returns an empty rectangle. Note that the clip region is
2636 given in logical coordinates.
2638 The bounding rectangle is not guaranteed to be tight.
2640 \sa setClipRect(), setClipPath(), setClipRegion()
2645 QRectF QPainter::clipBoundingRect() const
2647 Q_D(const QPainter);
2650 qWarning("QPainter::clipBoundingRect: Painter not active");
2654 // Accumulate the bounding box in device space. This is not 100%
2655 // precise, but it fits within the guarantee and it is reasonably
2658 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2660 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2662 if (info.clipType == QPainterClipInfo::RectClip)
2664 else if (info.clipType == QPainterClipInfo::RectFClip)
2666 else if (info.clipType == QPainterClipInfo::RegionClip)
2667 r = info.region.boundingRect();
2669 r = info.path.boundingRect();
2671 r = info.matrix.mapRect(r);
2675 else if (info.operation == Qt::IntersectClip)
2680 // Map the rectangle back into logical space using the inverse
2683 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2685 return d->invMatrix.mapRect(bounds);
2689 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2691 Enables clipping, and sets the clip region to the given \a
2692 rectangle using the given clip \a operation. The default operation
2693 is to replace the current clip rectangle.
2695 Note that the clip rectangle is specified in logical (painter)
2698 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2700 void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2705 if ((!d->state->clipEnabled && op != Qt::NoClip))
2706 op = Qt::ReplaceClip;
2709 qWarning("QPainter::setClipRect: Painter not active");
2712 qreal right = rect.x() + rect.width();
2713 qreal bottom = rect.y() + rect.height();
2714 qreal pts[] = { rect.x(), rect.y(),
2718 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2719 d->state->clipEnabled = true;
2720 d->extended->clip(vp, op);
2721 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2722 d->state->clipInfo.clear();
2723 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2724 d->state->clipOperation = op;
2728 if (qreal(int(rect.top())) == rect.top()
2729 && qreal(int(rect.bottom())) == rect.bottom()
2730 && qreal(int(rect.left())) == rect.left()
2731 && qreal(int(rect.right())) == rect.right())
2733 setClipRect(rect.toRect(), op);
2737 if (rect.isEmpty()) {
2738 setClipRegion(QRegion(), op);
2744 setClipPath(path, op);
2748 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2751 Enables clipping, and sets the clip region to the given \a rectangle using the given
2754 void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2759 qWarning("QPainter::setClipRect: Painter not active");
2763 if ((!d->state->clipEnabled && op != Qt::NoClip))
2764 op = Qt::ReplaceClip;
2767 d->state->clipEnabled = true;
2768 d->extended->clip(rect, op);
2769 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2770 d->state->clipInfo.clear();
2771 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2772 d->state->clipOperation = op;
2776 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2777 op = Qt::ReplaceClip;
2779 d->state->clipRegion = rect;
2780 d->state->clipOperation = op;
2781 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2782 d->state->clipInfo.clear();
2783 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2784 d->state->clipEnabled = true;
2785 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2786 d->updateState(d->state);
2790 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2792 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2793 with the given \a width and \a height.
2797 \fn void QPainter::setClipRegion(const QRegion ®ion, Qt::ClipOperation operation)
2799 Sets the clip region to the given \a region using the specified clip
2800 \a operation. The default clip operation is to replace the current
2803 Note that the clip region is given in logical coordinates.
2805 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2807 void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2810 #ifdef QT_DEBUG_DRAW
2811 QRect rect = r.boundingRect();
2812 if (qt_show_painter_debug_output)
2813 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2814 r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2817 qWarning("QPainter::setClipRegion: Painter not active");
2821 if ((!d->state->clipEnabled && op != Qt::NoClip))
2822 op = Qt::ReplaceClip;
2825 d->state->clipEnabled = true;
2826 d->extended->clip(r, op);
2827 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2828 d->state->clipInfo.clear();
2829 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2830 d->state->clipOperation = op;
2834 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2835 op = Qt::ReplaceClip;
2837 d->state->clipRegion = r;
2838 d->state->clipOperation = op;
2839 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2840 d->state->clipInfo.clear();
2841 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2842 d->state->clipEnabled = true;
2843 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2844 d->updateState(d->state);
2851 Sets the transformation matrix to \a matrix and enables transformations.
2853 \note It is advisable to use setWorldTransform() instead of this function to
2854 preserve the properties of perspective transformations.
2856 If \a combine is true, then \a matrix is combined with the current
2857 transformation matrix; otherwise \a matrix replaces the current
2858 transformation matrix.
2860 If \a matrix is the identity matrix and \a combine is false, this
2861 function calls setWorldMatrixEnabled(false). (The identity matrix is the
2862 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2865 The following functions can transform the coordinate system without using
2874 They operate on the painter's worldMatrix() and are implemented like this:
2876 \snippet code/src_gui_painting_qpainter.cpp 4
2878 Note that when using setWorldMatrix() function you should always have
2879 \a combine be true when you are drawing into a QPicture. Otherwise
2880 it may not be possible to replay the picture with additional
2881 transformations; using the translate(), scale(), etc. convenience
2884 For more information about the coordinate system, transformations
2885 and window-viewport conversion, see \l {Coordinate System}.
2887 \sa setWorldTransform(), QTransform
2890 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2892 setWorldTransform(QTransform(matrix), combine);
2899 Returns the world transformation matrix.
2901 It is advisable to use worldTransform() because worldMatrix() does not
2902 preserve the properties of perspective transformations.
2904 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2908 const QMatrix &QPainter::worldMatrix() const
2910 Q_D(const QPainter);
2912 qWarning("QPainter::worldMatrix: Painter not active");
2913 return d->fakeState()->transform.toAffine();
2915 return d->state->worldMatrix.toAffine();
2921 Use setWorldTransform() instead.
2923 \sa setWorldTransform()
2926 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
2928 setWorldTransform(QTransform(matrix), combine);
2934 Use worldTransform() instead.
2936 \sa worldTransform()
2939 const QMatrix &QPainter::matrix() const
2941 return worldMatrix();
2949 Returns the transformation matrix combining the current
2950 window/viewport and world transformation.
2952 It is advisable to use combinedTransform() instead of this
2953 function to preserve the properties of perspective transformations.
2955 \sa setWorldTransform(), setWindow(), setViewport()
2957 QMatrix QPainter::combinedMatrix() const
2959 return combinedTransform().toAffine();
2966 Returns the matrix that transforms from logical coordinates to
2967 device coordinates of the platform dependent paint device.
2969 \note It is advisable to use deviceTransform() instead of this
2970 function to preserve the properties of perspective transformations.
2972 This function is \e only needed when using platform painting
2973 commands on the platform dependent handle (Qt::HANDLE), and the
2974 platform does not do transformations nativly.
2976 The QPaintEngine::PaintEngineFeature enum can be queried to
2977 determine whether the platform performs the transformations or
2980 \sa worldMatrix(), QPaintEngine::hasFeature(),
2982 const QMatrix &QPainter::deviceMatrix() const
2984 Q_D(const QPainter);
2986 qWarning("QPainter::deviceMatrix: Painter not active");
2987 return d->fakeState()->transform.toAffine();
2989 return d->state->matrix.toAffine();
2995 Resets any transformations that were made using translate(), scale(),
2996 shear(), rotate(), setWorldMatrix(), setViewport() and
2999 It is advisable to use resetTransform() instead of this function
3000 to preserve the properties of perspective transformations.
3002 \sa {QPainter#Coordinate Transformations}{Coordinate
3006 void QPainter::resetMatrix()
3015 Enables transformations if \a enable is true, or disables
3016 transformations if \a enable is false. The world transformation
3017 matrix is not changed.
3019 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3020 Transformations}{Coordinate Transformations}
3023 void QPainter::setWorldMatrixEnabled(bool enable)
3026 #ifdef QT_DEBUG_DRAW
3027 if (qt_show_painter_debug_output)
3028 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3032 qWarning("QPainter::setMatrixEnabled: Painter not active");
3035 if (enable == d->state->WxF)
3038 d->state->WxF = enable;
3045 Returns true if world transformation is enabled; otherwise returns
3048 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3051 bool QPainter::worldMatrixEnabled() const
3053 Q_D(const QPainter);
3055 qWarning("QPainter::worldMatrixEnabled: Painter not active");
3058 return d->state->WxF;
3064 Use setWorldMatrixEnabled() instead.
3066 \sa setWorldMatrixEnabled()
3069 void QPainter::setMatrixEnabled(bool enable)
3071 setWorldMatrixEnabled(enable);
3077 Use worldMatrixEnabled() instead
3079 \sa worldMatrixEnabled()
3082 bool QPainter::matrixEnabled() const
3084 return worldMatrixEnabled();
3088 Scales the coordinate system by (\a{sx}, \a{sy}).
3090 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3093 void QPainter::scale(qreal sx, qreal sy)
3095 #ifdef QT_DEBUG_DRAW
3096 if (qt_show_painter_debug_output)
3097 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3101 qWarning("QPainter::scale: Painter not active");
3105 d->state->worldMatrix.scale(sx,sy);
3106 d->state->WxF = true;
3111 Shears the coordinate system by (\a{sh}, \a{sv}).
3113 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3116 void QPainter::shear(qreal sh, qreal sv)
3118 #ifdef QT_DEBUG_DRAW
3119 if (qt_show_painter_debug_output)
3120 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3124 qWarning("QPainter::shear: Painter not active");
3128 d->state->worldMatrix.shear(sh, sv);
3129 d->state->WxF = true;
3134 \fn void QPainter::rotate(qreal angle)
3136 Rotates the coordinate system the given \a angle clockwise.
3138 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3141 void QPainter::rotate(qreal a)
3143 #ifdef QT_DEBUG_DRAW
3144 if (qt_show_painter_debug_output)
3145 printf("QPainter::rotate(), angle=%f\n", a);
3149 qWarning("QPainter::rotate: Painter not active");
3153 d->state->worldMatrix.rotate(a);
3154 d->state->WxF = true;
3159 Translates the coordinate system by the given \a offset; i.e. the
3160 given \a offset is added to points.
3162 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3164 void QPainter::translate(const QPointF &offset)
3166 qreal dx = offset.x();
3167 qreal dy = offset.y();
3168 #ifdef QT_DEBUG_DRAW
3169 if (qt_show_painter_debug_output)
3170 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3174 qWarning("QPainter::translate: Painter not active");
3178 d->state->worldMatrix.translate(dx, dy);
3179 d->state->WxF = true;
3184 \fn void QPainter::translate(const QPoint &offset)
3187 Translates the coordinate system by the given \a offset.
3191 \fn void QPainter::translate(qreal dx, qreal dy)
3194 Translates the coordinate system by the vector (\a dx, \a dy).
3198 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3200 Enables clipping, and sets the clip path for the painter to the
3201 given \a path, with the clip \a operation.
3203 Note that the clip path is specified in logical (painter)
3206 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3209 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3211 #ifdef QT_DEBUG_DRAW
3212 if (qt_show_painter_debug_output) {
3213 QRectF b = path.boundingRect();
3214 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3215 path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3221 qWarning("QPainter::setClipPath: Painter not active");
3225 if ((!d->state->clipEnabled && op != Qt::NoClip))
3226 op = Qt::ReplaceClip;
3229 d->state->clipEnabled = true;
3230 d->extended->clip(path, op);
3231 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3232 d->state->clipInfo.clear();
3233 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3234 d->state->clipOperation = op;
3238 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
3239 op = Qt::ReplaceClip;
3241 d->state->clipPath = path;
3242 d->state->clipOperation = op;
3243 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3244 d->state->clipInfo.clear();
3245 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3246 d->state->clipEnabled = true;
3247 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3248 d->updateState(d->state);
3252 Draws the outline (strokes) the path \a path with the pen specified
3255 \sa fillPath(), {QPainter#Drawing}{Drawing}
3257 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3262 qWarning("QPainter::strokePath: Painter not active");
3270 const QGradient *g = qpen_brush(pen).gradient();
3271 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3272 d->extended->stroke(qtVectorPathForPath(path), pen);
3277 QBrush oldBrush = d->state->brush;
3278 QPen oldPen = d->state->pen;
3281 setBrush(Qt::NoBrush);
3291 Fills the given \a path using the given \a brush. The outline is
3294 Alternatively, you can specify a QColor instead of a QBrush; the
3295 QBrush constructor (taking a QColor argument) will automatically
3296 create a solid pattern brush.
3300 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3305 qWarning("QPainter::fillPath: Painter not active");
3313 const QGradient *g = brush.gradient();
3314 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3315 d->extended->fill(qtVectorPathForPath(path), brush);
3320 QBrush oldBrush = d->state->brush;
3321 QPen oldPen = d->state->pen;
3334 Draws the given painter \a path using the current pen for outline
3335 and the current brush for filling.
3339 \li \inlineimage qpainter-path.png
3341 \snippet code/src_gui_painting_qpainter.cpp 5
3344 \sa {painting/painterpaths}{the Painter Paths
3345 example},{painting/deform}{the Vector Deformation example}
3347 void QPainter::drawPath(const QPainterPath &path)
3349 #ifdef QT_DEBUG_DRAW
3350 QRectF pathBounds = path.boundingRect();
3351 if (qt_show_painter_debug_output)
3352 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3353 path.elementCount(),
3354 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3360 qWarning("QPainter::drawPath: Painter not active");
3365 d->extended->drawPath(path);
3368 d->updateState(d->state);
3370 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3371 d->engine->drawPath(path);
3373 d->draw_helper(path);
3378 \fn void QPainter::drawLine(const QLineF &line)
3380 Draws a line defined by \a line.
3384 \li \inlineimage qpainter-line.png
3386 \snippet code/src_gui_painting_qpainter.cpp 6
3389 \sa drawLines(), drawPolyline(), {Coordinate System}
3393 \fn void QPainter::drawLine(const QLine &line)
3396 Draws a line defined by \a line.
3400 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3403 Draws a line from \a p1 to \a p2.
3407 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3410 Draws a line from \a p1 to \a p2.
3414 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3417 Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3418 current pen position to (\a x2, \a y2).
3422 \fn void QPainter::drawRect(const QRectF &rectangle)
3424 Draws the current \a rectangle with the current pen and brush.
3426 A filled rectangle has a size of \a{rectangle}.size(). A stroked
3427 rectangle has a size of \a{rectangle}.size() plus the pen width.
3431 \li \inlineimage qpainter-rectangle.png
3433 \snippet code/src_gui_painting_qpainter.cpp 7
3436 \sa drawRects(), drawPolygon(), {Coordinate System}
3440 \fn void QPainter::drawRect(const QRect &rectangle)
3444 Draws the current \a rectangle with the current pen and brush.
3448 \fn void QPainter::drawRect(int x, int y, int width, int height)
3452 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3453 with the given \a width and \a height.
3457 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3459 Draws the first \a rectCount of the given \a rectangles using the
3460 current pen and brush.
3464 void QPainter::drawRects(const QRectF *rects, int rectCount)
3466 #ifdef QT_DEBUG_DRAW
3467 if (qt_show_painter_debug_output)
3468 printf("QPainter::drawRects(), count=%d\n", rectCount);
3473 qWarning("QPainter::drawRects: Painter not active");
3481 d->extended->drawRects(rects, rectCount);
3485 d->updateState(d->state);
3487 if (!d->state->emulationSpecifier) {
3488 d->engine->drawRects(rects, rectCount);
3492 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3493 && d->state->matrix.type() == QTransform::TxTranslate) {
3494 for (int i=0; i<rectCount; ++i) {
3495 QRectF r(rects[i].x() + d->state->matrix.dx(),
3496 rects[i].y() + d->state->matrix.dy(),
3499 d->engine->drawRects(&r, 1);
3502 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3503 for (int i=0; i<rectCount; ++i) {
3504 QPainterPath rectPath;
3505 rectPath.addRect(rects[i]);
3506 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3509 QPainterPath rectPath;
3510 for (int i=0; i<rectCount; ++i)
3511 rectPath.addRect(rects[i]);
3512 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3518 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3521 Draws the first \a rectCount of the given \a rectangles using the
3522 current pen and brush.
3524 void QPainter::drawRects(const QRect *rects, int rectCount)
3526 #ifdef QT_DEBUG_DRAW
3527 if (qt_show_painter_debug_output)
3528 printf("QPainter::drawRects(), count=%d\n", rectCount);
3533 qWarning("QPainter::drawRects: Painter not active");
3541 d->extended->drawRects(rects, rectCount);
3545 d->updateState(d->state);
3547 if (!d->state->emulationSpecifier) {
3548 d->engine->drawRects(rects, rectCount);
3552 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3553 && d->state->matrix.type() == QTransform::TxTranslate) {
3554 for (int i=0; i<rectCount; ++i) {
3555 QRectF r(rects[i].x() + d->state->matrix.dx(),
3556 rects[i].y() + d->state->matrix.dy(),
3560 d->engine->drawRects(&r, 1);
3563 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3564 for (int i=0; i<rectCount; ++i) {
3565 QPainterPath rectPath;
3566 rectPath.addRect(rects[i]);
3567 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3570 QPainterPath rectPath;
3571 for (int i=0; i<rectCount; ++i)
3572 rectPath.addRect(rects[i]);
3574 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3580 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3583 Draws the given \a rectangles using the current pen and brush.
3587 \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3591 Draws the given \a rectangles using the current pen and brush.
3595 \fn void QPainter::drawPoint(const QPointF &position)
3597 Draws a single point at the given \a position using the current
3600 \sa {Coordinate System}
3604 \fn void QPainter::drawPoint(const QPoint &position)
3607 Draws a single point at the given \a position using the current
3611 /*! \fn void QPainter::drawPoint(int x, int y)
3615 Draws a single point at position (\a x, \a y).
3619 Draws the first \a pointCount points in the array \a points using
3620 the current pen's color.
3622 \sa {Coordinate System}
3624 void QPainter::drawPoints(const QPointF *points, int pointCount)
3626 #ifdef QT_DEBUG_DRAW
3627 if (qt_show_painter_debug_output)
3628 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3633 qWarning("QPainter::drawPoints: Painter not active");
3637 if (pointCount <= 0)
3641 d->extended->drawPoints(points, pointCount);
3645 d->updateState(d->state);
3647 if (!d->state->emulationSpecifier) {
3648 d->engine->drawPoints(points, pointCount);
3652 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3653 && d->state->matrix.type() == QTransform::TxTranslate) {
3654 // ### use drawPoints function
3655 for (int i=0; i<pointCount; ++i) {
3656 QPointF pt(points[i].x() + d->state->matrix.dx(),
3657 points[i].y() + d->state->matrix.dy());
3658 d->engine->drawPoints(&pt, 1);
3661 QPen pen = d->state->pen;
3662 bool flat_pen = pen.capStyle() == Qt::FlatCap;
3665 pen.setCapStyle(Qt::SquareCap);
3669 for (int i=0; i<pointCount; ++i) {
3670 path.moveTo(points[i].x(), points[i].y());
3671 path.lineTo(points[i].x() + 0.0001, points[i].y());
3673 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3682 Draws the first \a pointCount points in the array \a points using
3683 the current pen's color.
3686 void QPainter::drawPoints(const QPoint *points, int pointCount)
3688 #ifdef QT_DEBUG_DRAW
3689 if (qt_show_painter_debug_output)
3690 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3695 qWarning("QPainter::drawPoints: Painter not active");
3699 if (pointCount <= 0)
3703 d->extended->drawPoints(points, pointCount);
3707 d->updateState(d->state);
3709 if (!d->state->emulationSpecifier) {
3710 d->engine->drawPoints(points, pointCount);
3714 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3715 && d->state->matrix.type() == QTransform::TxTranslate) {
3716 // ### use drawPoints function
3717 for (int i=0; i<pointCount; ++i) {
3718 QPointF pt(points[i].x() + d->state->matrix.dx(),
3719 points[i].y() + d->state->matrix.dy());
3720 d->engine->drawPoints(&pt, 1);
3723 QPen pen = d->state->pen;
3724 bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3727 pen.setCapStyle(Qt::SquareCap);
3731 for (int i=0; i<pointCount; ++i) {
3732 path.moveTo(points[i].x(), points[i].y());
3733 path.lineTo(points[i].x() + 0.0001, points[i].y());
3735 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3742 \fn void QPainter::drawPoints(const QPolygonF &points)
3746 Draws the points in the vector \a points.
3750 \fn void QPainter::drawPoints(const QPolygon &points)
3754 Draws the points in the vector \a points.
3758 Sets the background mode of the painter to the given \a mode
3760 Qt::TransparentMode (the default) draws stippled lines and text
3761 without setting the background pixels. Qt::OpaqueMode fills these
3762 space with the current background color.
3764 Note that in order to draw a bitmap or pixmap transparently, you
3765 must use QPixmap::setMask().
3767 \sa backgroundMode(), setBackground(),
3768 {QPainter#Settings}{Settings}
3771 void QPainter::setBackgroundMode(Qt::BGMode mode)
3773 #ifdef QT_DEBUG_DRAW
3774 if (qt_show_painter_debug_output)
3775 printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3780 qWarning("QPainter::setBackgroundMode: Painter not active");
3783 if (d->state->bgMode == mode)
3786 d->state->bgMode = mode;
3788 d->checkEmulation();
3790 d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3795 Returns the current background mode.
3797 \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3799 Qt::BGMode QPainter::backgroundMode() const
3801 Q_D(const QPainter);
3803 qWarning("QPainter::backgroundMode: Painter not active");
3804 return Qt::TransparentMode;
3806 return d->state->bgMode;
3813 Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3817 void QPainter::setPen(const QColor &color)
3819 #ifdef QT_DEBUG_DRAW
3820 if (qt_show_painter_debug_output)
3821 printf("QPainter::setPen(), color=%04x\n", color.rgb());
3825 qWarning("QPainter::setPen: Painter not active");
3829 if (d->state->pen.style() == Qt::SolidLine
3830 && d->state->pen.widthF() == 0
3831 && d->state->pen.isSolid()
3832 && d->state->pen.color() == color)
3835 QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
3837 d->state->pen = pen;
3839 d->extended->penChanged();
3841 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3845 Sets the painter's pen to be the given \a pen.
3847 The \a pen defines how to draw lines and outlines, and it also
3848 defines the text color.
3850 \sa pen(), {QPainter#Settings}{Settings}
3853 void QPainter::setPen(const QPen &pen)
3856 #ifdef QT_DEBUG_DRAW
3857 if (qt_show_painter_debug_output)
3858 printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3859 pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3863 qWarning("QPainter::setPen: Painter not active");
3867 if (d->state->pen == pen)
3870 d->state->pen = pen;
3873 d->checkEmulation();
3874 d->extended->penChanged();
3878 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3884 Sets the painter's pen to have the given \a style, width 0 and
3888 void QPainter::setPen(Qt::PenStyle style)
3892 qWarning("QPainter::setPen: Painter not active");
3896 if (d->state->pen.style() == style
3897 && (style == Qt::NoPen || (d->state->pen.widthF() == 0
3898 && d->state->pen.isSolid()
3899 && d->state->pen.color() == QColor(Qt::black))))
3902 // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
3903 // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
3904 d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
3907 d->extended->penChanged();
3909 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3914 Returns the painter's current pen.
3916 \sa setPen(), {QPainter#Settings}{Settings}
3919 const QPen &QPainter::pen() const
3921 Q_D(const QPainter);
3923 qWarning("QPainter::pen: Painter not active");
3924 return d->fakeState()->pen;
3926 return d->state->pen;
3931 Sets the painter's brush to the given \a brush.
3933 The painter's brush defines how shapes are filled.
3935 \sa brush(), {QPainter#Settings}{Settings}
3938 void QPainter::setBrush(const QBrush &brush)
3940 #ifdef QT_DEBUG_DRAW
3941 if (qt_show_painter_debug_output)
3942 printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
3946 qWarning("QPainter::setBrush: Painter not active");
3950 if (d->state->brush.d == brush.d)
3954 d->state->brush = brush;
3955 d->checkEmulation();
3956 d->extended->brushChanged();
3960 d->state->brush = brush;
3961 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
3968 Sets the painter's brush to black color and the specified \a
3972 void QPainter::setBrush(Qt::BrushStyle style)
3976 qWarning("QPainter::setBrush: Painter not active");
3979 if (d->state->brush.style() == style &&
3980 (style == Qt::NoBrush
3981 || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
3983 d->state->brush = QBrush(Qt::black, style);
3985 d->extended->brushChanged();
3987 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
3991 Returns the painter's current brush.
3993 \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
3996 const QBrush &QPainter::brush() const
3998 Q_D(const QPainter);
4000 qWarning("QPainter::brush: Painter not active");
4001 return d->fakeState()->brush;
4003 return d->state->brush;
4007 \fn void QPainter::setBackground(const QBrush &brush)
4009 Sets the background brush of the painter to the given \a brush.
4011 The background brush is the brush that is filled in when drawing
4012 opaque text, stippled lines and bitmaps. The background brush has
4013 no effect in transparent background mode (which is the default).
4015 \sa background(), setBackgroundMode(),
4016 {QPainter#Settings}{Settings}
4019 void QPainter::setBackground(const QBrush &bg)
4021 #ifdef QT_DEBUG_DRAW
4022 if (qt_show_painter_debug_output)
4023 printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4028 qWarning("QPainter::setBackground: Painter not active");
4031 d->state->bgBrush = bg;
4033 d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4037 Sets the painter's font to the given \a font.
4039 This font is used by subsequent drawText() functions. The text
4040 color is the same as the pen color.
4042 If you set a font that isn't available, Qt finds a close match.
4043 font() will return what you set using setFont() and fontInfo() returns the
4044 font actually being used (which may be the same).
4046 \sa font(), drawText(), {QPainter#Settings}{Settings}
4049 void QPainter::setFont(const QFont &font)
4053 #ifdef QT_DEBUG_DRAW
4054 if (qt_show_painter_debug_output)
4055 printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4059 qWarning("QPainter::setFont: Painter not active");
4063 d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4065 d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4069 Returns the currently set font used for drawing text.
4071 \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4073 const QFont &QPainter::font() const
4075 Q_D(const QPainter);
4077 qWarning("QPainter::font: Painter not active");
4078 return d->fakeState()->font;
4080 return d->state->font;
4086 Draws the given rectangle \a rect with rounded corners.
4088 The \a xRadius and \a yRadius arguments specify the radii
4089 of the ellipses defining the corners of the rounded rectangle.
4090 When \a mode is Qt::RelativeSize, \a xRadius and
4091 \a yRadius are specified in percentage of half the rectangle's
4092 width and height respectively, and should be in the range
4095 A filled rectangle has a size of rect.size(). A stroked rectangle
4096 has a size of rect.size() plus the pen width.
4100 \li \inlineimage qpainter-roundrect.png
4102 \snippet code/src_gui_painting_qpainter.cpp 8
4105 \sa drawRect(), QPen
4107 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4109 #ifdef QT_DEBUG_DRAW
4110 if (qt_show_painter_debug_output)
4111 printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4118 if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
4124 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4129 path.addRoundedRect(rect, xRadius, yRadius, mode);
4134 \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4135 Qt::SizeMode mode = Qt::AbsoluteSize);
4139 Draws the given rectangle \a rect with rounded corners.
4143 \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4144 Qt::SizeMode mode = Qt::AbsoluteSize);
4148 Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4154 Draws a rectangle \a r with rounded corners.
4156 The \a xRnd and \a yRnd arguments specify how rounded the corners
4157 should be. 0 is angled corners, 99 is maximum roundedness.
4159 A filled rectangle has a size of r.size(). A stroked rectangle
4160 has a size of r.size() plus the pen width.
4162 \sa drawRoundedRect()
4164 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4166 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4171 \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4176 Draws the rectangle \a r with rounded corners.
4182 \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4186 Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4190 \fn void QPainter::drawEllipse(const QRectF &rectangle)
4192 Draws the ellipse defined by the given \a rectangle.
4194 A filled ellipse has a size of \a{rectangle}.\l
4195 {QRect::size()}{size()}. A stroked ellipse has a size of
4196 \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4200 \li \inlineimage qpainter-ellipse.png
4202 \snippet code/src_gui_painting_qpainter.cpp 9
4205 \sa drawPie(), {Coordinate System}
4207 void QPainter::drawEllipse(const QRectF &r)
4209 #ifdef QT_DEBUG_DRAW
4210 if (qt_show_painter_debug_output)
4211 printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4218 QRectF rect(r.normalized());
4221 d->extended->drawEllipse(rect);
4225 d->updateState(d->state);
4226 if (d->state->emulationSpecifier) {
4227 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4228 && d->state->matrix.type() == QTransform::TxTranslate) {
4229 rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4232 path.addEllipse(rect);
4233 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4238 d->engine->drawEllipse(rect);
4242 \fn QPainter::drawEllipse(const QRect &rectangle)
4246 Draws the ellipse defined by the given \a rectangle.
4248 void QPainter::drawEllipse(const QRect &r)
4250 #ifdef QT_DEBUG_DRAW
4251 if (qt_show_painter_debug_output)
4252 printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4259 QRect rect(r.normalized());
4262 d->extended->drawEllipse(rect);
4266 d->updateState(d->state);
4268 if (d->state->emulationSpecifier) {
4269 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4270 && d->state->matrix.type() == QTransform::TxTranslate) {
4271 rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4274 path.addEllipse(rect);
4275 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4280 d->engine->drawEllipse(rect);
4284 \fn QPainter::drawEllipse(int x, int y, int width, int height)
4288 Draws the ellipse defined by the rectangle beginning at (\a{x},
4289 \a{y}) with the given \a width and \a height.
4295 \fn QPainter::drawEllipse(const QPointF ¢er, qreal rx, qreal ry)
4299 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4305 \fn QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)
4309 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4313 \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4315 Draws the arc defined by the given \a rectangle, \a startAngle and
4318 The \a startAngle and \a spanAngle must be specified in 1/16th of
4319 a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4320 values for the angles mean counter-clockwise while negative values
4321 mean the clockwise direction. Zero degrees is at the 3 o'clock
4326 \li \inlineimage qpainter-arc.png
4328 \snippet code/src_gui_painting_qpainter.cpp 10
4331 \sa drawPie(), drawChord(), {Coordinate System}
4334 void QPainter::drawArc(const QRectF &r, int a, int alen)
4336 #ifdef QT_DEBUG_DRAW
4337 if (qt_show_painter_debug_output)
4338 printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4339 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4346 QRectF rect = r.normalized();
4349 path.arcMoveTo(rect, a/16.0);
4350 path.arcTo(rect, a/16.0, alen/16.0);
4351 strokePath(path, d->state->pen);
4354 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4359 Draws the arc defined by the given \a rectangle, \a startAngle and
4364 \fn void QPainter::drawArc(int x, int y, int width, int height,
4365 int startAngle, int spanAngle)
4369 Draws the arc defined by the rectangle beginning at (\a x, \a y)
4370 with the specified \a width and \a height, and the given \a
4371 startAngle and \a spanAngle.
4375 \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4377 Draws a pie defined by the given \a rectangle, \a startAngle and
4380 The pie is filled with the current brush().
4382 The startAngle and spanAngle must be specified in 1/16th of a
4383 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4384 for the angles mean counter-clockwise while negative values mean
4385 the clockwise direction. Zero degrees is at the 3 o'clock
4390 \li \inlineimage qpainter-pie.png
4392 \snippet code/src_gui_painting_qpainter.cpp 11
4395 \sa drawEllipse(), drawChord(), {Coordinate System}
4397 void QPainter::drawPie(const QRectF &r, int a, int alen)
4399 #ifdef QT_DEBUG_DRAW
4400 if (qt_show_painter_debug_output)
4401 printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4402 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4413 if (a < 0) a += (360*16);
4416 QRectF rect = r.normalized();
4419 path.moveTo(rect.center());
4420 path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4421 path.closeSubpath();
4427 \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4430 Draws a pie defined by the given \a rectangle, \a startAngle and
4435 \fn void QPainter::drawPie(int x, int y, int width, int height, int
4436 startAngle, int spanAngle)
4440 Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4441 the specified \a width and \a height, and the given \a startAngle and
4446 \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4448 Draws the chord defined by the given \a rectangle, \a startAngle and
4449 \a spanAngle. The chord is filled with the current brush().
4451 The startAngle and spanAngle must be specified in 1/16th of a
4452 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4453 for the angles mean counter-clockwise while negative values mean
4454 the clockwise direction. Zero degrees is at the 3 o'clock
4459 \li \inlineimage qpainter-chord.png
4461 \snippet code/src_gui_painting_qpainter.cpp 12
4464 \sa drawArc(), drawPie(), {Coordinate System}
4466 void QPainter::drawChord(const QRectF &r, int a, int alen)
4468 #ifdef QT_DEBUG_DRAW
4469 if (qt_show_painter_debug_output)
4470 printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4471 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4478 QRectF rect = r.normalized();
4481 path.arcMoveTo(rect, a/16.0);
4482 path.arcTo(rect, a/16.0, alen/16.0);
4483 path.closeSubpath();
4487 \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4491 Draws the chord defined by the given \a rectangle, \a startAngle and
4496 \fn void QPainter::drawChord(int x, int y, int width, int height, int
4497 startAngle, int spanAngle)
4501 Draws the chord defined by the rectangle beginning at (\a x, \a y)
4502 with the specified \a width and \a height, and the given \a
4503 startAngle and \a spanAngle.
4508 Draws the first \a lineCount lines in the array \a lines
4509 using the current pen.
4511 \sa drawLine(), drawPolyline()
4513 void QPainter::drawLines(const QLineF *lines, int lineCount)
4515 #ifdef QT_DEBUG_DRAW
4516 if (qt_show_painter_debug_output)
4517 printf("QPainter::drawLines(), line count=%d\n", lineCount);
4522 if (!d->engine || lineCount < 1)
4526 d->extended->drawLines(lines, lineCount);
4530 d->updateState(d->state);
4532 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4534 if (lineEmulation) {
4535 if (lineEmulation == QPaintEngine::PrimitiveTransform
4536 && d->state->matrix.type() == QTransform::TxTranslate) {
4537 for (int i = 0; i < lineCount; ++i) {
4538 QLineF line = lines[i];
4539 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4540 d->engine->drawLines(&line, 1);
4543 QPainterPath linePath;
4544 for (int i = 0; i < lineCount; ++i) {
4545 linePath.moveTo(lines[i].p1());
4546 linePath.lineTo(lines[i].p2());
4548 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4552 d->engine->drawLines(lines, lineCount);
4556 \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4559 Draws the first \a lineCount lines in the array \a lines
4560 using the current pen.
4562 void QPainter::drawLines(const QLine *lines, int lineCount)
4564 #ifdef QT_DEBUG_DRAW
4565 if (qt_show_painter_debug_output)
4566 printf("QPainter::drawLine(), line count=%d\n", lineCount);
4571 if (!d->engine || lineCount < 1)
4575 d->extended->drawLines(lines, lineCount);
4579 d->updateState(d->state);
4581 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4583 if (lineEmulation) {
4584 if (lineEmulation == QPaintEngine::PrimitiveTransform
4585 && d->state->matrix.type() == QTransform::TxTranslate) {
4586 for (int i = 0; i < lineCount; ++i) {
4587 QLineF line = lines[i];
4588 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4589 d->engine->drawLines(&line, 1);
4592 QPainterPath linePath;
4593 for (int i = 0; i < lineCount; ++i) {
4594 linePath.moveTo(lines[i].p1());
4595 linePath.lineTo(lines[i].p2());
4597 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4601 d->engine->drawLines(lines, lineCount);
4607 Draws the first \a lineCount lines in the array \a pointPairs
4608 using the current pen. The lines are specified as pairs of points
4609 so the number of entries in \a pointPairs must be at least \a
4612 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4614 Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4616 drawLines((QLineF*)pointPairs, lineCount);
4622 Draws the first \a lineCount lines in the array \a pointPairs
4623 using the current pen.
4625 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4627 Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4629 drawLines((QLine*)pointPairs, lineCount);
4634 \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4637 Draws a line for each pair of points in the vector \a pointPairs
4638 using the current pen. If there is an odd number of points in the
4639 array, the last point will be ignored.
4643 \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4646 Draws a line for each pair of points in the vector \a pointPairs
4647 using the current pen.
4651 \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4654 Draws the set of lines defined by the list \a lines using the
4655 current pen and brush.
4659 \fn void QPainter::drawLines(const QVector<QLine> &lines)
4662 Draws the set of lines defined by the list \a lines using the
4663 current pen and brush.
4667 Draws the polyline defined by the first \a pointCount points in \a
4668 points using the current pen.
4670 Note that unlike the drawPolygon() function the last point is \e
4671 not connected to the first, neither is the polyline filled.
4676 \snippet code/src_gui_painting_qpainter.cpp 13
4679 \sa drawLines(), drawPolygon(), {Coordinate System}
4681 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4683 #ifdef QT_DEBUG_DRAW
4684 if (qt_show_painter_debug_output)
4685 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4689 if (!d->engine || pointCount < 2)
4693 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4697 d->updateState(d->state);
4699 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4701 if (lineEmulation) {
4703 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4704 // && d->state->matrix.type() == QTransform::TxTranslate) {
4706 QPainterPath polylinePath(points[0]);
4707 for (int i=1; i<pointCount; ++i)
4708 polylinePath.lineTo(points[i]);
4709 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4712 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4719 Draws the polyline defined by the first \a pointCount points in \a
4720 points using the current pen.
4722 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4724 #ifdef QT_DEBUG_DRAW
4725 if (qt_show_painter_debug_output)
4726 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4730 if (!d->engine || pointCount < 2)
4734 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4738 d->updateState(d->state);
4740 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4742 if (lineEmulation) {
4744 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4745 // && d->state->matrix.type() == QTransform::TxTranslate) {
4747 QPainterPath polylinePath(points[0]);
4748 for (int i=1; i<pointCount; ++i)
4749 polylinePath.lineTo(points[i]);
4750 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4753 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4758 \fn void QPainter::drawPolyline(const QPolygonF &points)
4762 Draws the polyline defined by the given \a points using the
4767 \fn void QPainter::drawPolyline(const QPolygon &points)
4771 Draws the polyline defined by the given \a points using the
4776 Draws the polygon defined by the first \a pointCount points in the
4777 array \a points using the current pen and brush.
4781 \li \inlineimage qpainter-polygon.png
4783 \snippet code/src_gui_painting_qpainter.cpp 14
4786 The first point is implicitly connected to the last point, and the
4787 polygon is filled with the current brush().
4789 If \a fillRule is Qt::WindingFill, the polygon is filled using the
4790 winding fill algorithm. If \a fillRule is Qt::OddEvenFill, the
4791 polygon is filled using the odd-even fill algorithm. See
4792 \l{Qt::FillRule} for a more detailed description of these fill
4795 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
4797 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
4799 #ifdef QT_DEBUG_DRAW
4800 if (qt_show_painter_debug_output)
4801 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4806 if (!d->engine || pointCount < 2)
4810 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4814 d->updateState(d->state);
4816 uint emulationSpecifier = d->state->emulationSpecifier;
4818 if (emulationSpecifier) {
4819 QPainterPath polygonPath(points[0]);
4820 for (int i=1; i<pointCount; ++i)
4821 polygonPath.lineTo(points[i]);
4822 polygonPath.closeSubpath();
4823 polygonPath.setFillRule(fillRule);
4824 d->draw_helper(polygonPath);
4828 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4833 Draws the polygon defined by the first \a pointCount points in the
4836 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
4838 #ifdef QT_DEBUG_DRAW
4839 if (qt_show_painter_debug_output)
4840 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4845 if (!d->engine || pointCount < 2)
4849 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4853 d->updateState(d->state);
4855 uint emulationSpecifier = d->state->emulationSpecifier;
4857 if (emulationSpecifier) {
4858 QPainterPath polygonPath(points[0]);
4859 for (int i=1; i<pointCount; ++i)
4860 polygonPath.lineTo(points[i]);
4861 polygonPath.closeSubpath();
4862 polygonPath.setFillRule(fillRule);
4863 d->draw_helper(polygonPath);
4867 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4870 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
4874 Draws the polygon defined by the given \a points using the fill
4878 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
4882 Draws the polygon defined by the given \a points using the fill
4887 \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4889 Draws the convex polygon defined by the first \a pointCount points
4890 in the array \a points using the current pen.
4894 \li \inlineimage qpainter-polygon.png
4896 \snippet code/src_gui_painting_qpainter.cpp 15
4899 The first point is implicitly connected to the last point, and the
4900 polygon is filled with the current brush(). If the supplied
4901 polygon is not convex, i.e. it contains at least one angle larger
4902 than 180 degrees, the results are undefined.
4904 On some platforms (e.g. X11), the drawConvexPolygon() function can
4905 be faster than the drawPolygon() function.
4907 \sa drawPolygon(), drawPolyline(), {Coordinate System}
4911 \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4914 Draws the convex polygon defined by the first \a pointCount points
4915 in the array \a points using the current pen.
4919 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
4923 Draws the convex polygon defined by \a polygon using the current
4928 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
4931 Draws the convex polygon defined by \a polygon using the current
4935 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4937 #ifdef QT_DEBUG_DRAW
4938 if (qt_show_painter_debug_output)
4939 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4944 if (!d->engine || pointCount < 2)
4948 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4952 d->updateState(d->state);
4954 uint emulationSpecifier = d->state->emulationSpecifier;
4956 if (emulationSpecifier) {
4957 QPainterPath polygonPath(points[0]);
4958 for (int i=1; i<pointCount; ++i)
4959 polygonPath.lineTo(points[i]);
4960 polygonPath.closeSubpath();
4961 polygonPath.setFillRule(Qt::WindingFill);
4962 d->draw_helper(polygonPath);
4966 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4969 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4971 #ifdef QT_DEBUG_DRAW
4972 if (qt_show_painter_debug_output)
4973 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4978 if (!d->engine || pointCount < 2)
4982 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4986 d->updateState(d->state);
4988 uint emulationSpecifier = d->state->emulationSpecifier;
4990 if (emulationSpecifier) {
4991 QPainterPath polygonPath(points[0]);
4992 for (int i=1; i<pointCount; ++i)
4993 polygonPath.lineTo(points[i]);
4994 polygonPath.closeSubpath();
4995 polygonPath.setFillRule(Qt::WindingFill);
4996 d->draw_helper(polygonPath);
5000 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5003 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5005 return m.inverted().map(QPointF(m.map(p).toPoint()));
5009 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5011 Draws the rectangular portion \a source of the given \a pixmap
5012 into the given \a target in the paint device.
5014 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5019 \snippet code/src_gui_painting_qpainter.cpp 16
5022 If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5023 using the pens color. If backgroundMode is Qt::OpaqueMode, the
5024 "unset" bits are drawn using the color of the background brush; if
5025 backgroundMode is Qt::TransparentMode, the "unset" bits are
5026 transparent. Drawing bitmaps with gradient or texture colors is
5031 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5033 #if defined QT_DEBUG_DRAW
5034 if (qt_show_painter_debug_output)
5035 printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5037 pm.width(), pm.height());
5042 if (!d->engine || pm.isNull())
5046 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5050 d->extended->drawPixmap(p, pm);
5058 int h = pm.height();
5063 // Emulate opaque background for bitmaps
5064 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5065 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5068 d->updateState(d->state);
5070 if ((d->state->matrix.type() > QTransform::TxTranslate
5071 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5072 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5073 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5076 // If there is no rotation involved we have to make sure we use the
5077 // antialiased and not the aliased coordinate system by rounding the coordinates.
5078 if (d->state->matrix.type() <= QTransform::TxScale) {
5079 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5084 setBackgroundMode(Qt::TransparentMode);
5085 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5086 QBrush brush(d->state->pen.color(), pm);
5089 setBrushOrigin(QPointF(0, 0));
5091 drawRect(pm.rect());
5094 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5095 x += d->state->matrix.dx();
5096 y += d->state->matrix.dy();
5098 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5102 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5104 #if defined QT_DEBUG_DRAW
5105 if (qt_show_painter_debug_output)
5106 printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5107 r.x(), r.y(), r.width(), r.height(),
5108 pm.width(), pm.height(),
5109 sr.x(), sr.y(), sr.width(), sr.height());
5113 if (!d->engine || pm.isNull())
5116 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5121 qreal w = r.width();
5122 qreal h = r.height();
5125 qreal sw = sr.width();
5126 qreal sh = sr.height();
5128 // Sanity-check clipping
5130 sw = pm.width() - sx;
5133 sh = pm.height() - sy;
5141 qreal w_ratio = sx * w/sw;
5149 qreal h_ratio = sy * h/sh;
5156 if (sw + sx > pm.width()) {
5157 qreal delta = sw - (pm.width() - sx);
5158 qreal w_ratio = delta * w/sw;
5163 if (sh + sy > pm.height()) {
5164 qreal delta = sh - (pm.height() - sy);
5165 qreal h_ratio = delta * h/sh;
5170 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5174 d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5178 // Emulate opaque background for bitmaps
5179 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5180 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5182 d->updateState(d->state);
5184 if ((d->state->matrix.type() > QTransform::TxTranslate
5185 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5186 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5187 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5188 || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5191 // If there is no rotation involved we have to make sure we use the
5192 // antialiased and not the aliased coordinate system by rounding the coordinates.
5193 if (d->state->matrix.type() <= QTransform::TxScale) {
5194 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5199 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5207 scale(w / sw, h / sh);
5208 setBackgroundMode(Qt::TransparentMode);
5209 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5212 if (sw == pm.width() && sh == pm.height())
5213 brush = QBrush(d->state->pen.color(), pm);
5215 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5220 drawRect(QRectF(0, 0, sw, sh));
5223 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5224 x += d->state->matrix.dx();
5225 y += d->state->matrix.dy();
5227 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5233 \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5234 const QRect &source)
5237 Draws the rectangular portion \a source of the given \a pixmap
5238 into the given \a target in the paint device.
5240 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5244 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5245 const QRectF &source)
5248 Draws the rectangular portion \a source of the given \a pixmap
5249 with its origin at the given \a point.
5253 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5254 const QRect &source)
5258 Draws the rectangular portion \a source of the given \a pixmap
5259 with its origin at the given \a point.
5263 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5266 Draws the given \a pixmap with its origin at the given \a point.
5270 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5273 Draws the given \a pixmap with its origin at the given \a point.
5277 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5281 Draws the given \a pixmap at position (\a{x}, \a{y}).
5285 \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5288 Draws the given \a pixmap into the given \a rectangle.
5290 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5294 \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5295 const QPixmap &pixmap)
5299 Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5300 with the given \a width and \a height.
5304 \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5305 int sx, int sy, int sw, int sh)
5309 Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5310 width \a sw and height \a sh, of the given \a pixmap , at the
5311 point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5312 If sw or sh are equal to zero the width/height of the pixmap
5313 is used and adjusted by the offset sx/sy;
5317 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5318 int sx, int sy, int sw, int sh)
5322 Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5323 pixmap into the paint device.
5325 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5326 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5327 pixmap that is to be drawn. The default is (0, 0).
5329 (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5330 The default, (0, 0) (and negative) means all the way to the
5331 bottom-right of the pixmap.
5334 void QPainter::drawImage(const QPointF &p, const QImage &image)
5338 if (!d->engine || image.isNull())
5342 d->extended->drawImage(p, image);
5349 int w = image.width();
5350 int h = image.height();
5352 d->updateState(d->state);
5354 if (((d->state->matrix.type() > QTransform::TxTranslate)
5355 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5356 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5357 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5360 // If there is no rotation involved we have to make sure we use the
5361 // antialiased and not the aliased coordinate system by rounding the coordinates.
5362 if (d->state->matrix.type() <= QTransform::TxScale) {
5363 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5368 setBackgroundMode(Qt::TransparentMode);
5369 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5370 QBrush brush(image);
5373 setBrushOrigin(QPointF(0, 0));
5375 drawRect(image.rect());
5380 if (d->state->matrix.type() == QTransform::TxTranslate
5381 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5382 x += d->state->matrix.dx();
5383 y += d->state->matrix.dy();
5386 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5389 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5390 Qt::ImageConversionFlags flags)
5394 if (!d->engine || image.isNull())
5397 qreal x = targetRect.x();
5398 qreal y = targetRect.y();
5399 qreal w = targetRect.width();
5400 qreal h = targetRect.height();
5401 qreal sx = sourceRect.x();
5402 qreal sy = sourceRect.y();
5403 qreal sw = sourceRect.width();
5404 qreal sh = sourceRect.height();
5406 // Sanity-check clipping
5408 sw = image.width() - sx;
5411 sh = image.height() - sy;
5419 qreal w_ratio = sx * w/sw;
5427 qreal h_ratio = sy * h/sh;
5434 if (sw + sx > image.width()) {
5435 qreal delta = sw - (image.width() - sx);
5436 qreal w_ratio = delta * w/sw;
5441 if (sh + sy > image.height()) {
5442 qreal delta = sh - (image.height() - sy);
5443 qreal h_ratio = delta * h/sh;
5448 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5452 d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5456 d->updateState(d->state);
5458 if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5459 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5460 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5461 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5464 // If there is no rotation involved we have to make sure we use the
5465 // antialiased and not the aliased coordinate system by rounding the coordinates.
5466 if (d->state->matrix.type() <= QTransform::TxScale) {
5467 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5472 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5479 scale(w / sw, h / sh);
5480 setBackgroundMode(Qt::TransparentMode);
5481 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5482 QBrush brush(image);
5485 setBrushOrigin(QPointF(-sx, -sy));
5487 drawRect(QRectF(0, 0, sw, sh));
5492 if (d->state->matrix.type() == QTransform::TxTranslate
5493 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5494 x += d->state->matrix.dx();
5495 y += d->state->matrix.dy();
5498 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5502 \fn void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphs)
5504 Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5505 edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5506 selected on \a glyphs and at offsets given by the positions in \a glyphs.
5510 \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes()
5512 #if !defined(QT_NO_RAWFONT)
5513 void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
5517 QRawFont font = glyphRun.rawFont();
5518 if (!font.isValid())
5521 QGlyphRunPrivate *glyphRun_d = QGlyphRunPrivate::get(glyphRun);
5523 const quint32 *glyphIndexes = glyphRun_d->glyphIndexData;
5524 const QPointF *glyphPositions = glyphRun_d->glyphPositionData;
5526 int count = qMin(glyphRun_d->glyphIndexDataSize, glyphRun_d->glyphPositionDataSize);
5527 QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5529 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5530 bool supportsTransformations = d->extended
5531 ? d->extended->supportsTransformations(fontD->fontEngine, d->state->matrix)
5532 : d->engine->type() == QPaintEngine::CoreGraphics || d->state->matrix.isAffine();
5534 for (int i=0; i<count; ++i) {
5535 QPointF processedPosition = position + glyphPositions[i];
5536 if (!supportsTransformations)
5537 processedPosition = d->state->transform().map(processedPosition);
5538 fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5541 d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, font, glyphRun.overline(),
5542 glyphRun.underline(), glyphRun.strikeOut());
5545 void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions,
5547 const QRawFont &font, bool overline, bool underline,
5554 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5555 QFontEngine *fontEngine = fontD->fontEngine;
5560 for (int i=0; i<glyphCount; ++i) {
5561 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5562 if (i == 0 || leftMost > positions[i].x)
5563 leftMost = positions[i].x;
5565 // We don't support glyphs that do not share a common baseline. If this turns out to
5566 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5567 // and do a drawTextItemDecorations call per cluster.
5568 if (i == 0 || baseLine < positions[i].y)
5569 baseLine = positions[i].y;
5571 // We use the advance rather than the actual bounds to match the algorithm in drawText()
5572 if (i == 0 || rightMost < positions[i].x + gm.xoff)
5573 rightMost = positions[i].x + gm.xoff;
5576 QFixed width = rightMost - leftMost;
5578 if (extended != 0 && state->matrix.isAffine()) {
5579 QStaticTextItem staticTextItem;
5580 staticTextItem.color = state->pen.color();
5581 staticTextItem.font = state->font;
5582 staticTextItem.setFontEngine(fontEngine);
5583 staticTextItem.numGlyphs = glyphCount;
5584 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5585 staticTextItem.glyphPositions = positions;
5587 extended->drawStaticTextItem(&staticTextItem);
5589 QTextItemInt textItem;
5590 textItem.fontEngine = fontEngine;
5592 QVarLengthArray<QFixed, 128> advances(glyphCount);
5593 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5594 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5595 memset(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5596 memset(advances.data(), 0, advances.size() * sizeof(QFixed));
5597 memset(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5599 textItem.glyphs.numGlyphs = glyphCount;
5600 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5601 textItem.glyphs.offsets = positions;
5602 textItem.glyphs.advances_x = advances.data();
5603 textItem.glyphs.advances_y = advances.data();
5604 textItem.glyphs.justifications = glyphJustifications.data();
5605 textItem.glyphs.attributes = glyphAttributes.data();
5607 engine->drawTextItem(QPointF(0, 0), textItem);
5610 QTextItemInt::RenderFlags flags;
5612 flags |= QTextItemInt::Underline;
5614 flags |= QTextItemInt::Overline;
5616 flags |= QTextItemInt::StrikeOut;
5618 drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5622 ? QTextCharFormat::SingleUnderline
5623 : QTextCharFormat::NoUnderline),
5624 flags, width.toReal(), QTextCharFormat());
5626 #endif // QT_NO_RAWFONT
5630 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5634 Draws the \a staticText at the \a topLeftPosition.
5636 \note The y-position is used as the top of the font.
5641 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5645 Draws the \a staticText at coordinates \a left and \a top.
5647 \note The y-position is used as the top of the font.
5651 \fn void QPainter::drawText(const QPointF &position, const QString &text)
5653 Draws the given \a text with the currently defined text direction,
5654 beginning at the given \a position.
5656 This function does not handle the newline character (\n), as it cannot
5657 break text into multiple lines, and it cannot display the newline character.
5658 Use the QPainter::drawText() overload that takes a rectangle instead
5659 if you want to draw multiple lines of text with the newline character, or
5660 if you want the text to be wrapped.
5662 By default, QPainter draws text anti-aliased.
5664 \note The y-position is used as the baseline of the font.
5667 void QPainter::drawText(const QPointF &p, const QString &str)
5669 drawText(p, str, 0, 0);
5675 Draws the given \a staticText at the given \a topLeftPosition.
5677 The text will be drawn using the font and the transformation set on the painter. If the
5678 font and/or transformation set on the painter are different from the ones used to initialize
5679 the layout of the QStaticText, then the layout will have to be recalculated. Use
5680 QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5681 it will later be drawn.
5683 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5684 last drawn, then there will be a slight overhead when translating the text to its new position.
5686 \note If the painter's transformation is not affine, then \a staticText will be drawn using
5687 regular calls to drawText(), losing any potential for performance improvement.
5689 \note The y-position is used as the top of the font.
5693 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5696 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5699 QStaticTextPrivate *staticText_d =
5700 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5702 if (font() != staticText_d->font) {
5703 staticText_d->font = font();
5704 staticText_d->needsRelayout = true;
5707 // If we don't have an extended paint engine, or if the painter is projected,
5708 // we go through standard code path
5709 if (d->extended == 0 || !d->state->matrix.isAffine()) {
5710 staticText_d->paintText(topLeftPosition, this);
5714 QFontEngine *fe = staticText_d->font.d->engineForScript(QUnicodeTables::Common);
5715 if (fe->type() == QFontEngine::Multi)
5716 fe = static_cast<QFontEngineMulti *>(fe)->engine(0);
5717 bool supportsTransformations = d->extended->supportsTransformations(fe,
5719 if (supportsTransformations && !staticText_d->untransformedCoordinates) {
5720 staticText_d->untransformedCoordinates = true;
5721 staticText_d->needsRelayout = true;
5722 } else if (!supportsTransformations && staticText_d->untransformedCoordinates) {
5723 staticText_d->untransformedCoordinates = false;
5724 staticText_d->needsRelayout = true;
5727 // Don't recalculate entire layout because of translation, rather add the dx and dy
5728 // into the position to move each text item the correct distance.
5729 QPointF transformedPosition = topLeftPosition;
5730 if (!staticText_d->untransformedCoordinates)
5731 transformedPosition = transformedPosition * d->state->matrix;
5732 QTransform oldMatrix;
5734 // The translation has been applied to transformedPosition. Remove translation
5735 // component from matrix.
5736 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
5737 qreal m11 = d->state->matrix.m11();
5738 qreal m12 = d->state->matrix.m12();
5739 qreal m13 = d->state->matrix.m13();
5740 qreal m21 = d->state->matrix.m21();
5741 qreal m22 = d->state->matrix.m22();
5742 qreal m23 = d->state->matrix.m23();
5743 qreal m33 = d->state->matrix.m33();
5745 oldMatrix = d->state->matrix;
5746 d->state->matrix.setMatrix(m11, m12, m13,
5751 // If the transform is not identical to the text transform,
5752 // we have to relayout the text (for other transformations than plain translation)
5753 bool staticTextNeedsReinit = staticText_d->needsRelayout;
5754 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
5755 staticText_d->matrix = d->state->matrix;
5756 staticTextNeedsReinit = true;
5759 // Recreate the layout of the static text because the matrix or font has changed
5760 if (staticTextNeedsReinit)
5761 staticText_d->init();
5763 if (transformedPosition != staticText_d->position) { // Translate to actual position
5764 QFixed fx = QFixed::fromReal(transformedPosition.x());
5765 QFixed fy = QFixed::fromReal(transformedPosition.y());
5766 QFixed oldX = QFixed::fromReal(staticText_d->position.x());
5767 QFixed oldY = QFixed::fromReal(staticText_d->position.y());
5768 for (int item=0; item<staticText_d->itemCount;++item) {
5769 QStaticTextItem *textItem = staticText_d->items + item;
5770 for (int i=0; i<textItem->numGlyphs; ++i) {
5771 textItem->glyphPositions[i].x += fx - oldX;
5772 textItem->glyphPositions[i].y += fy - oldY;
5774 textItem->userDataNeedsUpdate = true;
5777 staticText_d->position = transformedPosition;
5780 QPen oldPen = d->state->pen;
5781 QColor currentColor = oldPen.color();
5782 for (int i=0; i<staticText_d->itemCount; ++i) {
5783 QStaticTextItem *item = staticText_d->items + i;
5784 if (item->color.isValid() && currentColor != item->color) {
5785 setPen(item->color);
5786 currentColor = item->color;
5788 d->extended->drawStaticTextItem(item);
5790 qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
5791 item->numGlyphs, item->fontEngine(), staticText_d->font,
5794 if (currentColor != oldPen.color())
5797 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
5798 d->state->matrix = oldMatrix;
5804 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
5806 #ifdef QT_DEBUG_DRAW
5807 if (qt_show_painter_debug_output)
5808 printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
5813 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
5816 if (tf & Qt::TextBypassShaping) {
5817 // Skip harfbuzz complex shaping, shape using glyph advances only
5818 int len = str.length();
5819 int numGlyphs = len;
5820 QVarLengthGlyphLayoutArray glyphs(len);
5821 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
5822 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
5823 glyphs.resize(numGlyphs);
5824 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
5825 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
5828 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
5829 drawTextItem(p, gf);
5833 QStackTextEngine engine(str, d->state->font);
5834 engine.option.setTextDirection(d->state->layoutDirection);
5835 if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
5836 engine.ignoreBidi = true;
5837 engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
5841 line.length = str.length();
5842 engine.shapeLine(line);
5844 int nItems = engine.layoutData->items.size();
5845 QVarLengthArray<int> visualOrder(nItems);
5846 QVarLengthArray<uchar> levels(nItems);
5847 for (int i = 0; i < nItems; ++i)
5848 levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
5849 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
5851 if (justificationPadding > 0) {
5852 engine.option.setAlignment(Qt::AlignJustify);
5853 engine.forceJustification = true;
5854 // this works because justify() is only interested in the difference between width and textWidth
5855 line.width = justificationPadding;
5856 engine.justify(line);
5858 QFixed x = QFixed::fromReal(p.x());
5860 for (int i = 0; i < nItems; ++i) {
5861 int item = visualOrder[i];
5862 const QScriptItem &si = engine.layoutData->items.at(item);
5863 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
5867 QFont f = engine.font(si);
5868 QTextItemInt gf(si, &f);
5869 gf.glyphs = engine.shapedGlyphs(&si);
5870 gf.chars = engine.layoutData->string.unicode() + si.position;
5871 gf.num_chars = engine.length(item);
5872 if (engine.forceJustification) {
5873 for (int j=0; j<gf.glyphs.numGlyphs; ++j)
5874 gf.width += gf.glyphs.effectiveAdvance(j);
5876 gf.width = si.width;
5878 gf.logClusters = engine.logClusters(&si);
5880 drawTextItem(QPointF(x.toReal(), p.y()), gf);
5886 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
5888 #ifdef QT_DEBUG_DRAW
5889 if (qt_show_painter_debug_output)
5890 printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
5891 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5896 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5900 d->updateState(d->state);
5903 qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
5905 *br = bounds.toAlignedRect();
5909 \fn void QPainter::drawText(const QPoint &position, const QString &text)
5913 Draws the given \a text with the currently defined text direction,
5914 beginning at the given \a position.
5916 By default, QPainter draws text anti-aliased.
5918 \note The y-position is used as the baseline of the font.
5923 \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
5926 Draws the given \a text within the provided \a rectangle.
5930 \li \inlineimage qpainter-text.png
5932 \snippet code/src_gui_painting_qpainter.cpp 17
5935 The \a boundingRect (if not null) is set to the what the bounding rectangle
5936 should be in order to enclose the whole text. The \a flags argument is a bitwise
5937 OR of the following flags:
5942 \li Qt::AlignHCenter
5943 \li Qt::AlignJustify
5946 \li Qt::AlignVCenter
5948 \li Qt::TextDontClip
5949 \li Qt::TextSingleLine
5950 \li Qt::TextExpandTabs
5951 \li Qt::TextShowMnemonic
5952 \li Qt::TextWordWrap
5953 \li Qt::TextIncludeTrailingSpaces
5956 \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
5958 By default, QPainter draws text anti-aliased.
5960 \note The y-coordinate of \a rectangle is used as the top of the font.
5962 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
5964 #ifdef QT_DEBUG_DRAW
5965 if (qt_show_painter_debug_output)
5966 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
5967 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5972 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5976 d->updateState(d->state);
5978 qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
5982 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
5985 Draws the given \a text within the provided \a rectangle according
5986 to the specified \a flags. The \a boundingRect (if not null) is set to
5987 the what the bounding rectangle should be in order to enclose the whole text.
5989 By default, QPainter draws text anti-aliased.
5991 \note The y-coordinate of \a rectangle is used as the top of the font.
5995 \fn void QPainter::drawText(int x, int y, const QString &text)
5999 Draws the given \a text at position (\a{x}, \a{y}), using the painter's
6000 currently defined text direction.
6002 By default, QPainter draws text anti-aliased.
6004 \note The y-position is used as the baseline of the font.
6009 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6010 const QString &text, QRect *boundingRect)
6014 Draws the given \a text within the rectangle with origin (\a{x},
6015 \a{y}), \a width and \a height.
6017 The \a boundingRect (if not null) is set to the actual bounding
6018 rectangle of the output. The \a flags argument is a bitwise OR of
6019 the following flags:
6024 \li Qt::AlignHCenter
6025 \li Qt::AlignJustify
6028 \li Qt::AlignVCenter
6030 \li Qt::TextSingleLine
6031 \li Qt::TextExpandTabs
6032 \li Qt::TextShowMnemonic
6033 \li Qt::TextWordWrap
6036 By default, QPainter draws text anti-aliased.
6038 \note The y-position is used as the top of the font.
6040 \sa Qt::AlignmentFlag, Qt::TextFlag
6044 \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6045 const QTextOption &option)
6048 Draws the given \a text in the \a rectangle specified using the \a option
6049 to control its positioning and orientation.
6051 By default, QPainter draws text anti-aliased.
6053 \note The y-coordinate of \a rectangle is used as the top of the font.
6055 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6057 #ifdef QT_DEBUG_DRAW
6058 if (qt_show_painter_debug_output)
6059 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6060 r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6065 if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6069 d->updateState(d->state);
6071 qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6075 \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6082 \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6087 Draws the text item \a ti at position \a p.
6091 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6096 Draws the text item \a ti at position \a p.
6098 This method ignores the painters background mode and
6099 color. drawText and qt_format_text have to do it themselves, as
6100 only they know the extents of the complete string.
6102 It ignores the font set on the painter as the text item has one of its own.
6104 The underline and strikeout parameters of the text items font are
6105 ignored aswell. You'll need to pass in the correct flags to get
6106 underlining and strikeout.
6109 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6111 const qreal radiusBase = qMax(qreal(1), maxRadius);
6113 QString key = QLatin1String("WaveUnderline-")
6114 % pen.color().name()
6115 % HexString<qreal>(radiusBase);
6118 if (QPixmapCache::find(key, pixmap))
6121 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6122 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6123 const int radius = qFloor(radiusBase);
6130 while (xs < width) {
6133 path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6136 pixmap = QPixmap(width, radius * 2);
6137 pixmap.fill(Qt::transparent);
6140 wavePen.setCapStyle(Qt::SquareCap);
6142 // This is to protect against making the line too fat, as happens on Mac OS X
6143 // due to it having a rather thick width for the regular underline.
6144 const qreal maxPenWidth = .8 * radius;
6145 if (wavePen.widthF() > maxPenWidth)
6146 wavePen.setWidth(maxPenWidth);
6148 QPainter imgPainter(&pixmap);
6149 imgPainter.setPen(wavePen);
6150 imgPainter.setRenderHint(QPainter::Antialiasing);
6151 imgPainter.translate(0, radius);
6152 imgPainter.drawPath(path);
6155 QPixmapCache::insert(key, pixmap);
6160 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
6161 QTextCharFormat::UnderlineStyle underlineStyle,
6162 QTextItem::RenderFlags flags, qreal width,
6163 const QTextCharFormat &charFormat)
6165 if (underlineStyle == QTextCharFormat::NoUnderline
6166 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6169 const QPen oldPen = painter->pen();
6170 const QBrush oldBrush = painter->brush();
6171 painter->setBrush(Qt::NoBrush);
6173 pen.setStyle(Qt::SolidLine);
6174 pen.setWidthF(fe->lineThickness().toReal());
6175 pen.setCapStyle(Qt::FlatCap);
6177 QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6179 const qreal underlineOffset = fe->underlinePosition().toReal();
6180 // deliberately ceil the offset to avoid the underline coming too close to
6181 // the text above it.
6182 const qreal underlinePos = pos.y() + qCeil(underlineOffset);
6184 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6185 QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
6187 underlineStyle = QTextCharFormat::UnderlineStyle(theme->themeHint(QPlatformTheme::SpellCheckUnderlineStyle).toInt());
6190 if (underlineStyle == QTextCharFormat::WaveUnderline) {
6192 painter->translate(0, pos.y() + 1);
6194 QColor uc = charFormat.underlineColor();
6198 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6199 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6200 const int descent = (int) fe->descent().toReal();
6202 painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6203 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6205 } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6206 QColor uc = charFormat.underlineColor();
6210 pen.setStyle((Qt::PenStyle)(underlineStyle));
6211 painter->setPen(pen);
6212 QLineF underline(line.x1(), underlinePos, line.x2(), underlinePos);
6214 textEngine->addUnderline(painter, underline);
6216 painter->drawLine(underline);
6219 pen.setStyle(Qt::SolidLine);
6220 pen.setColor(oldPen.color());
6222 if (flags & QTextItem::StrikeOut) {
6223 QLineF strikeOutLine = line;
6224 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6225 painter->setPen(pen);
6227 textEngine->addStrikeOut(painter, strikeOutLine);
6229 painter->drawLine(strikeOutLine);
6232 if (flags & QTextItem::Overline) {
6233 QLineF overline = line;
6234 overline.translate(0., - fe->ascent().toReal());
6235 painter->setPen(pen);
6237 textEngine->addOverline(painter, overline);
6239 painter->drawLine(overline);
6242 painter->setPen(oldPen);
6243 painter->setBrush(oldBrush);
6246 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6247 const QFixedPoint *positions, int glyphCount,
6248 QFontEngine *fontEngine, const QFont &font,
6249 const QTextCharFormat &charFormat)
6251 if (!(font.underline() || font.strikeOut() || font.overline()))
6257 for (int i=0; i<glyphCount; ++i) {
6258 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6259 if (i == 0 || leftMost > positions[i].x)
6260 leftMost = positions[i].x;
6262 // We don't support glyphs that do not share a common baseline. If this turns out to
6263 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6264 // and do a drawTextItemDecoration call per cluster.
6265 if (i == 0 || baseLine < positions[i].y)
6266 baseLine = positions[i].y;
6268 // We use the advance rather than the actual bounds to match the algorithm in drawText()
6269 if (i == 0 || rightMost < positions[i].x + gm.xoff)
6270 rightMost = positions[i].x + gm.xoff;
6273 QFixed width = rightMost - leftMost;
6274 QTextItem::RenderFlags flags = 0;
6276 if (font.underline())
6277 flags |= QTextItem::Underline;
6278 if (font.overline())
6279 flags |= QTextItem::Overline;
6280 if (font.strikeOut())
6281 flags |= QTextItem::StrikeOut;
6283 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6286 font.underline() ? QTextCharFormat::SingleUnderline
6287 : QTextCharFormat::NoUnderline, flags,
6288 width.toReal(), charFormat);
6291 void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6295 d->drawTextItem(p, ti, static_cast<QTextEngine *>(0));
6298 void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine)
6300 #ifdef QT_DEBUG_DRAW
6301 if (qt_show_painter_debug_output)
6302 printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6303 p.x(), p.y(), qPrintable(_ti.text()));
6312 qt_painter_thread_test(device->devType(),
6314 QFontDatabase::supportsThreadedFontRendering());
6317 QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6319 if (!extended && state->bgMode == Qt::OpaqueMode) {
6320 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6321 q->fillRect(rect, state->bgBrush);
6324 if (q->pen().style() == Qt::NoPen)
6327 const QPainter::RenderHints oldRenderHints = state->renderHints;
6328 if (!state->renderHints & QPainter::Antialiasing && state->matrix.type() >= QTransform::TxScale) {
6329 // draw antialias decoration (underline/overline/strikeout) with
6333 const QTransform &m = state->matrix;
6334 if (state->matrix.type() < QTransform::TxShear) {
6335 bool isPlain90DegreeRotation =
6336 (qFuzzyIsNull(m.m11())
6337 && qFuzzyIsNull(m.m12() - qreal(1))
6338 && qFuzzyIsNull(m.m21() + qreal(1))
6339 && qFuzzyIsNull(m.m22())
6342 (qFuzzyIsNull(m.m11() + qreal(1))
6343 && qFuzzyIsNull(m.m12())
6344 && qFuzzyIsNull(m.m21())
6345 && qFuzzyIsNull(m.m22() + qreal(1))
6348 (qFuzzyIsNull(m.m11())
6349 && qFuzzyIsNull(m.m12() + qreal(1))
6350 && qFuzzyIsNull(m.m21() - qreal(1))
6351 && qFuzzyIsNull(m.m22())
6354 aa = !isPlain90DegreeRotation;
6357 q->setRenderHint(QPainter::Antialiasing, true);
6363 if (!ti.glyphs.numGlyphs) {
6365 } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6366 QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6368 const QGlyphLayout &glyphs = ti.glyphs;
6369 int which = glyphs.glyphs[0] >> 24;
6374 bool rtl = ti.flags & QTextItem::RightToLeft;
6376 x += ti.width.toReal();
6380 for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6381 const int e = glyphs.glyphs[end] >> 24;
6386 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6388 // set the high byte to zero and calc the width
6389 for (i = start; i < end; ++i) {
6390 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6391 ti2.width += ti.glyphs.effectiveAdvance(i);
6395 x -= ti2.width.toReal();
6397 engine->drawTextItem(QPointF(x, y), ti2);
6400 x += ti2.width.toReal();
6402 // reset the high byte for all glyphs and advance to the next sub-string
6403 const int hi = which << 24;
6404 for (i = start; i < end; ++i) {
6405 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6413 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6415 // set the high byte to zero and calc the width
6416 for (i = start; i < end; ++i) {
6417 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6418 ti2.width += ti.glyphs.effectiveAdvance(i);
6422 x -= ti2.width.toReal();
6425 extended->drawTextItem(QPointF(x, y), ti2);
6427 engine->drawTextItem(QPointF(x,y), ti2);
6429 // reset the high byte for all glyphs
6430 const int hi = which << 24;
6431 for (i = start; i < end; ++i)
6432 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6436 extended->drawTextItem(p, ti);
6438 engine->drawTextItem(p, ti);
6440 drawTextItemDecoration(q, p, ti.fontEngine, textEngine, ti.underlineStyle,
6441 ti.flags, ti.width.toReal(), ti.charFormat);
6443 if (state->renderHints != oldRenderHints) {
6444 state->renderHints = oldRenderHints;
6446 extended->renderHintsChanged();
6448 state->dirtyFlags |= QPaintEngine::DirtyHints;
6453 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6455 Returns the bounding rectangle of the \a text as it will appear
6456 when drawn inside the given \a rectangle with the specified \a
6457 flags using the currently set font(); i.e the function tells you
6458 where the drawText() function will draw when given the same
6461 If the \a text does not fit within the given \a rectangle using
6462 the specified \a flags, the function returns the required
6465 The \a flags argument is a bitwise OR of the following flags:
6469 \li Qt::AlignHCenter
6472 \li Qt::AlignVCenter
6474 \li Qt::TextSingleLine
6475 \li Qt::TextExpandTabs
6476 \li Qt::TextShowMnemonic
6477 \li Qt::TextWordWrap
6478 \li Qt::TextIncludeTrailingSpaces
6480 If several of the horizontal or several of the vertical alignment
6481 flags are set, the resulting alignment is undefined.
6483 \sa drawText(), Qt::Alignment, Qt::TextFlag
6487 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6488 const QString &text)
6492 Returns the bounding rectangle of the \a text as it will appear
6493 when drawn inside the given \a rectangle with the specified \a
6494 flags using the currently set font().
6498 \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6499 const QString &text);
6503 Returns the bounding rectangle of the given \a text as it will
6504 appear when drawn inside the rectangle beginning at the point
6505 (\a{x}, \a{y}) with width \a w and height \a h.
6507 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6510 return QRect(rect.x(),rect.y(), 0,0);
6512 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6518 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6521 return QRectF(rect.x(),rect.y(), 0,0);
6523 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6528 \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6529 const QString &text, const QTextOption &option)
6533 Instead of specifying flags as a bitwise OR of the
6534 Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6535 an \a option argument. The QTextOption class provides a
6536 description of general rich text properties.
6540 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6544 if (!d->engine || text.length() == 0)
6545 return QRectF(r.x(),r.y(), 0,0);
6548 qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6553 \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6555 Draws a tiled \a pixmap, inside the given \a rectangle with its
6556 origin at the given \a position.
6558 Calling drawTiledPixmap() is similar to calling drawPixmap()
6559 several times to fill (tile) an area with a pixmap, but is
6560 potentially much more efficient depending on the underlying window
6565 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6567 #ifdef QT_DEBUG_DRAW
6568 if (qt_show_painter_debug_output)
6569 printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6570 r.x(), r.y(), r.width(), r.height(),
6571 pixmap.width(), pixmap.height(),
6576 if (!d->engine || pixmap.isNull() || r.isEmpty())
6580 qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6583 qreal sw = pixmap.width();
6584 qreal sh = pixmap.height();
6588 sx = qRound(sw) - qRound(-sx) % qRound(sw);
6590 sx = qRound(sx) % qRound(sw);
6592 sy = qRound(sh) - -qRound(sy) % qRound(sh);
6594 sy = qRound(sy) % qRound(sh);
6598 d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6602 if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6603 fillRect(r, d->state->bgBrush);
6605 d->updateState(d->state);
6606 if ((d->state->matrix.type() > QTransform::TxTranslate
6607 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6608 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6611 setBackgroundMode(Qt::TransparentMode);
6612 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6613 setBrush(QBrush(d->state->pen.color(), pixmap));
6616 // If there is no rotation involved we have to make sure we use the
6617 // antialiased and not the aliased coordinate system by rounding the coordinates.
6618 if (d->state->matrix.type() <= QTransform::TxScale) {
6619 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6621 if (d->state->matrix.type() <= QTransform::TxTranslate) {
6626 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6627 drawRect(QRectF(p, r.size()));
6629 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6638 if (d->state->matrix.type() == QTransform::TxTranslate
6639 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6640 x += d->state->matrix.dx();
6641 y += d->state->matrix.dy();
6644 d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6648 \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6649 const QPoint &position = QPoint())
6652 Draws a tiled \a pixmap, inside the given \a rectangle with its
6653 origin at the given \a position.
6657 \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6658 QPixmap &pixmap, int sx, int sy);
6661 Draws a tiled \a pixmap in the specified rectangle.
6663 (\a{x}, \a{y}) specifies the top-left point in the paint device
6664 that is to be drawn onto; with the given \a width and \a
6665 height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6666 pixmap that is to be drawn; this defaults to (0, 0).
6669 #ifndef QT_NO_PICTURE
6672 \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6674 Replays the given \a picture at the given \a point.
6676 The QPicture class is a paint device that records and replays
6677 QPainter commands. A picture serializes the painter commands to an
6678 IO device in a platform-independent format. Everything that can be
6679 painted on a widget or pixmap can also be stored in a picture.
6681 This function does exactly the same as QPicture::play() when
6682 called with \a point = QPoint(0, 0).
6687 \snippet code/src_gui_painting_qpainter.cpp 18
6690 \sa QPicture::play()
6693 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6701 d->updateState(d->state);
6705 const_cast<QPicture *>(&picture)->play(this);
6710 \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6713 Replays the given \a picture at the given \a point.
6717 \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6720 Draws the given \a picture at point (\a x, \a y).
6723 #endif // QT_NO_PICTURE
6726 \fn void QPainter::eraseRect(const QRectF &rectangle)
6728 Erases the area inside the given \a rectangle. Equivalent to
6730 \snippet code/src_gui_painting_qpainter.cpp 19
6734 void QPainter::eraseRect(const QRectF &r)
6738 fillRect(r, d->state->bgBrush);
6741 static inline bool needsResolving(const QBrush &brush)
6743 Qt::BrushStyle s = brush.style();
6744 return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
6745 s == Qt::ConicalGradientPattern) &&
6746 brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
6750 \fn void QPainter::eraseRect(const QRect &rectangle)
6753 Erases the area inside the given \a rectangle.
6757 \fn void QPainter::eraseRect(int x, int y, int width, int height)
6760 Erases the area inside the rectangle beginning at (\a x, \a y)
6761 with the given \a width and \a height.
6766 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
6769 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6770 width and \a height, using the brush \a style specified.
6776 \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
6779 Fills the given \a rectangle with the brush \a style specified.
6785 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
6788 Fills the given \a rectangle with the brush \a style specified.
6794 \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
6796 Fills the given \a rectangle with the \a brush specified.
6798 Alternatively, you can specify a QColor instead of a QBrush; the
6799 QBrush constructor (taking a QColor argument) will automatically
6800 create a solid pattern brush.
6804 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
6812 const QGradient *g = brush.gradient();
6813 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6814 d->extended->fillRect(r, brush);
6819 QPen oldPen = pen();
6820 QBrush oldBrush = this->brush();
6822 if (brush.style() == Qt::SolidPattern) {
6823 d->colorBrush.setStyle(Qt::SolidPattern);
6824 d->colorBrush.setColor(brush.color());
6825 setBrush(d->colorBrush);
6836 \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
6839 Fills the given \a rectangle with the specified \a brush.
6842 void QPainter::fillRect(const QRect &r, const QBrush &brush)
6850 const QGradient *g = brush.gradient();
6851 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6852 d->extended->fillRect(r, brush);
6857 QPen oldPen = pen();
6858 QBrush oldBrush = this->brush();
6860 if (brush.style() == Qt::SolidPattern) {
6861 d->colorBrush.setStyle(Qt::SolidPattern);
6862 d->colorBrush.setColor(brush.color());
6863 setBrush(d->colorBrush);
6876 \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
6879 Fills the given \a rectangle with the \a color specified.
6883 void QPainter::fillRect(const QRect &r, const QColor &color)
6891 d->extended->fillRect(r, color);
6895 fillRect(r, QBrush(color));
6900 \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
6903 Fills the given \a rectangle with the \a color specified.
6907 void QPainter::fillRect(const QRectF &r, const QColor &color)
6915 d->extended->fillRect(r, color);
6919 fillRect(r, QBrush(color));
6923 \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
6927 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6928 width and \a height, using the given \a brush.
6932 \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
6936 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6937 width and \a height, using the given \a color.
6943 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
6947 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6948 width and \a height, using the given \a color.
6954 \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
6958 Fills the given \a rectangle with the specified \a color.
6964 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
6968 Fills the given \a rectangle with the specified \a color.
6974 Sets the given render \a hint on the painter if \a on is true;
6975 otherwise clears the render hint.
6977 \sa setRenderHints(), renderHints(), {QPainter#Rendering
6978 Quality}{Rendering Quality}
6980 void QPainter::setRenderHint(RenderHint hint, bool on)
6982 #ifdef QT_DEBUG_DRAW
6983 if (qt_show_painter_debug_output)
6984 printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
6988 static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
6989 if (hint == QPainter::Antialiasing && antialiasingDisabled)
6993 setRenderHints(hint, on);
6999 Sets the given render \a hints on the painter if \a on is true;
7000 otherwise clears the render hints.
7002 \sa setRenderHint(), renderHints(), {QPainter#Rendering
7003 Quality}{Rendering Quality}
7006 void QPainter::setRenderHints(RenderHints hints, bool on)
7011 qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7016 d->state->renderHints |= hints;
7018 d->state->renderHints &= ~hints;
7021 d->extended->renderHintsChanged();
7023 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7027 Returns a flag that specifies the rendering hints that are set for
7030 \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7032 QPainter::RenderHints QPainter::renderHints() const
7034 Q_D(const QPainter);
7039 return d->state->renderHints;
7043 \fn bool QPainter::testRenderHint(RenderHint hint) const
7046 Returns true if \a hint is set; otherwise returns false.
7048 \sa renderHints(), setRenderHint()
7052 Returns true if view transformation is enabled; otherwise returns
7055 \sa setViewTransformEnabled(), worldTransform()
7058 bool QPainter::viewTransformEnabled() const
7060 Q_D(const QPainter);
7062 qWarning("QPainter::viewTransformEnabled: Painter not active");
7065 return d->state->VxF;
7069 \fn void QPainter::setWindow(const QRect &rectangle)
7071 Sets the painter's window to the given \a rectangle, and enables
7072 view transformations.
7074 The window rectangle is part of the view transformation. The
7075 window specifies the logical coordinate system. Its sister, the
7076 viewport(), specifies the device coordinate system.
7078 The default window rectangle is the same as the device's
7081 \sa window(), viewTransformEnabled(), {Coordinate
7082 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7086 \fn void QPainter::setWindow(int x, int y, int width, int height)
7089 Sets the painter's window to the rectangle beginning at (\a x, \a
7090 y) and the given \a width and \a height.
7093 void QPainter::setWindow(const QRect &r)
7095 #ifdef QT_DEBUG_DRAW
7096 if (qt_show_painter_debug_output)
7097 printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7103 qWarning("QPainter::setWindow: Painter not active");
7107 d->state->wx = r.x();
7108 d->state->wy = r.y();
7109 d->state->ww = r.width();
7110 d->state->wh = r.height();
7112 d->state->VxF = true;
7117 Returns the window rectangle.
7119 \sa setWindow(), setViewTransformEnabled()
7122 QRect QPainter::window() const
7124 Q_D(const QPainter);
7126 qWarning("QPainter::window: Painter not active");
7129 return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7133 \fn void QPainter::setViewport(const QRect &rectangle)
7135 Sets the painter's viewport rectangle to the given \a rectangle,
7136 and enables view transformations.
7138 The viewport rectangle is part of the view transformation. The
7139 viewport specifies the device coordinate system. Its sister, the
7140 window(), specifies the logical coordinate system.
7142 The default viewport rectangle is the same as the device's
7145 \sa viewport(), viewTransformEnabled(), {Coordinate
7146 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7150 \fn void QPainter::setViewport(int x, int y, int width, int height)
7153 Sets the painter's viewport rectangle to be the rectangle
7154 beginning at (\a x, \a y) with the given \a width and \a height.
7157 void QPainter::setViewport(const QRect &r)
7159 #ifdef QT_DEBUG_DRAW
7160 if (qt_show_painter_debug_output)
7161 printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7167 qWarning("QPainter::setViewport: Painter not active");
7171 d->state->vx = r.x();
7172 d->state->vy = r.y();
7173 d->state->vw = r.width();
7174 d->state->vh = r.height();
7176 d->state->VxF = true;
7181 Returns the viewport rectangle.
7183 \sa setViewport(), setViewTransformEnabled()
7186 QRect QPainter::viewport() const
7188 Q_D(const QPainter);
7190 qWarning("QPainter::viewport: Painter not active");
7193 return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7197 Enables view transformations if \a enable is true, or disables
7198 view transformations if \a enable is false.
7200 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7201 Conversion}{Window-Viewport Conversion}
7204 void QPainter::setViewTransformEnabled(bool enable)
7206 #ifdef QT_DEBUG_DRAW
7207 if (qt_show_painter_debug_output)
7208 printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7214 qWarning("QPainter::setViewTransformEnabled: Painter not active");
7218 if (enable == d->state->VxF)
7221 d->state->VxF = enable;
7230 Please use QWidget::render() instead.
7232 Redirects all paint commands for the given paint \a device, to the
7233 \a replacement device. The optional point \a offset defines an
7234 offset within the source device.
7236 The redirection will not be effective until the begin() function
7237 has been called; make sure to call end() for the given \a
7238 device's painter (if any) before redirecting. Call
7239 restoreRedirected() to restore the previous redirection.
7241 \warning Making use of redirections in the QPainter API implies
7242 that QPainter::begin() and QPaintDevice destructors need to hold
7243 a mutex for a short period. This can impact performance. Use of
7244 QWidget::render is strongly encouraged.
7246 \sa redirected(), restoreRedirected()
7248 void QPainter::setRedirected(const QPaintDevice *device,
7249 QPaintDevice *replacement,
7250 const QPoint &offset)
7252 Q_ASSERT(device != 0);
7254 Q_UNUSED(replacement)
7256 qWarning("QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7264 Using QWidget::render() obsoletes the use of this function.
7266 Restores the previous redirection for the given \a device after a
7267 call to setRedirected().
7269 \warning Making use of redirections in the QPainter API implies
7270 that QPainter::begin() and QPaintDevice destructors need to hold
7271 a mutex for a short period. This can impact performance. Use of
7272 QWidget::render is strongly encouraged.
7276 void QPainter::restoreRedirected(const QPaintDevice *device)
7279 qWarning("QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7287 Using QWidget::render() obsoletes the use of this function.
7289 Returns the replacement for given \a device. The optional out
7290 parameter \a offset returns the offset within the replaced device.
7292 \warning Making use of redirections in the QPainter API implies
7293 that QPainter::begin() and QPaintDevice destructors need to hold
7294 a mutex for a short period. This can impact performance. Use of
7295 QWidget::render is strongly encouraged.
7297 \sa setRedirected(), restoreRedirected()
7299 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7306 void qt_format_text(const QFont &fnt, const QRectF &_r,
7307 int tf, const QString& str, QRectF *brect,
7308 int tabstops, int *ta, int tabarraylen,
7311 qt_format_text(fnt, _r,
7313 tabstops, ta, tabarraylen,
7316 void qt_format_text(const QFont &fnt, const QRectF &_r,
7317 int tf, const QTextOption *option, const QString& str, QRectF *brect,
7318 int tabstops, int *ta, int tabarraylen,
7322 Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
7325 tf |= option->alignment();
7326 if (option->wrapMode() != QTextOption::NoWrap)
7327 tf |= Qt::TextWordWrap;
7329 if (option->flags() & QTextOption::IncludeTrailingSpaces)
7330 tf |= Qt::TextIncludeTrailingSpaces;
7332 if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
7333 tf |= Qt::TextExpandTabs;
7336 // we need to copy r here to protect against the case (&r == brect).
7339 bool dontclip = (tf & Qt::TextDontClip);
7340 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
7341 bool singleline = (tf & Qt::TextSingleLine);
7342 bool showmnemonic = (tf & Qt::TextShowMnemonic);
7343 bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
7345 Qt::LayoutDirection layout_direction;
7346 if (tf & Qt::TextForceLeftToRight)
7347 layout_direction = Qt::LeftToRight;
7348 else if (tf & Qt::TextForceRightToLeft)
7349 layout_direction = Qt::RightToLeft;
7351 layout_direction = option->textDirection();
7353 layout_direction = painter->layoutDirection();
7355 layout_direction = Qt::LeftToRight;
7357 tf = QGuiApplicationPrivate::visualAlignment(layout_direction, QFlag(tf));
7359 bool isRightToLeft = layout_direction == Qt::RightToLeft;
7360 bool expandtabs = ((tf & Qt::TextExpandTabs) &&
7361 (((tf & Qt::AlignLeft) && !isRightToLeft) ||
7362 ((tf & Qt::AlignRight) && isRightToLeft)));
7365 tf |= Qt::TextDontPrint;
7367 uint maxUnderlines = 0;
7368 int numUnderlines = 0;
7369 QVarLengthArray<int, 32> underlinePositions(1);
7371 QFontMetricsF fm(fnt);
7374 start_lengthVariant:
7375 bool hasMoreLengthVariants = false;
7376 // compatible behaviour to the old implementation. Replace
7378 int old_offset = offset;
7379 for (; offset < text.length(); offset++) {
7380 QChar chr = text.at(offset);
7381 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
7382 text[offset] = QLatin1Char(' ');
7383 } else if (chr == QLatin1Char('\n')) {
7384 text[offset] = QChar::LineSeparator;
7385 } else if (chr == QLatin1Char('&')) {
7387 } else if (chr == QLatin1Char('\t')) {
7389 text[offset] = QLatin1Char(' ');
7390 } else if (!tabarraylen && !tabstops) {
7391 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
7393 } else if (chr == QChar(ushort(0x9c))) {
7394 // string with multiple length variants
7395 hasMoreLengthVariants = true;
7400 int length = offset - old_offset;
7401 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
7402 underlinePositions.resize(maxUnderlines + 1);
7404 QChar *cout = text.data() + old_offset;
7408 if (*cin == QLatin1Char('&')) {
7414 if (*cin != QLatin1Char('&') && !hidemnmemonic)
7415 underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
7424 // no need to do extra work for underlines if we don't paint
7425 if (tf & Qt::TextDontPrint)
7428 underlinePositions[numUnderlines] = -1;
7432 QString finalText = text.mid(old_offset, length);
7433 QStackTextEngine engine(finalText, fnt);
7435 engine.option = *option;
7438 if (engine.option.tabStop() < 0 && tabstops > 0)
7439 engine.option.setTabStop(tabstops);
7441 if (engine.option.tabs().isEmpty() && ta) {
7443 for (int i = 0; i < tabarraylen; i++)
7444 tabs.append(qreal(ta[i]));
7445 engine.option.setTabArray(tabs);
7448 engine.option.setTextDirection(layout_direction);
7449 if (tf & Qt::AlignJustify)
7450 engine.option.setAlignment(Qt::AlignJustify);
7452 engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
7454 if (!option && (tf & Qt::TextWrapAnywhere))
7455 engine.option.setWrapMode(QTextOption::WrapAnywhere);
7457 if (tf & Qt::TextJustificationForced)
7458 engine.forceJustification = true;
7459 QTextLayout textLayout(&engine);
7460 textLayout.setCacheEnabled(true);
7461 textLayout.engine()->underlinePositions = underlinePositions.data();
7463 if (finalText.isEmpty()) {
7464 height = fm.height();
7466 tf |= Qt::TextDontPrint;
7468 qreal lineWidth = 0x01000000;
7469 if (wordwrap || (tf & Qt::TextJustificationForced))
7470 lineWidth = qMax<qreal>(0, r.width());
7472 tf |= Qt::TextIncludeTrailingSpaces;
7473 textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
7474 textLayout.beginLayout();
7476 qreal leading = fm.leading();
7480 QTextLine l = textLayout.createLine();
7484 l.setLineWidth(lineWidth);
7486 l.setPosition(QPointF(0., height));
7487 height += l.height();
7488 width = qMax(width, l.naturalTextWidth());
7489 if (!dontclip && !brect && height >= r.height())
7492 textLayout.endLayout();
7497 if (tf & Qt::AlignBottom) {
7498 yoff = r.height() - height;
7499 } else if (tf & Qt::AlignVCenter) {
7500 yoff = (r.height() - height)/2;
7502 QTransform::TransformationType type = painter->transform().type();
7503 if (type <= QTransform::TxScale) {
7504 // do the rounding manually to work around inconsistencies
7505 // in the paint engines when drawing on floating point offsets
7506 const qreal scale = painter->transform().m22();
7508 yoff = -qRound(-yoff * scale) / scale;
7512 if (tf & Qt::AlignRight) {
7513 xoff = r.width() - width;
7514 } else if (tf & Qt::AlignHCenter) {
7515 xoff = (r.width() - width)/2;
7517 QTransform::TransformationType type = painter->transform().type();
7518 if (type <= QTransform::TxScale) {
7519 // do the rounding manually to work around inconsistencies
7520 // in the paint engines when drawing on floating point offsets
7521 const qreal scale = painter->transform().m11();
7523 xoff = qRound(xoff * scale) / scale;
7527 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
7529 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
7531 goto start_lengthVariant;
7536 if (!(tf & Qt::TextDontPrint)) {
7537 bool restore = false;
7538 if (!dontclip && !r.contains(bounds)) {
7541 painter->setClipRect(r, Qt::IntersectClip);
7544 for (int i = 0; i < textLayout.lineCount(); i++) {
7545 QTextLine line = textLayout.lineAt(i);
7546 QTextEngine *eng = textLayout.engine();
7547 eng->enableDelayDecorations();
7549 qreal advance = line.horizontalAdvance();
7551 if (tf & Qt::AlignRight) {
7552 xoff = r.width() - advance -
7553 eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
7555 else if (tf & Qt::AlignHCenter)
7556 xoff = (r.width() - advance) / 2;
7558 line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
7559 eng->drawDecorations(painter);
7569 Sets the layout direction used by the painter when drawing text,
7570 to the specified \a direction.
7572 The default is Qt::LayoutDirectionAuto, which will implicitly determine the
7573 direction from the text drawn.
7575 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
7577 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
7581 d->state->layoutDirection = direction;
7585 Returns the layout direction used by the painter when drawing text.
7587 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
7589 Qt::LayoutDirection QPainter::layoutDirection() const
7591 Q_D(const QPainter);
7592 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
7595 QPainterState::QPainterState(const QPainterState *s)
7596 : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
7597 pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
7598 clipRegion(s->clipRegion), clipPath(s->clipPath),
7599 clipOperation(s->clipOperation),
7600 renderHints(s->renderHints), clipInfo(s->clipInfo),
7601 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
7602 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
7603 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
7604 opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
7605 clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
7606 layoutDirection(s->layoutDirection),
7607 composition_mode(s->composition_mode),
7608 emulationSpecifier(s->emulationSpecifier), changeFlags(0)
7610 dirtyFlags = s->dirtyFlags;
7613 QPainterState::QPainterState()
7614 : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
7616 wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
7617 opacity(1), WxF(false), VxF(false), clipEnabled(true),
7618 bgMode(Qt::TransparentMode), painter(0),
7619 layoutDirection(QGuiApplication::layoutDirection()),
7620 composition_mode(QPainter::CompositionMode_SourceOver),
7621 emulationSpecifier(0), changeFlags(0)
7626 QPainterState::~QPainterState()
7630 void QPainterState::init(QPainter *p) {
7631 bgBrush = Qt::white;
7632 bgMode = Qt::TransparentMode;
7636 wx = wy = ww = wh = 0;
7637 vx = vy = vw = vh = 0;
7640 brushOrigin = QPointF(0, 0);
7642 font = deviceFont = QFont();
7643 clipRegion = QRegion();
7644 clipPath = QPainterPath();
7645 clipOperation = Qt::NoClip;
7647 worldMatrix.reset();
7649 layoutDirection = QGuiApplication::layoutDirection();
7650 composition_mode = QPainter::CompositionMode_SourceOver;
7651 emulationSpecifier = 0;
7659 \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
7660 Qt::ImageConversionFlags flags)
7662 Draws the rectangular portion \a source of the given \a image
7663 into the \a target rectangle in the paint device.
7665 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7667 If the image needs to be modified to fit in a lower-resolution
7668 result (e.g. converting from 32-bit to 8-bit), use the \a flags to
7669 specify how you would prefer this to happen.
7674 \snippet code/src_gui_painting_qpainter.cpp 20
7681 \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
7682 Qt::ImageConversionFlags flags)
7685 Draws the rectangular portion \a source of the given \a image
7686 into the \a target rectangle in the paint device.
7688 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7692 \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
7696 Draws the given \a image at the given \a point.
7700 \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
7704 Draws the given \a image at the given \a point.
7708 \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
7709 Qt::ImageConversionFlags flags = 0)
7713 Draws the rectangular portion \a source of the given \a image with
7714 its origin at the given \a point.
7718 \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
7719 Qt::ImageConversionFlags flags = 0)
7722 Draws the rectangular portion \a source of the given \a image with
7723 its origin at the given \a point.
7727 \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
7731 Draws the given \a image into the given \a rectangle.
7733 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7737 \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
7741 Draws the given \a image into the given \a rectangle.
7743 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7747 \fn void QPainter::drawImage(int x, int y, const QImage &image,
7748 int sx, int sy, int sw, int sh,
7749 Qt::ImageConversionFlags flags)
7752 Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
7755 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
7756 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
7757 image that is to be drawn. The default is (0, 0).
7759 (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
7760 The default, (0, 0) (and negative) means all the way to the
7761 bottom-right of the image.
7765 \class QPaintEngineState
7768 \brief The QPaintEngineState class provides information about the
7769 active paint engine's current state.
7772 QPaintEngineState records which properties that have changed since
7773 the last time the paint engine was updated, as well as their
7776 Which properties that have changed can at any time be retrieved
7777 using the state() function. This function returns an instance of
7778 the QPaintEngine::DirtyFlags type which stores an OR combination
7779 of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
7780 enum defines whether a property has changed since the last update
7783 If a property is marked with a dirty flag, its current value can
7784 be retrieved using the corresponding get function:
7789 \header \li Property Flag \li Current Property Value
7790 \row \li QPaintEngine::DirtyBackground \li backgroundBrush()
7791 \row \li QPaintEngine::DirtyBackgroundMode \li backgroundMode()
7792 \row \li QPaintEngine::DirtyBrush \li brush()
7793 \row \li QPaintEngine::DirtyBrushOrigin \li brushOrigin()
7794 \row \li QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
7796 \row \li QPaintEngine::DirtyClipPath \li clipPath()
7797 \row \li QPaintEngine::DirtyClipRegion \li clipRegion()
7798 \row \li QPaintEngine::DirtyCompositionMode \li compositionMode()
7799 \row \li QPaintEngine::DirtyFont \li font()
7800 \row \li QPaintEngine::DirtyTransform \li transform()
7801 \row \li QPaintEngine::DirtyClipEnabled \li isClipEnabled()
7802 \row \li QPaintEngine::DirtyPen \li pen()
7803 \row \li QPaintEngine::DirtyHints \li renderHints()
7806 The QPaintEngineState class also provide the painter() function
7807 which returns a pointer to the painter that is currently updating
7810 An instance of this class, representing the current state of the
7811 active paint engine, is passed as argument to the
7812 QPaintEngine::updateState() function. The only situation in which
7813 you will have to use this class directly is when implementing your
7821 \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
7823 Returns a combination of flags identifying the set of properties
7824 that need to be updated when updating the paint engine's state
7825 (i.e. during a call to the QPaintEngine::updateState() function).
7827 \sa QPaintEngine::updateState()
7832 Returns the pen in the current paint engine state.
7834 This variable should only be used when the state() returns a
7835 combination which includes the QPaintEngine::DirtyPen flag.
7837 \sa state(), QPaintEngine::updateState()
7840 QPen QPaintEngineState::pen() const
7842 return static_cast<const QPainterState *>(this)->pen;
7846 Returns the brush in the current paint engine state.
7848 This variable should only be used when the state() returns a
7849 combination which includes the QPaintEngine::DirtyBrush flag.
7851 \sa state(), QPaintEngine::updateState()
7854 QBrush QPaintEngineState::brush() const
7856 return static_cast<const QPainterState *>(this)->brush;
7860 Returns the brush origin in the current paint engine state.
7862 This variable should only be used when the state() returns a
7863 combination which includes the QPaintEngine::DirtyBrushOrigin flag.
7865 \sa state(), QPaintEngine::updateState()
7868 QPointF QPaintEngineState::brushOrigin() const
7870 return static_cast<const QPainterState *>(this)->brushOrigin;
7874 Returns the background brush in the current paint engine state.
7876 This variable should only be used when the state() returns a
7877 combination which includes the QPaintEngine::DirtyBackground flag.
7879 \sa state(), QPaintEngine::updateState()
7882 QBrush QPaintEngineState::backgroundBrush() const
7884 return static_cast<const QPainterState *>(this)->bgBrush;
7888 Returns the background mode in the current paint engine
7891 This variable should only be used when the state() returns a
7892 combination which includes the QPaintEngine::DirtyBackgroundMode flag.
7894 \sa state(), QPaintEngine::updateState()
7897 Qt::BGMode QPaintEngineState::backgroundMode() const
7899 return static_cast<const QPainterState *>(this)->bgMode;
7903 Returns the font in the current paint engine
7906 This variable should only be used when the state() returns a
7907 combination which includes the QPaintEngine::DirtyFont flag.
7909 \sa state(), QPaintEngine::updateState()
7912 QFont QPaintEngineState::font() const
7914 return static_cast<const QPainterState *>(this)->font;
7921 Returns the matrix in the current paint engine
7924 \note It is advisable to use transform() instead of this function to
7925 preserve the properties of perspective transformations.
7927 This variable should only be used when the state() returns a
7928 combination which includes the QPaintEngine::DirtyTransform flag.
7930 \sa state(), QPaintEngine::updateState()
7933 QMatrix QPaintEngineState::matrix() const
7935 const QPainterState *st = static_cast<const QPainterState *>(this);
7937 return st->matrix.toAffine();
7943 Returns the matrix in the current paint engine state.
7945 This variable should only be used when the state() returns a
7946 combination which includes the QPaintEngine::DirtyTransform flag.
7948 \sa state(), QPaintEngine::updateState()
7952 QTransform QPaintEngineState::transform() const
7954 const QPainterState *st = static_cast<const QPainterState *>(this);
7961 Returns the clip operation in the current paint engine
7964 This variable should only be used when the state() returns a
7965 combination which includes either the QPaintEngine::DirtyClipPath
7966 or the QPaintEngine::DirtyClipRegion flag.
7968 \sa state(), QPaintEngine::updateState()
7971 Qt::ClipOperation QPaintEngineState::clipOperation() const
7973 return static_cast<const QPainterState *>(this)->clipOperation;
7979 Returns whether the coordinate of the fill have been specified
7980 as bounded by the current rendering operation and have to be
7981 resolved (about the currently rendered primitive).
7983 bool QPaintEngineState::brushNeedsResolving() const
7985 const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
7986 return needsResolving(brush);
7993 Returns whether the coordinate of the stroke have been specified
7994 as bounded by the current rendering operation and have to be
7995 resolved (about the currently rendered primitive).
7997 bool QPaintEngineState::penNeedsResolving() const
7999 const QPen &pen = static_cast<const QPainterState *>(this)->pen;
8000 return needsResolving(pen.brush());
8004 Returns the clip region in the current paint engine state.
8006 This variable should only be used when the state() returns a
8007 combination which includes the QPaintEngine::DirtyClipRegion flag.
8009 \sa state(), QPaintEngine::updateState()
8012 QRegion QPaintEngineState::clipRegion() const
8014 return static_cast<const QPainterState *>(this)->clipRegion;
8018 Returns the clip path in the current paint engine state.
8020 This variable should only be used when the state() returns a
8021 combination which includes the QPaintEngine::DirtyClipPath flag.
8023 \sa state(), QPaintEngine::updateState()
8026 QPainterPath QPaintEngineState::clipPath() const
8028 return static_cast<const QPainterState *>(this)->clipPath;
8032 Returns whether clipping is enabled or not in the current paint
8035 This variable should only be used when the state() returns a
8036 combination which includes the QPaintEngine::DirtyClipEnabled
8039 \sa state(), QPaintEngine::updateState()
8042 bool QPaintEngineState::isClipEnabled() const
8044 return static_cast<const QPainterState *>(this)->clipEnabled;
8048 Returns the render hints in the current paint engine state.
8050 This variable should only be used when the state() returns a
8051 combination which includes the QPaintEngine::DirtyHints
8054 \sa state(), QPaintEngine::updateState()
8057 QPainter::RenderHints QPaintEngineState::renderHints() const
8059 return static_cast<const QPainterState *>(this)->renderHints;
8063 Returns the composition mode in the current paint engine state.
8065 This variable should only be used when the state() returns a
8066 combination which includes the QPaintEngine::DirtyCompositionMode
8069 \sa state(), QPaintEngine::updateState()
8072 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8074 return static_cast<const QPainterState *>(this)->composition_mode;
8079 Returns a pointer to the painter currently updating the paint
8083 QPainter *QPaintEngineState::painter() const
8085 return static_cast<const QPainterState *>(this)->painter;
8092 Returns the opacity in the current paint engine state.
8095 qreal QPaintEngineState::opacity() const
8097 return static_cast<const QPainterState *>(this)->opacity;
8103 Sets the world transformation matrix.
8104 If \a combine is true, the specified \a transform is combined with
8105 the current matrix; otherwise it replaces the current matrix.
8107 \sa transform(), setWorldTransform()
8110 void QPainter::setTransform(const QTransform &transform, bool combine )
8112 setWorldTransform(transform, combine);
8116 Returns the world transformation matrix.
8118 \sa worldTransform()
8121 const QTransform & QPainter::transform() const
8123 return worldTransform();
8128 Returns the matrix that transforms from logical coordinates to
8129 device coordinates of the platform dependent paint device.
8131 This function is \e only needed when using platform painting
8132 commands on the platform dependent handle (Qt::HANDLE), and the
8133 platform does not do transformations nativly.
8135 The QPaintEngine::PaintEngineFeature enum can be queried to
8136 determine whether the platform performs the transformations or
8139 \sa worldTransform(), QPaintEngine::hasFeature(),
8142 const QTransform & QPainter::deviceTransform() const
8144 Q_D(const QPainter);
8146 qWarning("QPainter::deviceTransform: Painter not active");
8147 return d->fakeState()->transform;
8149 return d->state->matrix;
8154 Resets any transformations that were made using translate(),
8155 scale(), shear(), rotate(), setWorldTransform(), setViewport()
8158 \sa {Coordinate Transformations}
8161 void QPainter::resetTransform()
8164 #ifdef QT_DEBUG_DRAW
8165 if (qt_show_painter_debug_output)
8166 printf("QPainter::resetMatrix()\n");
8169 qWarning("QPainter::resetMatrix: Painter not active");
8173 d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins
8174 d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
8175 d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
8176 d->state->worldMatrix = QTransform();
8177 setMatrixEnabled(false);
8178 setViewTransformEnabled(false);
8180 d->extended->transformChanged();
8182 d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
8186 Sets the world transformation matrix.
8187 If \a combine is true, the specified \a matrix is combined with the current matrix;
8188 otherwise it replaces the current matrix.
8190 \sa transform(), setTransform()
8193 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
8198 qWarning("QPainter::setWorldTransform: Painter not active");
8203 d->state->worldMatrix = matrix * d->state->worldMatrix; // combines
8205 d->state->worldMatrix = matrix; // set new matrix
8207 d->state->WxF = true;
8212 Returns the world transformation matrix.
8215 const QTransform & QPainter::worldTransform() const
8217 Q_D(const QPainter);
8219 qWarning("QPainter::worldTransform: Painter not active");
8220 return d->fakeState()->transform;
8222 return d->state->worldMatrix;
8226 Returns the transformation matrix combining the current
8227 window/viewport and world transformation.
8229 \sa setWorldTransform(), setWindow(), setViewport()
8232 QTransform QPainter::combinedTransform() const
8234 Q_D(const QPainter);
8236 qWarning("QPainter::combinedTransform: Painter not active");
8237 return QTransform();
8239 return d->state->worldMatrix * d->viewTransform();
8245 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
8246 at multiple positions with different scale, rotation and opacity. \a
8247 fragments is an array of \a fragmentCount elements specifying the
8248 parameters used to draw each pixmap fragment. The \a hints
8249 parameter can be used to pass in drawing hints.
8251 This function is potentially faster than multiple calls to drawPixmap(),
8252 since the backend can optimize state changes.
8254 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
8257 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
8258 const QPixmap &pixmap, PixmapFragmentHints hints)
8262 if (!d->engine || pixmap.isNull())
8266 for (int i = 0; i < fragmentCount; ++i) {
8267 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8268 fragments[i].width, fragments[i].height);
8269 if (!(QRectF(pixmap.rect()).contains(sourceRect)))
8270 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
8274 if (d->engine->isExtended()) {
8275 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
8277 qreal oldOpacity = opacity();
8278 QTransform oldTransform = transform();
8280 for (int i = 0; i < fragmentCount; ++i) {
8281 QTransform transform = oldTransform;
8284 if (fragments[i].rotation == 0) {
8285 xOffset = fragments[i].x;
8286 yOffset = fragments[i].y;
8288 transform.translate(fragments[i].x, fragments[i].y);
8289 transform.rotate(fragments[i].rotation);
8291 setOpacity(oldOpacity * fragments[i].opacity);
8292 setTransform(transform);
8294 qreal w = fragments[i].scaleX * fragments[i].width;
8295 qreal h = fragments[i].scaleY * fragments[i].height;
8296 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8297 fragments[i].width, fragments[i].height);
8298 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
8301 setOpacity(oldOpacity);
8302 setTransform(oldTransform);
8308 \class QPainter::PixmapFragment
8310 \brief This class is used in conjunction with the
8311 QPainter::drawPixmapFragments() function to specify how a pixmap, or
8312 sub-rect of a pixmap, is drawn.
8314 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
8315 as a source rectangle within the pixmap passed into the
8316 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
8317 width and \a height are used to calculate the target rectangle that is
8318 drawn. \a x and \a y denotes the center of the target rectangle. The \a
8319 width and \a height in the target rectangle is scaled by the \a scaleX and
8320 \a scaleY values. The resulting target rectangle is then rotated \a
8321 rotation degrees around the \a x, \a y center point.
8323 \sa QPainter::drawPixmapFragments()
8329 This is a convenience function that returns a QPainter::PixmapFragment that is
8330 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
8331 rotation, \a opacity parameters.
8334 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
8335 qreal scaleX, qreal scaleY, qreal rotation,
8338 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
8339 sourceRect.height(), scaleX, scaleY, rotation, opacity};
8344 \variable QPainter::PixmapFragment::x
8345 \brief the x coordinate of center point in the target rectangle.
8349 \variable QPainter::PixmapFragment::y
8350 \brief the y coordinate of the center point in the target rectangle.
8354 \variable QPainter::PixmapFragment::sourceLeft
8355 \brief the left coordinate of the source rectangle.
8359 \variable QPainter::PixmapFragment::sourceTop
8360 \brief the top coordinate of the source rectangle.
8364 \variable QPainter::PixmapFragment::width
8366 \brief the width of the source rectangle and is used to calculate the width
8367 of the target rectangle.
8371 \variable QPainter::PixmapFragment::height
8373 \brief the height of the source rectangle and is used to calculate the
8374 height of the target rectangle.
8378 \variable QPainter::PixmapFragment::scaleX
8379 \brief the horizontal scale of the target rectangle.
8383 \variable QPainter::PixmapFragment::scaleY
8384 \brief the vertical scale of the target rectangle.
8388 \variable QPainter::PixmapFragment::rotation
8390 \brief the rotation of the target rectangle in degrees. The target
8391 rectangle is rotated after it has been scaled.
8395 \variable QPainter::PixmapFragment::opacity
8397 \brief the opacity of the target rectangle, where 0.0 is fully transparent
8398 and 1.0 is fully opaque.
8404 \enum QPainter::PixmapFragmentHint
8406 \value OpaqueHint Indicates that the pixmap fragments to be drawn are
8407 opaque. Opaque fragments are potentially faster to draw.
8409 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
8412 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
8414 p->draw_helper(path, operation);