1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
50 #include "qpaintdevice.h"
51 #include "qpaintengine.h"
53 #include "qpainter_p.h"
54 #include "qpainterpath.h"
56 #include "qpixmapcache.h"
58 #include "qtextlayout.h"
60 #include "qvarlengtharray.h"
61 #include "qstatictext.h"
62 #include "qglyphrun.h"
64 #include <qpa/qplatformtheme.h>
66 #include <private/qfontengine_p.h>
67 #include <private/qpaintengine_p.h>
68 #include <private/qemulationpaintengine_p.h>
69 #include <private/qpainterpath_p.h>
70 #include <private/qtextengine_p.h>
71 #include <private/qpaintengine_raster_p.h>
72 #include <private/qmath_p.h>
73 #include <private/qstatictext_p.h>
74 #include <private/qglyphrun_p.h>
75 #include <private/qhexstring_p.h>
76 #include <private/qguiapplication_p.h>
77 #include <private/qrawfont_p.h>
81 #define QGradient_StretchToDevice 0x10000000
82 #define QPaintEngine_OpaqueBackground 0x40000000
84 // #define QT_DEBUG_DRAW
86 bool qt_show_painter_debug_output = true;
89 extern QPixmap qt_pixmapForBrush(int style, bool invert);
91 void qt_format_text(const QFont &font,
92 const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
93 int tabstops, int* tabarray, int tabarraylen,
95 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
96 QTextCharFormat::UnderlineStyle underlineStyle,
97 QTextItem::RenderFlags flags, qreal width,
98 const QTextCharFormat &charFormat);
99 // Helper function to calculate left most position, width and flags for decoration drawing
100 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
101 const QFixedPoint *positions, int glyphCount,
102 QFontEngine *fontEngine, const QFont &font,
103 const QTextCharFormat &charFormat);
105 static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush)
107 switch (brush.style()) {
108 case Qt::LinearGradientPattern:
109 case Qt::RadialGradientPattern:
110 case Qt::ConicalGradientPattern:
111 return brush.gradient()->coordinateMode();
115 return QGradient::LogicalMode;
118 /* Returns true if the gradient requires stretch to device...*/
119 static inline bool check_gradient(const QBrush &brush)
121 return coordinateMode(brush) == QGradient::StretchToDeviceMode;
124 extern bool qHasPixmapTexture(const QBrush &);
126 static inline bool is_brush_transparent(const QBrush &brush) {
127 Qt::BrushStyle s = brush.style();
128 bool brushBitmap = qHasPixmapTexture(brush)
129 ? brush.texture().isQBitmap()
130 : (brush.textureImage().depth() == 1);
131 return ((s >= Qt::Dense1Pattern && s <= Qt::DiagCrossPattern)
132 || (s == Qt::TexturePattern && brushBitmap));
135 static inline bool is_pen_transparent(const QPen &pen) {
136 return pen.style() > Qt::SolidLine || is_brush_transparent(pen.brush());
139 /* Discards the emulation flags that are not relevant for line drawing
140 and returns the result
142 static inline uint line_emulation(uint emulation)
144 return emulation & (QPaintEngine::PrimitiveTransform
145 | QPaintEngine::AlphaBlend
146 | QPaintEngine::Antialiasing
147 | QPaintEngine::BrushStroke
148 | QPaintEngine::ConstantOpacity
149 | QGradient_StretchToDevice
150 | QPaintEngine::ObjectBoundingModeGradients
151 | QPaintEngine_OpaqueBackground);
155 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
158 case QInternal::Image:
159 case QInternal::Printer:
160 case QInternal::Picture:
161 // can be drawn onto these devices safely from any thread
165 if (!extraCondition && QThread::currentThread() != qApp->thread()) {
166 qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
175 void QPainterPrivate::checkEmulation()
178 if (extended->flags() & QPaintEngineEx::DoNotEmulate)
181 bool doEmulation = false;
182 if (state->bgMode == Qt::OpaqueMode)
185 const QGradient *bg = state->brush.gradient();
186 if (bg && bg->coordinateMode() > QGradient::LogicalMode)
189 const QGradient *pg = qpen_brush(state->pen).gradient();
190 if (pg && pg->coordinateMode() > QGradient::LogicalMode)
194 if (extended != emulationEngine) {
195 if (!emulationEngine)
196 emulationEngine = new QEmulationPaintEngine(extended);
197 extended = emulationEngine;
198 extended->setState(state);
200 } else if (emulationEngine == extended) {
201 extended = emulationEngine->real_engine;
206 QPainterPrivate::~QPainterPrivate()
208 delete emulationEngine;
209 for (int i=0; i<states.size(); ++i)
217 QTransform QPainterPrivate::viewTransform() const
220 qreal scaleW = qreal(state->vw)/qreal(state->ww);
221 qreal scaleH = qreal(state->vh)/qreal(state->wh);
222 return QTransform(scaleW, 0, 0, scaleH,
223 state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
231 Returns true if using a shared painter; otherwise false.
233 bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
238 QPainter *sp = pdev->sharedPainter();
242 // Save the current state of the shared painter and assign
243 // the current d_ptr to the shared painter's d_ptr.
245 if (!sp->d_ptr->d_ptrs) {
246 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
247 // redirections within the same paintEvent(), which should be enough
248 // in 99% of all cases). E.g: A renders B which renders C which renders D.
249 sp->d_ptr->d_ptrs_size = 4;
250 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
251 Q_CHECK_PTR(sp->d_ptr->d_ptrs);
252 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
253 // However, to support corner cases we grow the array dynamically if needed.
254 sp->d_ptr->d_ptrs_size <<= 1;
255 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
256 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
258 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
260 q->d_ptr.reset(sp->d_ptr.data());
262 Q_ASSERT(q->d_ptr->state);
264 // Now initialize the painter with correct widget properties.
267 pdev->redirected(&offset);
268 offset += q->d_ptr->engine->coordinateOffset();
270 // Update system rect.
271 q->d_ptr->state->ww = q->d_ptr->state->vw = pdev->width();
272 q->d_ptr->state->wh = q->d_ptr->state->vh = pdev->height();
275 if (q->d_ptr->state->WxF) {
276 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix;
277 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
278 q->d_ptr->state->worldMatrix = QTransform();
279 q->d_ptr->state->WxF = false;
281 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
283 q->d_ptr->updateMatrix();
285 QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
286 if (enginePrivate->currentClipDevice == pdev) {
287 enginePrivate->systemStateChanged();
291 // Update system transform and clip.
292 enginePrivate->currentClipDevice = pdev;
293 enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
297 void QPainterPrivate::detachPainterPrivate(QPainter *q)
299 Q_ASSERT(refcount > 1);
302 QPainterPrivate *original = d_ptrs[--refcount - 1];
304 inDestructor = false;
306 original->inDestructor = true;
307 } else if (!original) {
308 original = new QPainterPrivate(q);
311 d_ptrs[refcount - 1] = 0;
314 q->d_ptr.reset(original);
316 if (emulationEngine) {
317 extended = emulationEngine->real_engine;
318 delete emulationEngine;
324 void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op)
327 if (qt_show_painter_debug_output) {
328 printf("QPainter::drawHelper\n");
332 if (originalPath.isEmpty())
335 QPaintEngine::PaintEngineFeatures gradientStretch =
336 QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
337 | QPaintEngine::ObjectBoundingModeGradients);
339 const bool mustEmulateObjectBoundingModeGradients = extended
340 || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients)
341 && !engine->hasFeature(QPaintEngine::PatternTransform));
343 if (!(state->emulationSpecifier & ~gradientStretch)
344 && !mustEmulateObjectBoundingModeGradients) {
345 drawStretchedGradient(originalPath, op);
347 } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {
348 drawOpaqueBackground(originalPath, op);
354 qreal strokeOffsetX = 0, strokeOffsetY = 0;
356 QPainterPath path = originalPath * state->matrix;
357 QRectF pathBounds = path.boundingRect();
359 bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
361 qreal penWidth = state->pen.widthF();
366 // In case of complex xform
367 if (state->matrix.type() > QTransform::TxScale) {
368 QPainterPathStroker stroker;
369 stroker.setWidth(penWidth);
370 stroker.setJoinStyle(state->pen.joinStyle());
371 stroker.setCapStyle(state->pen.capStyle());
372 QPainterPath stroke = stroker.createStroke(originalPath);
373 strokeBounds = (stroke * state->matrix).boundingRect();
375 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);
376 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);
382 if (!strokeBounds.isEmpty()) {
383 absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
385 absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
386 .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
389 if (q->hasClipping()) {
390 bool hasPerspectiveTransform = false;
391 for (int i = 0; i < state->clipInfo.size(); ++i) {
392 const QPainterClipInfo &info = state->clipInfo.at(i);
393 if (info.matrix.type() == QTransform::TxProject) {
394 hasPerspectiveTransform = true;
398 // avoid mapping QRegions with perspective transforms
399 if (!hasPerspectiveTransform) {
400 // The trick with txinv and invMatrix is done in order to
401 // avoid transforming the clip to logical coordinates, and
402 // then back to device coordinates. This is a problem with
403 // QRegion/QRect based clips, since they use integer
404 // coordinates and converting to/from logical coordinates will
406 bool old_txinv = txinv;
407 QTransform old_invMatrix = invMatrix;
409 invMatrix = QTransform();
410 QPainterPath clipPath = q->clipPath();
411 QRectF r = clipPath.boundingRect().intersected(absPathRect);
412 absPathRect = r.toAlignedRect();
414 invMatrix = old_invMatrix;
418 // qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
419 // devMinX, devMinY, device->width(), device->height());
420 // qDebug() << " - matrix" << state->matrix;
421 // qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
422 // qDebug() << " - path.bounds" << path.boundingRect();
424 if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
427 QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
432 p.d_ptr->helper_device = helper_device;
434 p.setOpacity(state->opacity);
435 p.translate(-absPathRect.x(), -absPathRect.y());
436 p.setTransform(state->matrix, true);
437 p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
438 p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
439 p.setBackground(state->bgBrush);
440 p.setBackgroundMode(state->bgMode);
441 p.setBrushOrigin(state->brushOrigin);
443 p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);
444 p.setRenderHint(QPainter::SmoothPixmapTransform,
445 state->renderHints & QPainter::SmoothPixmapTransform);
447 p.drawPath(originalPath);
450 static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0;
451 if (do_fallback_overlay) {
452 QImage block(8, 8, QImage::Format_ARGB32_Premultiplied);
454 pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
455 pt.drawLine(0, 0, 8, 8);
458 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
460 p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
467 state->matrix = QTransform();
469 extended->transformChanged();
471 state->dirtyFlags |= QPaintEngine::DirtyTransform;
474 engine->drawImage(absPathRect,
476 QRectF(0, 0, absPathRect.width(), absPathRect.height()),
477 Qt::OrderedDither | Qt::OrderedAlphaDither);
481 void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op)
485 q->setBackgroundMode(Qt::TransparentMode);
487 if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
488 q->fillPath(path, state->bgBrush.color());
489 q->fillPath(path, state->brush);
492 if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
493 q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
494 q->strokePath(path, state->pen);
497 q->setBackgroundMode(Qt::OpaqueMode);
500 static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
502 Q_ASSERT(brush.style() >= Qt::LinearGradientPattern
503 && brush.style() <= Qt::ConicalGradientPattern);
505 QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
506 boundingRect.x(), boundingRect.y());
508 QGradient g = *brush.gradient();
509 g.setCoordinateMode(QGradient::LogicalMode);
512 b.setTransform(gradientToUser * b.transform());
516 void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op)
520 const qreal sw = helper_device->width();
521 const qreal sh = helper_device->height();
523 bool changedPen = false;
524 bool changedBrush = false;
525 bool needsFill = false;
527 const QPen pen = state->pen;
528 const QBrush brush = state->brush;
530 const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
531 const QGradient::CoordinateMode brushMode = coordinateMode(brush);
535 // Draw the xformed fill if the brush is a stretch gradient.
536 if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
537 if (brushMode == QGradient::StretchToDeviceMode) {
538 q->setPen(Qt::NoPen);
539 changedPen = pen.style() != Qt::NoPen;
543 const qreal isw = 1.0 / sw;
544 const qreal ish = 1.0 / sh;
545 QTransform inv(isw, 0, 0, ish, 0, 0);
546 engine->drawPath(path * inv);
551 if (brushMode == QGradient::ObjectBoundingMode) {
552 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
553 boundingRect = path.boundingRect();
554 q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
560 if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
561 // Draw the xformed outline if the pen is a stretch gradient.
562 if (penMode == QGradient::StretchToDeviceMode) {
563 q->setPen(Qt::NoPen);
568 engine->drawPath(path);
572 q->setBrush(pen.brush());
576 QPainterPathStroker stroker;
577 stroker.setDashPattern(pen.style());
578 stroker.setWidth(pen.widthF());
579 stroker.setJoinStyle(pen.joinStyle());
580 stroker.setCapStyle(pen.capStyle());
581 stroker.setMiterLimit(pen.miterLimit());
582 QPainterPath stroke = stroker.createStroke(path);
584 const qreal isw = 1.0 / sw;
585 const qreal ish = 1.0 / sh;
586 QTransform inv(isw, 0, 0, ish, 0, 0);
587 engine->drawPath(stroke * inv);
590 if (!needsFill && brush.style() != Qt::NoBrush) {
591 q->setBrush(Qt::NoBrush);
595 if (penMode == QGradient::ObjectBoundingMode) {
596 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
598 // avoid computing the bounding rect twice
599 if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
600 boundingRect = path.boundingRect();
603 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect));
606 } else if (changedPen) {
612 engine->drawPath(path);
614 } else if (needsFill) {
615 if (pen.style() != Qt::NoPen) {
616 q->setPen(Qt::NoPen);
621 engine->drawPath(path);
631 void QPainterPrivate::updateMatrix()
633 state->matrix = state->WxF ? state->worldMatrix : QTransform();
635 state->matrix *= viewTransform();
637 txinv = false; // no inverted matrix
638 state->matrix *= state->redirectionMatrix;
640 extended->transformChanged();
642 state->dirtyFlags |= QPaintEngine::DirtyTransform;
644 // printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
645 // qDebug() << " --- using matrix" << state->matrix << redirection_offset;
649 void QPainterPrivate::updateInvMatrix()
651 Q_ASSERT(txinv == false);
652 txinv = true; // creating inverted matrix
653 invMatrix = state->matrix.inverted();
656 extern bool qt_isExtendedRadialGradient(const QBrush &brush);
658 void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
661 bool linearGradient = false;
662 bool radialGradient = false;
663 bool extendedRadialGradient = false;
664 bool conicalGradient = false;
665 bool patternBrush = false;
667 bool complexXform = false;
671 // Pen and brush properties (we have to check both if one changes because the
672 // one that's unchanged can still be in a state which requires emulation)
673 if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) {
674 // Check Brush stroke emulation
675 if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke))
676 s->emulationSpecifier |= QPaintEngine::BrushStroke;
678 s->emulationSpecifier &= ~QPaintEngine::BrushStroke;
682 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
683 Qt::BrushStyle brushStyle = qbrush_style(s->brush);
684 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
685 alpha = (penBrushStyle != Qt::NoBrush
686 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
687 && !penBrush.isOpaque())
688 || (brushStyle != Qt::NoBrush
689 && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
690 && !s->brush.isOpaque());
691 linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
692 (brushStyle == Qt::LinearGradientPattern));
693 radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
694 (brushStyle == Qt::RadialGradientPattern));
695 extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
696 conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
697 (brushStyle == Qt::ConicalGradientPattern));
698 patternBrush = (((penBrushStyle > Qt::SolidPattern
699 && penBrushStyle < Qt::LinearGradientPattern)
700 || penBrushStyle == Qt::TexturePattern) ||
701 ((brushStyle > Qt::SolidPattern
702 && brushStyle < Qt::LinearGradientPattern)
703 || brushStyle == Qt::TexturePattern));
705 bool penTextureAlpha = false;
706 if (penBrush.style() == Qt::TexturePattern)
707 penTextureAlpha = qHasPixmapTexture(penBrush)
708 ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
709 : penBrush.textureImage().hasAlphaChannel();
710 bool brushTextureAlpha = false;
711 if (s->brush.style() == Qt::TexturePattern) {
712 brushTextureAlpha = qHasPixmapTexture(s->brush)
713 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
714 : s->brush.textureImage().hasAlphaChannel();
716 if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
717 || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
718 && !engine->hasFeature(QPaintEngine::MaskedBrush))
719 s->emulationSpecifier |= QPaintEngine::MaskedBrush;
721 s->emulationSpecifier &= ~QPaintEngine::MaskedBrush;
724 if (s->state() & (QPaintEngine::DirtyHints
725 | QPaintEngine::DirtyOpacity
726 | QPaintEngine::DirtyBackgroundMode)) {
734 qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
736 " - linearGradient: %d\n"
737 " - radialGradient: %d\n"
738 " - conicalGradient: %d\n"
739 " - patternBrush: %d\n"
748 uint(s->renderHints),
753 if (s->state() & QPaintEngine::DirtyTransform) {
754 xform = !s->matrix.isIdentity();
755 complexXform = !s->matrix.isAffine();
756 } else if (s->matrix.type() >= QTransform::TxTranslate) {
758 complexXform = !s->matrix.isAffine();
761 const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone);
762 const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone);
764 const bool patternXform = patternBrush && (xform || brushXform || penXform);
766 // Check alphablending
767 if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend))
768 s->emulationSpecifier |= QPaintEngine::AlphaBlend;
770 s->emulationSpecifier &= ~QPaintEngine::AlphaBlend;
772 // Linear gradient emulation
773 if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill))
774 s->emulationSpecifier |= QPaintEngine::LinearGradientFill;
776 s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
778 // Radial gradient emulation
779 if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
780 s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
782 s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
784 // Conical gradient emulation
785 if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
786 s->emulationSpecifier |= QPaintEngine::ConicalGradientFill;
788 s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill;
791 if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
792 s->emulationSpecifier |= QPaintEngine::PatternBrush;
794 s->emulationSpecifier &= ~QPaintEngine::PatternBrush;
797 if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform))
798 s->emulationSpecifier |= QPaintEngine::PatternTransform;
800 s->emulationSpecifier &= ~QPaintEngine::PatternTransform;
803 if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform))
804 s->emulationSpecifier |= QPaintEngine::PrimitiveTransform;
806 s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform;
808 // Perspective XForms
809 if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform))
810 s->emulationSpecifier |= QPaintEngine::PerspectiveTransform;
812 s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform;
815 if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity))
816 s->emulationSpecifier |= QPaintEngine::ConstantOpacity;
818 s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity;
820 bool gradientStretch = false;
821 bool objectBoundingMode = false;
822 if (linearGradient || conicalGradient || radialGradient) {
823 QGradient::CoordinateMode brushMode = coordinateMode(s->brush);
824 QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush());
826 gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
827 gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
829 objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
830 objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
833 s->emulationSpecifier |= QGradient_StretchToDevice;
835 s->emulationSpecifier &= ~QGradient_StretchToDevice;
837 if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
838 s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients;
840 s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients;
842 // Opaque backgrounds...
843 if (s->bgMode == Qt::OpaqueMode &&
844 (is_pen_transparent(s->pen) || is_brush_transparent(s->brush)))
845 s->emulationSpecifier |= QPaintEngine_OpaqueBackground;
847 s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground;
850 //won't be correct either way because the device can already have
851 // something rendered to it in which case subsequent emulation
852 // on a fully transparent qimage and then blitting the results
853 // won't produce correct results
855 if (state->composition_mode > QPainter::CompositionMode_Xor &&
856 !engine->hasFeature(QPaintEngine::BlendModes))
857 s->emulationSpecifier |= QPaintEngine::BlendModes;
859 s->emulationSpecifier &= ~QPaintEngine::BlendModes;
863 void QPainterPrivate::updateStateImpl(QPainterState *newState)
865 // ### we might have to call QPainter::begin() here...
866 if (!engine->state) {
867 engine->state = newState;
868 engine->setDirty(QPaintEngine::AllDirty);
871 if (engine->state->painter() != newState->painter)
872 // ### this could break with clip regions vs paths.
873 engine->setDirty(QPaintEngine::AllDirty);
875 // Upon restore, revert all changes since last save
876 else if (engine->state != newState)
877 newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
879 // We need to store all changes made so that restore can deal with them
881 newState->changeFlags |= newState->dirtyFlags;
883 updateEmulationSpecifier(newState);
885 // Unset potential dirty background mode
886 newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode
887 | QPaintEngine::DirtyBackground);
889 engine->state = newState;
890 engine->updateState(*newState);
891 engine->clearDirty(QPaintEngine::AllDirty);
895 void QPainterPrivate::updateState(QPainterState *newState)
899 engine->state = newState;
901 } else if (newState->state() || engine->state!=newState) {
902 bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
903 && newState->pen.widthF() == 0;
904 if (setNonCosmeticPen) {
905 // Override the default pen's cosmetic state if the
906 // NonCosmeticDefaultPen render hint is used.
907 QPen oldPen = newState->pen;
908 newState->pen.setWidth(1);
909 newState->pen.setCosmetic(false);
910 newState->dirtyFlags |= QPaintEngine::DirtyPen;
912 updateStateImpl(newState);
914 // Restore the state pen back to its default to preserve visible
916 newState->pen = oldPen;
918 updateStateImpl(newState);
926 \brief The QPainter class performs low-level painting on widgets and
934 QPainter provides highly optimized functions to do most of the
935 drawing GUI programs require. It can draw everything from simple
936 lines to complex shapes like pies and chords. It can also draw
937 aligned text and pixmaps. Normally, it draws in a "natural"
938 coordinate system, but it can also do view and world
939 transformation. QPainter can operate on any object that inherits
940 the QPaintDevice class.
942 The common use of QPainter is inside a widget's paint event:
943 Construct and customize (e.g. set the pen or the brush) the
944 painter. Then draw. Remember to destroy the QPainter object after
945 drawing. For example:
947 \snippet code/src_gui_painting_qpainter.cpp 0
949 The core functionality of QPainter is drawing, but the class also
950 provide several functions that allows you to customize QPainter's
951 settings and its rendering quality, and others that enable
952 clipping. In addition you can control how different shapes are
953 merged together by specifying the painter's composition mode.
955 The isActive() function indicates whether the painter is active. A
956 painter is activated by the begin() function and the constructor
957 that takes a QPaintDevice argument. The end() function, and the
958 destructor, deactivates it.
960 Together with the QPaintDevice and QPaintEngine classes, QPainter
961 form the basis for Qt's paint system. QPainter is the class used
962 to perform drawing operations. QPaintDevice represents a device
963 that can be painted on using a QPainter. QPaintEngine provides the
964 interface that the painter uses to draw onto different types of
965 devices. If the painter is active, device() returns the paint
966 device on which the painter paints, and paintEngine() returns the
967 paint engine that the painter is currently operating on. For more
968 information, see the \l {Paint System}.
970 Sometimes it is desirable to make someone else paint on an unusual
971 QPaintDevice. QPainter supports a static function to do this,
974 \warning When the paintdevice is a widget, QPainter can only be
975 used inside a paintEvent() function or in a function called by
982 There are several settings that you can customize to make QPainter
983 draw according to your preferences:
987 \li font() is the font used for drawing text. If the painter
988 isActive(), you can retrieve information about the currently set
989 font, and its metrics, using the fontInfo() and fontMetrics()
990 functions respectively.
992 \li brush() defines the color or pattern that is used for filling
995 \li pen() defines the color or stipple that is used for drawing
998 \li backgroundMode() defines whether there is a background() or
999 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
1001 \li background() only applies when backgroundMode() is \l
1002 Qt::OpaqueMode and pen() is a stipple. In that case, it
1003 describes the color of the background pixels in the stipple.
1005 \li brushOrigin() defines the origin of the tiled brushes, normally
1006 the origin of widget's background.
1008 \li viewport(), window(), worldTransform() make up the painter's coordinate
1009 transformation system. For more information, see the \l
1010 {Coordinate Transformations} section and the \l {Coordinate
1011 System} documentation.
1013 \li hasClipping() tells whether the painter clips at all. (The paint
1014 device clips, too.) If the painter clips, it clips to clipRegion().
1016 \li layoutDirection() defines the layout direction used by the
1017 painter when drawing text.
1019 \li worldMatrixEnabled() tells whether world transformation is enabled.
1021 \li viewTransformEnabled() tells whether view transformation is
1026 Note that some of these settings mirror settings in some paint
1027 devices, e.g. QWidget::font(). The QPainter::begin() function (or
1028 equivalently the QPainter constructor) copies these attributes
1029 from the paint device.
1031 You can at any time save the QPainter's state by calling the
1032 save() function which saves all the available settings on an
1033 internal stack. The restore() function pops them back.
1037 QPainter provides functions to draw most primitives: drawPoint(),
1038 drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1039 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1040 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
1041 convenience functions, drawRects() and drawLines(), draw the given
1042 number of rectangles or lines in the given array of \l
1043 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1046 The QPainter class also provides the fillRect() function which
1047 fills the given QRect, with the given QBrush, and the eraseRect()
1048 function that erases the area inside the given rectangle.
1050 All of these functions have both integer and floating point
1055 \li \inlineimage qpainter-basicdrawing.png
1057 \b {Basic Drawing Example}
1059 The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1060 display basic graphics primitives in a variety of styles using the
1065 If you need to draw a complex shape, especially if you need to do
1066 so repeatedly, consider creating a QPainterPath and drawing it
1072 \b {Painter Paths example}
1074 The QPainterPath class provides a container for painting
1075 operations, enabling graphical shapes to be constructed and
1078 The \l {painting/painterpaths}{Painter Paths} example shows how
1079 painter paths can be used to build complex shapes for rendering.
1081 \li \inlineimage qpainter-painterpaths.png
1084 QPainter also provides the fillPath() function which fills the
1085 given QPainterPath with the given QBrush, and the strokePath()
1086 function that draws the outline of the given path (i.e. strokes
1089 See also the \l {painting/deform}{Vector Deformation} example which
1090 shows how to use advanced vector techniques to draw text using a
1091 QPainterPath, the \l {painting/gradients}{Gradients} example which shows
1092 the different types of gradients that are available in Qt, and the \l
1093 {painting/pathstroke}{Path Stroking} example which shows Qt's built-in
1094 dash patterns and shows how custom patterns can be used to extend
1095 the range of available patterns.
1099 \li \l {painting/deform}{Vector Deformation}
1100 \li \l {painting/gradients}{Gradients}
1101 \li \l {painting/pathstroke}{Path Stroking}
1103 \li \inlineimage qpainter-vectordeformation.png
1104 \li \inlineimage qpainter-gradients.png
1105 \li \inlineimage qpainter-pathstroking.png
1109 There are functions to draw pixmaps/images, namely drawPixmap(),
1110 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1111 produce the same result, except that drawPixmap() is faster
1112 on-screen while drawImage() may be faster on a QPrinter or other
1115 Text drawing is done using drawText(). When you need
1116 fine-grained positioning, boundingRect() tells you where a given
1117 drawText() command will draw.
1119 There is a drawPicture() function that draws the contents of an
1120 entire QPicture. The drawPicture() function is the only function
1121 that disregards all the painter's settings as QPicture has its own
1124 \section1 Rendering Quality
1126 To get the optimal rendering result using QPainter, you should use
1127 the platform independent QImage as paint device; i.e. using QImage
1128 will ensure that the result has an identical pixel representation
1131 The QPainter class also provides a means of controlling the
1132 rendering quality through its RenderHint enum and the support for
1133 floating point precision: All the functions for drawing primitives
1134 has a floating point version. These are often used in combination
1135 with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1139 \li \inlineimage qpainter-concentriccircles.png
1141 \b {Concentric Circles Example}
1143 The \l {painting/concentriccircles}{Concentric Circles} example
1144 shows the improved rendering quality that can be obtained using
1145 floating point precision and anti-aliasing when drawing custom
1148 The application's main window displays several widgets which are
1149 drawn using the various combinations of precision and
1154 The RenderHint enum specifies flags to QPainter that may or may
1155 not be respected by any given engine. \l
1156 {RenderHint}{QPainter::Antialiasing} indicates that the engine
1157 should antialias edges of primitives if possible, \l
1158 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1159 should antialias text if possible, and the \l
1160 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1161 engine should use a smooth pixmap transformation algorithm.
1162 \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
1163 indicating that the engine should use fragment programs and offscreen
1164 rendering for antialiasing.
1166 The renderHints() function returns a flag that specifies the
1167 rendering hints that are set for this painter. Use the
1168 setRenderHint() function to set or clear the currently set
1171 \section1 Coordinate Transformations
1173 Normally, the QPainter operates on the device's own coordinate
1174 system (usually pixels), but QPainter has good support for
1175 coordinate transformations.
1179 \li nop \li rotate() \li scale() \li translate()
1181 \li \inlineimage qpainter-clock.png
1182 \li \inlineimage qpainter-rotation.png
1183 \li \inlineimage qpainter-scale.png
1184 \li \inlineimage qpainter-translation.png
1187 The most commonly used transformations are scaling, rotation,
1188 translation and shearing. Use the scale() function to scale the
1189 coordinate system by a given offset, the rotate() function to
1190 rotate it clockwise and translate() to translate it (i.e. adding a
1191 given offset to the points). You can also twist the coordinate
1192 system around the origin using the shear() function. See the \l
1193 {painting/affine}{Affine Transformations} example for a visualization of
1194 a sheared coordinate system.
1196 See also the \l {painting/transformations}{Transformations}
1197 example which shows how transformations influence the way that
1198 QPainter renders graphics primitives. In particular it shows how
1199 the order of transformations affects the result.
1204 \b {Affine Transformations Example}
1206 The \l {painting/affine}{Affine Transformations} example shows Qt's
1207 ability to perform affine transformations on painting
1208 operations. The demo also allows the user to experiment with the
1209 transformation operations and see the results immediately.
1211 \li \inlineimage qpainter-affinetransformations.png
1214 All the tranformation operations operate on the transformation
1215 worldTransform(). A matrix transforms a point in the plane to another
1216 point. For more information about the transformation matrix, see
1217 the \l {Coordinate System} and QTransform documentation.
1219 The setWorldTransform() function can replace or add to the currently
1220 set worldTransform(). The resetTransform() function resets any
1221 transformations that were made using translate(), scale(),
1222 shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1223 functions. The deviceTransform() returns the matrix that transforms
1224 from logical coordinates to device coordinates of the platform
1225 dependent paint device. The latter function is only needed when
1226 using platform painting commands on the platform dependent handle,
1227 and the platform does not do transformations nativly.
1229 When drawing with QPainter, we specify points using logical
1230 coordinates which then are converted into the physical coordinates
1231 of the paint device. The mapping of the logical coordinates to the
1232 physical coordinates are handled by QPainter's combinedTransform(), a
1233 combination of viewport() and window() and worldTransform(). The
1234 viewport() represents the physical coordinates specifying an
1235 arbitrary rectangle, the window() describes the same rectangle in
1236 logical coordinates, and the worldTransform() is identical with the
1237 transformation matrix.
1239 See also \l {Coordinate System}
1243 QPainter can clip any drawing operation to a rectangle, a region,
1244 or a vector path. The current clip is available using the
1245 functions clipRegion() and clipPath(). Whether paths or regions are
1246 preferred (faster) depends on the underlying paintEngine(). For
1247 example, the QImage paint engine prefers paths while the X11 paint
1248 engine prefers regions. Setting a clip is done in the painters
1249 logical coordinates.
1251 After QPainter's clipping, the paint device may also clip. For
1252 example, most widgets clip away the pixels used by child widgets,
1253 and most printers clip away an area near the edges of the paper.
1254 This additional clipping is not reflected by the return value of
1255 clipRegion() or hasClipping().
1257 \section1 Composition Modes
1258 \target Composition Modes
1260 QPainter provides the CompositionMode enum which defines the
1261 Porter-Duff rules for digital image compositing; it describes a
1262 model for combining the pixels in one image, the source, with the
1263 pixels in another image, the destination.
1265 The two most common forms of composition are \l
1266 {QPainter::CompositionMode}{Source} and \l
1267 {QPainter::CompositionMode}{SourceOver}. \l
1268 {QPainter::CompositionMode}{Source} is used to draw opaque objects
1269 onto a paint device. In this mode, each pixel in the source
1270 replaces the corresponding pixel in the destination. In \l
1271 {QPainter::CompositionMode}{SourceOver} composition mode, the
1272 source object is transparent and is drawn on top of the
1275 Note that composition transformation operates pixelwise. For that
1276 reason, there is a difference between using the graphic primitive
1277 itself and its bounding rectangle: The bounding rect contains
1278 pixels with alpha == 0 (i.e the pixels surrounding the
1279 primitive). These pixels will overwrite the other image's pixels,
1280 affectively clearing those, while the primitive only overwrites
1285 \li \inlineimage qpainter-compositiondemo.png
1288 \b {Composition Modes Example}
1290 The \l {painting/composition}{Composition Modes} example, available in
1291 Qt's examples directory, allows you to experiment with the various
1292 composition modes and see the results immediately.
1296 \section1 Limitations
1299 If you are using coordinates with Qt's raster-based paint engine, it is
1300 important to note that, while coordinates greater than +/- 2\sup 15 can
1301 be used, any painting performed with coordinates outside this range is not
1302 guaranteed to be shown; the drawing may be clipped. This is due to the
1303 use of \c{short int} in the implementation.
1305 The outlines generated by Qt's stroker are only an approximation when dealing
1306 with curved shapes. It is in most cases impossible to represent the outline of
1307 a bezier curve segment using another bezier curve segment, and so Qt approximates
1308 the curve outlines by using several smaller curves. For performance reasons there
1309 is a limit to how many curves Qt uses for these outlines, and thus when using
1310 large pen widths or scales the outline error increases. To generate outlines with
1311 smaller errors it is possible to use the QPainterPathStroker class, which has the
1312 setCurveThreshold member function which let's the user specify the error tolerance.
1313 Another workaround is to convert the paths to polygons first and then draw the
1316 \section1 Performance
1318 QPainter is a rich framework that allows developers to do a great
1319 variety of graphical operations, such as gradients, composition
1320 modes and vector graphics. And QPainter can do this across a
1321 variety of different hardware and software stacks. Naturally the
1322 underlying combination of hardware and software has some
1323 implications for performance, and ensuring that every single
1324 operation is fast in combination with all the various combinations
1325 of composition modes, brushes, clipping, transformation, etc, is
1326 close to an impossible task because of the number of
1327 permutations. As a compromise we have selected a subset of the
1328 QPainter API and backends, where performance is guaranteed to be as
1329 good as we can sensibly get it for the given combination of
1330 hardware and software.
1332 The backends we focus on as high-performance engines are:
1336 \li Raster - This backend implements all rendering in pure software
1337 and is always used to render into QImages. For optimal performance
1338 only use the format types QImage::Format_ARGB32_Premultiplied,
1339 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1340 including QImage::Format_ARGB32, has significantly worse
1341 performance. This engine is used by default for QWidget and QPixmap.
1343 \li OpenGL 2.0 (ES) - This backend is the primary backend for
1344 hardware accelerated graphics. It can be run on desktop machines
1345 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1346 specification. This includes most graphics chips produced in the
1347 last couple of years. The engine can be enabled by using QPainter
1348 onto a QOpenGLWidget or by passing \c {-graphicssystem opengl} on the
1349 command line when the underlying system supports it.
1351 \li OpenVG - This backend implements the Khronos standard for 2D
1352 and Vector Graphics. It is primarily for embedded devices with
1353 hardware support for OpenVG. The engine can be enabled by
1354 passing \c {-graphicssystem openvg} on the command line when
1355 the underlying system supports it.
1359 These operations are:
1363 \li Simple transformations, meaning translation and scaling, pluss
1364 0, 90, 180, 270 degree rotations.
1366 \li \c drawPixmap() in combination with simple transformations and
1367 opacity with non-smooth transformation mode
1368 (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1370 \li Rectangle fills with solid color, two-color linear gradients
1371 and simple transforms.
1373 \li Rectangular clipping with simple transformations and intersect
1376 \li Composition Modes \c QPainter::CompositionMode_Source and
1377 QPainter::CompositionMode_SourceOver
1379 \li Rounded rectangle filling using solid color and two-color
1380 linear gradients fills.
1382 \li 3x3 patched pixmaps, via qDrawBorderPixmap.
1386 This list gives an indication of which features to safely use in
1387 an application where performance is critical. For certain setups,
1388 other operations may be fast too, but before making extensive use
1389 of them, it is recommended to benchmark and verify them on the
1390 system where the software will run in the end. There are also
1391 cases where expensive operations are ok to use, for instance when
1392 the result is cached in a QPixmap.
1394 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
1395 {Drawing Utility Functions}
1399 \enum QPainter::RenderHint
1401 Renderhints are used to specify flags to QPainter that may or
1402 may not be respected by any given engine.
1404 \value Antialiasing Indicates that the engine should antialias
1405 edges of primitives if possible.
1407 \value TextAntialiasing Indicates that the engine should antialias
1408 text if possible. To forcibly disable antialiasing for text, do not
1409 use this hint. Instead, set QFont::NoAntialias on your font's style
1412 \value SmoothPixmapTransform Indicates that the engine should use
1413 a smooth pixmap transformation algorithm (such as bilinear) rather
1414 than nearest neighbor.
1416 \value HighQualityAntialiasing An OpenGL-specific rendering hint
1417 indicating that the engine should use fragment programs and offscreen
1418 rendering for antialiasing.
1420 \value NonCosmeticDefaultPen The engine should interpret pens with a width
1421 of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
1422 pen with a width of 1.
1424 \sa renderHints(), setRenderHint(), {QPainter#Rendering
1425 Quality}{Rendering Quality}, {Concentric Circles Example}
1430 Constructs a painter.
1435 QPainter::QPainter()
1436 : d_ptr(new QPainterPrivate(this))
1441 \fn QPainter::QPainter(QPaintDevice *device)
1443 Constructs a painter that begins painting the paint \a device
1446 This constructor is convenient for short-lived painters, e.g. in a
1447 QWidget::paintEvent() and should be used only once. The
1448 constructor calls begin() for you and the QPainter destructor
1449 automatically calls end().
1451 Here's an example using begin() and end():
1452 \snippet code/src_gui_painting_qpainter.cpp 1
1454 The same example using this constructor:
1455 \snippet code/src_gui_painting_qpainter.cpp 2
1457 Since the constructor cannot provide feedback when the initialization
1458 of the painter failed you should rather use begin() and end() to paint
1459 on external devices, e.g. printers.
1464 QPainter::QPainter(QPaintDevice *pd)
1468 if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1469 d_ptr.reset(new QPainterPrivate(this));
1476 Destroys the painter.
1478 QPainter::~QPainter()
1480 d_ptr->inDestructor = true;
1484 else if (d_ptr->refcount > 1)
1485 d_ptr->detachPainterPrivate(this);
1487 // don't throw anything in the destructor.
1490 // Make sure we haven't messed things up.
1491 Q_ASSERT(d_ptr->inDestructor);
1492 d_ptr->inDestructor = false;
1493 Q_ASSERT(d_ptr->refcount == 1);
1495 free(d_ptr->d_ptrs);
1500 Returns the paint device on which this painter is currently
1501 painting, or 0 if the painter is not active.
1506 QPaintDevice *QPainter::device() const
1508 Q_D(const QPainter);
1509 if (isActive() && d->engine->d_func()->currentClipDevice)
1510 return d->engine->d_func()->currentClipDevice;
1511 return d->original_device;
1515 Returns true if begin() has been called and end() has not yet been
1516 called; otherwise returns false.
1518 \sa begin(), QPaintDevice::paintingActive()
1521 bool QPainter::isActive() const
1523 Q_D(const QPainter);
1528 Initializes the painters pen, background and font to the same as
1529 the given \a device.
1533 \sa begin(), {QPainter#Settings}{Settings}
1535 void QPainter::initFrom(const QPaintDevice *device)
1537 Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0");
1540 qWarning("QPainter::initFrom: Painter not active, aborted");
1544 device->initPainter(this);
1547 d->extended->penChanged();
1548 } else if (d->engine) {
1549 d->engine->setDirty(QPaintEngine::DirtyPen);
1550 d->engine->setDirty(QPaintEngine::DirtyBrush);
1551 d->engine->setDirty(QPaintEngine::DirtyFont);
1557 Saves the current painter state (pushes the state onto a stack). A
1558 save() must be followed by a corresponding restore(); the end()
1559 function unwinds the stack.
1564 void QPainter::save()
1566 #ifdef QT_DEBUG_DRAW
1567 if (qt_show_painter_debug_output)
1568 printf("QPainter::save()\n");
1572 qWarning("QPainter::save: Painter not active");
1577 d->state = d->extended->createState(d->states.back());
1578 d->extended->setState(d->state);
1580 d->updateState(d->state);
1581 d->state = new QPainterState(d->states.back());
1582 d->engine->state = d->state;
1584 d->states.push_back(d->state);
1588 Restores the current painter state (pops a saved state off the
1594 void QPainter::restore()
1596 #ifdef QT_DEBUG_DRAW
1597 if (qt_show_painter_debug_output)
1598 printf("QPainter::restore()\n");
1601 if (d->states.size()<=1) {
1602 qWarning("QPainter::restore: Unbalanced save/restore");
1604 } else if (!d->engine) {
1605 qWarning("QPainter::restore: Painter not active");
1609 QPainterState *tmp = d->state;
1610 d->states.pop_back();
1611 d->state = d->states.back();
1615 d->checkEmulation();
1616 d->extended->setState(d->state);
1621 // trigger clip update if the clip path/region has changed since
1623 if (!d->state->clipInfo.isEmpty()
1624 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1625 // reuse the tmp state to avoid any extra allocs...
1626 tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1627 tmp->clipOperation = Qt::NoClip;
1628 tmp->clipPath = QPainterPath();
1629 d->engine->updateState(*tmp);
1630 // replay the list of clip states,
1631 for (int i=0; i<d->state->clipInfo.size(); ++i) {
1632 const QPainterClipInfo &info = d->state->clipInfo.at(i);
1633 tmp->matrix = info.matrix;
1634 tmp->matrix *= d->state->redirectionMatrix;
1635 tmp->clipOperation = info.operation;
1636 if (info.clipType == QPainterClipInfo::RectClip) {
1637 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1638 tmp->clipRegion = info.rect;
1639 } else if (info.clipType == QPainterClipInfo::RegionClip) {
1640 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1641 tmp->clipRegion = info.region;
1642 } else { // clipType == QPainterClipInfo::PathClip
1643 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1644 tmp->clipPath = info.path;
1646 d->engine->updateState(*tmp);
1650 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1651 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1652 tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1653 tmp->changeFlags |= QPaintEngine::DirtyTransform;
1656 d->updateState(d->state);
1663 \fn bool QPainter::begin(QPaintDevice *device)
1665 Begins painting the paint \a device and returns true if
1666 successful; otherwise returns false.
1668 Notice that all painter settings (setPen(), setBrush() etc.) are reset
1669 to default values when begin() is called.
1671 The errors that can occur are serious problems, such as these:
1673 \snippet code/src_gui_painting_qpainter.cpp 3
1675 Note that most of the time, you can use one of the constructors
1676 instead of begin(), and that end() is automatically done at
1679 \warning A paint device can only be painted by one painter at a
1682 \warning Painting on a QImage with the format
1683 QImage::Format_Indexed8 is not supported.
1685 \sa end(), QPainter()
1688 static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1697 bool QPainter::begin(QPaintDevice *pd)
1701 if (pd->painters > 0) {
1702 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1706 if (d_ptr->engine) {
1707 qWarning("QPainter::begin: Painter already active");
1711 if (QPainterPrivate::attachPainterPrivate(this, pd))
1716 d->helper_device = pd;
1717 d->original_device = pd;
1719 QPoint redirectionOffset;
1720 QPaintDevice *rpd = pd->redirected(&redirectionOffset);
1724 #ifdef QT_DEBUG_DRAW
1725 if (qt_show_painter_debug_output)
1726 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1729 if (pd->devType() == QInternal::Pixmap)
1730 static_cast<QPixmap *>(pd)->detach();
1731 else if (pd->devType() == QInternal::Image)
1732 static_cast<QImage *>(pd)->detach();
1734 d->engine = pd->paintEngine();
1737 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1743 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1744 if (d->emulationEngine)
1745 d->emulationEngine->real_engine = d->extended;
1747 // Setup new state...
1748 Q_ASSERT(!d->state);
1749 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1750 d->state->painter = this;
1751 d->states.push_back(d->state);
1753 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1754 d->state->brushOrigin = QPointF();
1756 // Slip a painter state into the engine before we do any other operations
1758 d->extended->setState(d->state);
1760 d->engine->state = d->state;
1762 switch (pd->devType()) {
1763 case QInternal::Pixmap:
1765 QPixmap *pm = static_cast<QPixmap *>(pd);
1768 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1769 qt_cleanup_painter_state(d);
1773 if (pm->depth() == 1) {
1774 d->state->pen = QPen(Qt::color1);
1775 d->state->brush = QBrush(Qt::color0);
1779 case QInternal::Image:
1781 QImage *img = static_cast<QImage *>(pd);
1783 if (img->isNull()) {
1784 qWarning("QPainter::begin: Cannot paint on a null image");
1785 qt_cleanup_painter_state(d);
1787 } else if (img->format() == QImage::Format_Indexed8) {
1788 // Painting on indexed8 images is not supported.
1789 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1790 qt_cleanup_painter_state(d);
1793 if (img->depth() == 1) {
1794 d->state->pen = QPen(Qt::color1);
1795 d->state->brush = QBrush(Qt::color0);
1802 if (d->state->ww == 0) // For compat with 3.x painter defaults
1803 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1805 d->engine->setPaintDevice(pd);
1807 bool begun = d->engine->begin(pd);
1809 qWarning("QPainter::begin(): Returned false");
1810 if (d->engine->isActive()) {
1813 qt_cleanup_painter_state(d);
1817 d->engine->setActive(begun);
1820 // Copy painter properties from original paint device,
1821 // required for QPixmap::grabWidget()
1822 if (d->original_device->devType() == QInternal::Widget) {
1823 initFrom(d->original_device);
1825 d->state->layoutDirection = Qt::LayoutDirectionAuto;
1826 // make sure we have a font compatible with the paintdevice
1827 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1830 QRect systemRect = d->engine->systemRect();
1831 if (!systemRect.isEmpty()) {
1832 d->state->ww = d->state->vw = systemRect.width();
1833 d->state->wh = d->state->vh = systemRect.height();
1835 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1836 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1839 const QPoint coordinateOffset = d->engine->coordinateOffset();
1840 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1842 Q_ASSERT(d->engine->isActive());
1844 if (!d->state->redirectionMatrix.isIdentity())
1847 Q_ASSERT(d->engine->isActive());
1848 d->state->renderHints = QPainter::TextAntialiasing;
1849 ++d->device->painters;
1851 d->state->emulationSpecifier = 0;
1857 Ends painting. Any resources used while painting are released. You
1858 don't normally need to call this since it is called by the
1861 Returns true if the painter is no longer active; otherwise returns false.
1863 \sa begin(), isActive()
1866 bool QPainter::end()
1868 #ifdef QT_DEBUG_DRAW
1869 if (qt_show_painter_debug_output)
1870 printf("QPainter::end()\n");
1875 qWarning("QPainter::end: Painter not active, aborted");
1876 qt_cleanup_painter_state(d);
1880 if (d->refcount > 1) {
1881 d->detachPainterPrivate(this);
1887 if (d->engine->isActive()) {
1888 ended = d->engine->end();
1891 --d->device->painters;
1892 if (d->device->painters == 0) {
1893 d->engine->setPaintDevice(0);
1894 d->engine->setActive(false);
1898 if (d->states.size() > 1) {
1899 qWarning("QPainter::end: Painter ended with %d saved states",
1903 if (d->engine->autoDestruct()) {
1907 if (d->emulationEngine) {
1908 delete d->emulationEngine;
1909 d->emulationEngine = 0;
1916 qt_cleanup_painter_state(d);
1923 Returns the paint engine that the painter is currently operating
1924 on if the painter is active; otherwise 0.
1928 QPaintEngine *QPainter::paintEngine() const
1930 Q_D(const QPainter);
1937 Flushes the painting pipeline and prepares for the user issuing commands
1938 directly to the underlying graphics context. Must be followed by a call to
1939 endNativePainting().
1941 Note that only the states the underlying paint engine changes will be reset
1942 to their respective default states. The states we reset may change from
1943 release to release. The following states are currently reset in the OpenGL
1947 \li blending is disabled
1948 \li the depth, stencil and scissor tests are disabled
1949 \li the active texture unit is reset to 0
1950 \li the depth mask, depth function and the clear depth are reset to their
1952 \li the stencil mask, stencil operation and stencil function are reset to
1953 their default values
1954 \li the current color is reset to solid white
1957 If, for example, the OpenGL polygon mode is changed by the user inside a
1958 beginNativePaint()/endNativePainting() block, it will not be reset to the
1959 default state by endNativePainting(). Here is an example that shows
1960 intermixing of painter commands and raw OpenGL commands:
1962 \snippet code/src_gui_painting_qpainter.cpp 21
1964 \sa endNativePainting()
1966 void QPainter::beginNativePainting()
1970 qWarning("QPainter::beginNativePainting: Painter not active");
1975 d->extended->beginNativePainting();
1981 Restores the painter after manually issuing native painting commands. Lets
1982 the painter restore any native state that it relies on before calling any
1983 other painter commands.
1985 \sa beginNativePainting()
1987 void QPainter::endNativePainting()
1989 Q_D(const QPainter);
1991 qWarning("QPainter::beginNativePainting: Painter not active");
1996 d->extended->endNativePainting();
1998 d->engine->syncState();
2002 Returns the font metrics for the painter if the painter is
2003 active. Otherwise, the return value is undefined.
2005 \sa font(), isActive(), {QPainter#Settings}{Settings}
2008 QFontMetrics QPainter::fontMetrics() const
2010 Q_D(const QPainter);
2012 qWarning("QPainter::fontMetrics: Painter not active");
2013 return QFontMetrics(QFont());
2015 return QFontMetrics(d->state->font);
2020 Returns the font info for the painter if the painter is
2021 active. Otherwise, the return value is undefined.
2023 \sa font(), isActive(), {QPainter#Settings}{Settings}
2026 QFontInfo QPainter::fontInfo() const
2028 Q_D(const QPainter);
2030 qWarning("QPainter::fontInfo: Painter not active");
2031 return QFontInfo(QFont());
2033 return QFontInfo(d->state->font);
2039 Returns the opacity of the painter. The default value is
2043 qreal QPainter::opacity() const
2045 Q_D(const QPainter);
2047 qWarning("QPainter::opacity: Painter not active");
2050 return d->state->opacity;
2056 Sets the opacity of the painter to \a opacity. The value should
2057 be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2058 1.0 is fully opaque.
2060 Opacity set on the painter will apply to all drawing operations
2064 void QPainter::setOpacity(qreal opacity)
2069 qWarning("QPainter::setOpacity: Painter not active");
2073 opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2075 if (opacity == d->state->opacity)
2078 d->state->opacity = opacity;
2081 d->extended->opacityChanged();
2083 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2088 Returns the currently set brush origin.
2090 \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2093 QPoint QPainter::brushOrigin() const
2095 Q_D(const QPainter);
2097 qWarning("QPainter::brushOrigin: Painter not active");
2100 return QPointF(d->state->brushOrigin).toPoint();
2104 \fn void QPainter::setBrushOrigin(const QPointF &position)
2106 Sets the brush origin to \a position.
2108 The brush origin specifies the (0, 0) coordinate of the painter's
2111 Note that while the brushOrigin() was necessary to adopt the
2112 parent's background for a widget in Qt 3, this is no longer the
2113 case since the Qt 4 painter doesn't paint the background unless
2114 you explicitly tell it to do so by setting the widget's \l
2115 {QWidget::autoFillBackground}{autoFillBackground} property to
2118 \sa brushOrigin(), {QPainter#Settings}{Settings}
2121 void QPainter::setBrushOrigin(const QPointF &p)
2124 #ifdef QT_DEBUG_DRAW
2125 if (qt_show_painter_debug_output)
2126 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2130 qWarning("QPainter::setBrushOrigin: Painter not active");
2134 d->state->brushOrigin = p;
2137 d->extended->brushOriginChanged();
2141 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2145 \fn void QPainter::setBrushOrigin(const QPoint &position)
2148 Sets the brush's origin to the given \a position.
2152 \fn void QPainter::setBrushOrigin(int x, int y)
2156 Sets the brush's origin to point (\a x, \a y).
2160 \enum QPainter::CompositionMode
2162 Defines the modes supported for digital image compositing.
2163 Composition modes are used to specify how the pixels in one image,
2164 the source, are merged with the pixel in another image, the
2167 Please note that the bitwise raster operation modes, denoted with
2168 a RasterOp prefix, are only natively supported in the X11 and
2169 raster paint engines. This means that the only way to utilize
2170 these modes on the Mac is via a QImage. The RasterOp denoted blend
2171 modes are \e not supported for pens and brushes with alpha
2172 components. Also, turning on the QPainter::Antialiasing render
2173 hint will effectively disable the RasterOp modes.
2176 \image qpainter-compositionmode1.png
2177 \image qpainter-compositionmode2.png
2179 The most common type is SourceOver (often referred to as just
2180 alpha blending) where the source pixel is blended on top of the
2181 destination pixel in such a way that the alpha component of the
2182 source defines the translucency of the pixel.
2184 When the paint device is a QImage, the image format must be set to
2185 \l {QImage::Format}{Format_ARGB32_Premultiplied} or
2186 \l {QImage::Format}{Format_ARGB32} for the composition modes to have
2187 any effect. For performance the premultiplied version is the preferred
2190 When a composition mode is set it applies to all painting
2191 operator, pens, brushes, gradients and pixmap/image drawing.
2193 \value CompositionMode_SourceOver This is the default mode. The
2194 alpha of the source is used to blend the pixel on top of the
2197 \value CompositionMode_DestinationOver The alpha of the
2198 destination is used to blend it on top of the source pixels. This
2199 mode is the inverse of CompositionMode_SourceOver.
2201 \value CompositionMode_Clear The pixels in the destination are
2202 cleared (set to fully transparent) independent of the source.
2204 \value CompositionMode_Source The output is the source
2205 pixel. (This means a basic copy operation and is identical to
2206 SourceOver when the source pixel is opaque).
2208 \value CompositionMode_Destination The output is the destination
2209 pixel. This means that the blending has no effect. This mode is
2210 the inverse of CompositionMode_Source.
2212 \value CompositionMode_SourceIn The output is the source, where
2213 the alpha is reduced by that of the destination.
2215 \value CompositionMode_DestinationIn The output is the
2216 destination, where the alpha is reduced by that of the
2217 source. This mode is the inverse of CompositionMode_SourceIn.
2219 \value CompositionMode_SourceOut The output is the source, where
2220 the alpha is reduced by the inverse of destination.
2222 \value CompositionMode_DestinationOut The output is the
2223 destination, where the alpha is reduced by the inverse of the
2224 source. This mode is the inverse of CompositionMode_SourceOut.
2226 \value CompositionMode_SourceAtop The source pixel is blended on
2227 top of the destination, with the alpha of the source pixel reduced
2228 by the alpha of the destination pixel.
2230 \value CompositionMode_DestinationAtop The destination pixel is
2231 blended on top of the source, with the alpha of the destination
2232 pixel is reduced by the alpha of the destination pixel. This mode
2233 is the inverse of CompositionMode_SourceAtop.
2235 \value CompositionMode_Xor The source, whose alpha is reduced with
2236 the inverse of the destination alpha, is merged with the
2237 destination, whose alpha is reduced by the inverse of the source
2238 alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2240 \value CompositionMode_Plus Both the alpha and color of the source
2241 and destination pixels are added together.
2243 \value CompositionMode_Multiply The output is the source color
2244 multiplied by the destination. Multiplying a color with white
2245 leaves the color unchanged, while multiplying a color
2246 with black produces black.
2248 \value CompositionMode_Screen The source and destination colors
2249 are inverted and then multiplied. Screening a color with white
2250 produces white, whereas screening a color with black leaves the
2253 \value CompositionMode_Overlay Multiplies or screens the colors
2254 depending on the destination color. The destination color is mixed
2255 with the source color to reflect the lightness or darkness of the
2258 \value CompositionMode_Darken The darker of the source and
2259 destination colors is selected.
2261 \value CompositionMode_Lighten The lighter of the source and
2262 destination colors is selected.
2264 \value CompositionMode_ColorDodge The destination color is
2265 brightened to reflect the source color. A black source color
2266 leaves the destination color unchanged.
2268 \value CompositionMode_ColorBurn The destination color is darkened
2269 to reflect the source color. A white source color leaves the
2270 destination color unchanged.
2272 \value CompositionMode_HardLight Multiplies or screens the colors
2273 depending on the source color. A light source color will lighten
2274 the destination color, whereas a dark source color will darken the
2277 \value CompositionMode_SoftLight Darkens or lightens the colors
2278 depending on the source color. Similar to
2279 CompositionMode_HardLight.
2281 \value CompositionMode_Difference Subtracts the darker of the
2282 colors from the lighter. Painting with white inverts the
2283 destination color, whereas painting with black leaves the
2284 destination color unchanged.
2286 \value CompositionMode_Exclusion Similar to
2287 CompositionMode_Difference, but with a lower contrast. Painting
2288 with white inverts the destination color, whereas painting with
2289 black leaves the destination color unchanged.
2291 \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2292 the source and destination pixels (src OR dst).
2294 \value RasterOp_SourceAndDestination Does a bitwise AND operation
2295 on the source and destination pixels (src AND dst).
2297 \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2298 on the source and destination pixels (src XOR dst).
2300 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2301 operation on the source and destination pixels ((NOT src) AND (NOT
2304 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2305 operation on the source and destination pixels ((NOT src) OR (NOT
2308 \value RasterOp_NotSourceXorDestination Does a bitwise operation
2309 where the source pixels are inverted and then XOR'ed with the
2310 destination ((NOT src) XOR dst).
2312 \value RasterOp_NotSource Does a bitwise operation where the
2313 source pixels are inverted (NOT src).
2315 \value RasterOp_NotSourceAndDestination Does a bitwise operation
2316 where the source is inverted and then AND'ed with the destination
2317 ((NOT src) AND dst).
2319 \value RasterOp_SourceAndNotDestination Does a bitwise operation
2320 where the source is AND'ed with the inverted destination pixels
2321 (src AND (NOT dst)).
2323 \value RasterOp_NotSourceOrDestination Does a bitwise operation
2324 where the source is inverted and then OR'ed with the destination
2327 \value RasterOp_ClearDestination The pixels in the destination are
2328 cleared (set to 0) independent of the source.
2330 \value RasterOp_SetDestination The pixels in the destination are
2331 set (set to 1) independent of the source.
2333 \value RasterOp_NotDestination Does a bitwise operation
2334 where the destination pixels are inverted (NOT dst).
2336 \value RasterOp_SourceOrNotDestination Does a bitwise operation
2337 where the source is OR'ed with the inverted destination pixels
2340 \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2341 Modes}{Composition Modes}, {Image Composition Example}
2345 Sets the composition mode to the given \a mode.
2347 \warning Only a QPainter operating on a QImage fully supports all
2348 composition modes. The RasterOp modes are supported for X11 as
2349 described in compositionMode().
2351 \sa compositionMode()
2353 void QPainter::setCompositionMode(CompositionMode mode)
2357 qWarning("QPainter::setCompositionMode: Painter not active");
2360 if (d->state->composition_mode == mode)
2363 d->state->composition_mode = mode;
2364 d->extended->compositionModeChanged();
2368 if (mode >= QPainter::RasterOp_SourceOrDestination) {
2369 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2370 qWarning("QPainter::setCompositionMode: "
2371 "Raster operation modes not supported on device");
2374 } else if (mode >= QPainter::CompositionMode_Plus) {
2375 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2376 qWarning("QPainter::setCompositionMode: "
2377 "Blend modes not supported on device");
2380 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2381 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2382 qWarning("QPainter::setCompositionMode: "
2383 "PorterDuff modes not supported on device");
2388 d->state->composition_mode = mode;
2389 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2393 Returns the current composition mode.
2395 \sa CompositionMode, setCompositionMode()
2397 QPainter::CompositionMode QPainter::compositionMode() const
2399 Q_D(const QPainter);
2401 qWarning("QPainter::compositionMode: Painter not active");
2402 return QPainter::CompositionMode_SourceOver;
2404 return d->state->composition_mode;
2408 Returns the current background brush.
2410 \sa setBackground(), {QPainter#Settings}{Settings}
2413 const QBrush &QPainter::background() const
2415 Q_D(const QPainter);
2417 qWarning("QPainter::background: Painter not active");
2418 return d->fakeState()->brush;
2420 return d->state->bgBrush;
2425 Returns true if clipping has been set; otherwise returns false.
2427 \sa setClipping(), {QPainter#Clipping}{Clipping}
2430 bool QPainter::hasClipping() const
2432 Q_D(const QPainter);
2434 qWarning("QPainter::hasClipping: Painter not active");
2437 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2442 Enables clipping if \a enable is true, or disables clipping if \a
2445 \sa hasClipping(), {QPainter#Clipping}{Clipping}
2448 void QPainter::setClipping(bool enable)
2451 #ifdef QT_DEBUG_DRAW
2452 if (qt_show_painter_debug_output)
2453 printf("QPainter::setClipping(), enable=%s, was=%s\n",
2454 enable ? "on" : "off",
2455 hasClipping() ? "on" : "off");
2458 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2462 if (hasClipping() == enable)
2465 // we can't enable clipping if we don't have a clip
2467 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2469 d->state->clipEnabled = enable;
2472 d->extended->clipEnabledChanged();
2476 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2477 d->updateState(d->state);
2482 Returns the currently set clip region. Note that the clip region
2483 is given in logical coordinates.
2485 \warning QPainter does not store the combined clip explicitly as
2486 this is handled by the underlying QPaintEngine, so the path is
2487 recreated on demand and transformed to the current logical
2488 coordinate system. This is potentially an expensive operation.
2490 \sa setClipRegion(), clipPath(), setClipping()
2493 QRegion QPainter::clipRegion() const
2495 Q_D(const QPainter);
2497 qWarning("QPainter::clipRegion: Painter not active");
2502 bool lastWasNothing = true;
2505 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2507 // ### Falcon: Use QPainterPath
2508 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2509 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2510 switch (info.clipType) {
2512 case QPainterClipInfo::RegionClip: {
2513 QTransform matrix = (info.matrix * d->invMatrix);
2514 if (lastWasNothing) {
2515 region = info.region * matrix;
2516 lastWasNothing = false;
2519 if (info.operation == Qt::IntersectClip)
2520 region &= info.region * matrix;
2521 else if (info.operation == Qt::NoClip) {
2522 lastWasNothing = true;
2525 region = info.region * matrix;
2529 case QPainterClipInfo::PathClip: {
2530 QTransform matrix = (info.matrix * d->invMatrix);
2531 if (lastWasNothing) {
2532 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2533 info.path.fillRule());
2534 lastWasNothing = false;
2537 if (info.operation == Qt::IntersectClip) {
2538 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2539 info.path.fillRule());
2540 } else if (info.operation == Qt::NoClip) {
2541 lastWasNothing = true;
2544 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2545 info.path.fillRule());
2550 case QPainterClipInfo::RectClip: {
2551 QTransform matrix = (info.matrix * d->invMatrix);
2552 if (lastWasNothing) {
2553 region = QRegion(info.rect) * matrix;
2554 lastWasNothing = false;
2557 if (info.operation == Qt::IntersectClip) {
2558 // Use rect intersection if possible.
2559 if (matrix.type() <= QTransform::TxScale)
2560 region &= matrix.mapRect(info.rect);
2562 region &= matrix.map(QRegion(info.rect));
2563 } else if (info.operation == Qt::NoClip) {
2564 lastWasNothing = true;
2567 region = QRegion(info.rect) * matrix;
2572 case QPainterClipInfo::RectFClip: {
2573 QTransform matrix = (info.matrix * d->invMatrix);
2574 if (lastWasNothing) {
2575 region = QRegion(info.rectf.toRect()) * matrix;
2576 lastWasNothing = false;
2579 if (info.operation == Qt::IntersectClip) {
2580 // Use rect intersection if possible.
2581 if (matrix.type() <= QTransform::TxScale)
2582 region &= matrix.mapRect(info.rectf.toRect());
2584 region &= matrix.map(QRegion(info.rectf.toRect()));
2585 } else if (info.operation == Qt::NoClip) {
2586 lastWasNothing = true;
2589 region = QRegion(info.rectf.toRect()) * matrix;
2599 extern QPainterPath qt_regionToPath(const QRegion ®ion);
2602 Returns the currently clip as a path. Note that the clip path is
2603 given in logical coordinates.
2605 \warning QPainter does not store the combined clip explicitly as
2606 this is handled by the underlying QPaintEngine, so the path is
2607 recreated on demand and transformed to the current logical
2608 coordinate system. This is potentially an expensive operation.
2610 \sa setClipPath(), clipRegion(), setClipping()
2612 QPainterPath QPainter::clipPath() const
2614 Q_D(const QPainter);
2616 // ### Since we do not support path intersections and path unions yet,
2617 // we just use clipRegion() here...
2619 qWarning("QPainter::clipPath: Painter not active");
2620 return QPainterPath();
2623 // No clip, return empty
2624 if (d->state->clipInfo.size() == 0) {
2625 return QPainterPath();
2628 // Update inverse matrix, used below.
2630 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2632 // For the simple case avoid conversion.
2633 if (d->state->clipInfo.size() == 1
2634 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2635 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2636 return d->state->clipInfo.at(0).path * matrix;
2638 } else if (d->state->clipInfo.size() == 1
2639 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2640 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2642 path.addRect(d->state->clipInfo.at(0).rect);
2643 return path * matrix;
2645 // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2646 return qt_regionToPath(clipRegion());
2652 Returns the bounding rectangle of the current clip if there is a clip;
2653 otherwise returns an empty rectangle. Note that the clip region is
2654 given in logical coordinates.
2656 The bounding rectangle is not guaranteed to be tight.
2658 \sa setClipRect(), setClipPath(), setClipRegion()
2663 QRectF QPainter::clipBoundingRect() const
2665 Q_D(const QPainter);
2668 qWarning("QPainter::clipBoundingRect: Painter not active");
2672 // Accumulate the bounding box in device space. This is not 100%
2673 // precise, but it fits within the guarantee and it is reasonably
2676 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2678 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2680 if (info.clipType == QPainterClipInfo::RectClip)
2682 else if (info.clipType == QPainterClipInfo::RectFClip)
2684 else if (info.clipType == QPainterClipInfo::RegionClip)
2685 r = info.region.boundingRect();
2687 r = info.path.boundingRect();
2689 r = info.matrix.mapRect(r);
2693 else if (info.operation == Qt::IntersectClip)
2698 // Map the rectangle back into logical space using the inverse
2701 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2703 return d->invMatrix.mapRect(bounds);
2707 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2709 Enables clipping, and sets the clip region to the given \a
2710 rectangle using the given clip \a operation. The default operation
2711 is to replace the current clip rectangle.
2713 Note that the clip rectangle is specified in logical (painter)
2716 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2718 void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2723 if ((!d->state->clipEnabled && op != Qt::NoClip))
2724 op = Qt::ReplaceClip;
2727 qWarning("QPainter::setClipRect: Painter not active");
2730 qreal right = rect.x() + rect.width();
2731 qreal bottom = rect.y() + rect.height();
2732 qreal pts[] = { rect.x(), rect.y(),
2736 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2737 d->state->clipEnabled = true;
2738 d->extended->clip(vp, op);
2739 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2740 d->state->clipInfo.clear();
2741 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2742 d->state->clipOperation = op;
2746 if (qreal(int(rect.top())) == rect.top()
2747 && qreal(int(rect.bottom())) == rect.bottom()
2748 && qreal(int(rect.left())) == rect.left()
2749 && qreal(int(rect.right())) == rect.right())
2751 setClipRect(rect.toRect(), op);
2755 if (rect.isEmpty()) {
2756 setClipRegion(QRegion(), op);
2762 setClipPath(path, op);
2766 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2769 Enables clipping, and sets the clip region to the given \a rectangle using the given
2772 void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2777 qWarning("QPainter::setClipRect: Painter not active");
2781 if ((!d->state->clipEnabled && op != Qt::NoClip))
2782 op = Qt::ReplaceClip;
2785 d->state->clipEnabled = true;
2786 d->extended->clip(rect, op);
2787 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2788 d->state->clipInfo.clear();
2789 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2790 d->state->clipOperation = op;
2794 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2795 op = Qt::ReplaceClip;
2797 d->state->clipRegion = rect;
2798 d->state->clipOperation = op;
2799 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2800 d->state->clipInfo.clear();
2801 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2802 d->state->clipEnabled = true;
2803 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2804 d->updateState(d->state);
2808 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2810 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2811 with the given \a width and \a height.
2815 \fn void QPainter::setClipRegion(const QRegion ®ion, Qt::ClipOperation operation)
2817 Sets the clip region to the given \a region using the specified clip
2818 \a operation. The default clip operation is to replace the current
2821 Note that the clip region is given in logical coordinates.
2823 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2825 void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2828 #ifdef QT_DEBUG_DRAW
2829 QRect rect = r.boundingRect();
2830 if (qt_show_painter_debug_output)
2831 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2832 r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2835 qWarning("QPainter::setClipRegion: Painter not active");
2839 if ((!d->state->clipEnabled && op != Qt::NoClip))
2840 op = Qt::ReplaceClip;
2843 d->state->clipEnabled = true;
2844 d->extended->clip(r, op);
2845 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2846 d->state->clipInfo.clear();
2847 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2848 d->state->clipOperation = op;
2852 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2853 op = Qt::ReplaceClip;
2855 d->state->clipRegion = r;
2856 d->state->clipOperation = op;
2857 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2858 d->state->clipInfo.clear();
2859 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2860 d->state->clipEnabled = true;
2861 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2862 d->updateState(d->state);
2869 Sets the transformation matrix to \a matrix and enables transformations.
2871 \note It is advisable to use setWorldTransform() instead of this function to
2872 preserve the properties of perspective transformations.
2874 If \a combine is true, then \a matrix is combined with the current
2875 transformation matrix; otherwise \a matrix replaces the current
2876 transformation matrix.
2878 If \a matrix is the identity matrix and \a combine is false, this
2879 function calls setWorldMatrixEnabled(false). (The identity matrix is the
2880 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2883 The following functions can transform the coordinate system without using
2892 They operate on the painter's worldMatrix() and are implemented like this:
2894 \snippet code/src_gui_painting_qpainter.cpp 4
2896 Note that when using setWorldMatrix() function you should always have
2897 \a combine be true when you are drawing into a QPicture. Otherwise
2898 it may not be possible to replay the picture with additional
2899 transformations; using the translate(), scale(), etc. convenience
2902 For more information about the coordinate system, transformations
2903 and window-viewport conversion, see \l {Coordinate System}.
2905 \sa setWorldTransform(), QTransform
2908 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2910 setWorldTransform(QTransform(matrix), combine);
2917 Returns the world transformation matrix.
2919 It is advisable to use worldTransform() because worldMatrix() does not
2920 preserve the properties of perspective transformations.
2922 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2926 const QMatrix &QPainter::worldMatrix() const
2928 Q_D(const QPainter);
2930 qWarning("QPainter::worldMatrix: Painter not active");
2931 return d->fakeState()->transform.toAffine();
2933 return d->state->worldMatrix.toAffine();
2939 Use setWorldTransform() instead.
2941 \sa setWorldTransform()
2944 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
2946 setWorldTransform(QTransform(matrix), combine);
2952 Use worldTransform() instead.
2954 \sa worldTransform()
2957 const QMatrix &QPainter::matrix() const
2959 return worldMatrix();
2967 Returns the transformation matrix combining the current
2968 window/viewport and world transformation.
2970 It is advisable to use combinedTransform() instead of this
2971 function to preserve the properties of perspective transformations.
2973 \sa setWorldTransform(), setWindow(), setViewport()
2975 QMatrix QPainter::combinedMatrix() const
2977 return combinedTransform().toAffine();
2984 Returns the matrix that transforms from logical coordinates to
2985 device coordinates of the platform dependent paint device.
2987 \note It is advisable to use deviceTransform() instead of this
2988 function to preserve the properties of perspective transformations.
2990 This function is \e only needed when using platform painting
2991 commands on the platform dependent handle (Qt::HANDLE), and the
2992 platform does not do transformations nativly.
2994 The QPaintEngine::PaintEngineFeature enum can be queried to
2995 determine whether the platform performs the transformations or
2998 \sa worldMatrix(), QPaintEngine::hasFeature(),
3000 const QMatrix &QPainter::deviceMatrix() const
3002 Q_D(const QPainter);
3004 qWarning("QPainter::deviceMatrix: Painter not active");
3005 return d->fakeState()->transform.toAffine();
3007 return d->state->matrix.toAffine();
3013 Resets any transformations that were made using translate(), scale(),
3014 shear(), rotate(), setWorldMatrix(), setViewport() and
3017 It is advisable to use resetTransform() instead of this function
3018 to preserve the properties of perspective transformations.
3020 \sa {QPainter#Coordinate Transformations}{Coordinate
3024 void QPainter::resetMatrix()
3033 Enables transformations if \a enable is true, or disables
3034 transformations if \a enable is false. The world transformation
3035 matrix is not changed.
3037 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3038 Transformations}{Coordinate Transformations}
3041 void QPainter::setWorldMatrixEnabled(bool enable)
3044 #ifdef QT_DEBUG_DRAW
3045 if (qt_show_painter_debug_output)
3046 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3050 qWarning("QPainter::setMatrixEnabled: Painter not active");
3053 if (enable == d->state->WxF)
3056 d->state->WxF = enable;
3063 Returns true if world transformation is enabled; otherwise returns
3066 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3069 bool QPainter::worldMatrixEnabled() const
3071 Q_D(const QPainter);
3073 qWarning("QPainter::worldMatrixEnabled: Painter not active");
3076 return d->state->WxF;
3082 Use setWorldMatrixEnabled() instead.
3084 \sa setWorldMatrixEnabled()
3087 void QPainter::setMatrixEnabled(bool enable)
3089 setWorldMatrixEnabled(enable);
3095 Use worldMatrixEnabled() instead
3097 \sa worldMatrixEnabled()
3100 bool QPainter::matrixEnabled() const
3102 return worldMatrixEnabled();
3106 Scales the coordinate system by (\a{sx}, \a{sy}).
3108 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3111 void QPainter::scale(qreal sx, qreal sy)
3113 #ifdef QT_DEBUG_DRAW
3114 if (qt_show_painter_debug_output)
3115 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3119 qWarning("QPainter::scale: Painter not active");
3123 d->state->worldMatrix.scale(sx,sy);
3124 d->state->WxF = true;
3129 Shears the coordinate system by (\a{sh}, \a{sv}).
3131 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3134 void QPainter::shear(qreal sh, qreal sv)
3136 #ifdef QT_DEBUG_DRAW
3137 if (qt_show_painter_debug_output)
3138 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3142 qWarning("QPainter::shear: Painter not active");
3146 d->state->worldMatrix.shear(sh, sv);
3147 d->state->WxF = true;
3152 \fn void QPainter::rotate(qreal angle)
3154 Rotates the coordinate system clockwise. The given \a angle parameter uses degree unit.
3156 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3159 void QPainter::rotate(qreal a)
3161 #ifdef QT_DEBUG_DRAW
3162 if (qt_show_painter_debug_output)
3163 printf("QPainter::rotate(), angle=%f\n", a);
3167 qWarning("QPainter::rotate: Painter not active");
3171 d->state->worldMatrix.rotate(a);
3172 d->state->WxF = true;
3177 Translates the coordinate system by the given \a offset; i.e. the
3178 given \a offset is added to points.
3180 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3182 void QPainter::translate(const QPointF &offset)
3184 qreal dx = offset.x();
3185 qreal dy = offset.y();
3186 #ifdef QT_DEBUG_DRAW
3187 if (qt_show_painter_debug_output)
3188 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3192 qWarning("QPainter::translate: Painter not active");
3196 d->state->worldMatrix.translate(dx, dy);
3197 d->state->WxF = true;
3202 \fn void QPainter::translate(const QPoint &offset)
3205 Translates the coordinate system by the given \a offset.
3209 \fn void QPainter::translate(qreal dx, qreal dy)
3212 Translates the coordinate system by the vector (\a dx, \a dy).
3216 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3218 Enables clipping, and sets the clip path for the painter to the
3219 given \a path, with the clip \a operation.
3221 Note that the clip path is specified in logical (painter)
3224 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3227 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3229 #ifdef QT_DEBUG_DRAW
3230 if (qt_show_painter_debug_output) {
3231 QRectF b = path.boundingRect();
3232 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3233 path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3239 qWarning("QPainter::setClipPath: Painter not active");
3243 if ((!d->state->clipEnabled && op != Qt::NoClip))
3244 op = Qt::ReplaceClip;
3247 d->state->clipEnabled = true;
3248 d->extended->clip(path, op);
3249 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3250 d->state->clipInfo.clear();
3251 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3252 d->state->clipOperation = op;
3256 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
3257 op = Qt::ReplaceClip;
3259 d->state->clipPath = path;
3260 d->state->clipOperation = op;
3261 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3262 d->state->clipInfo.clear();
3263 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3264 d->state->clipEnabled = true;
3265 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3266 d->updateState(d->state);
3270 Draws the outline (strokes) the path \a path with the pen specified
3273 \sa fillPath(), {QPainter#Drawing}{Drawing}
3275 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3280 qWarning("QPainter::strokePath: Painter not active");
3288 const QGradient *g = qpen_brush(pen).gradient();
3289 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3290 d->extended->stroke(qtVectorPathForPath(path), pen);
3295 QBrush oldBrush = d->state->brush;
3296 QPen oldPen = d->state->pen;
3299 setBrush(Qt::NoBrush);
3309 Fills the given \a path using the given \a brush. The outline is
3312 Alternatively, you can specify a QColor instead of a QBrush; the
3313 QBrush constructor (taking a QColor argument) will automatically
3314 create a solid pattern brush.
3318 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3323 qWarning("QPainter::fillPath: Painter not active");
3331 const QGradient *g = brush.gradient();
3332 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3333 d->extended->fill(qtVectorPathForPath(path), brush);
3338 QBrush oldBrush = d->state->brush;
3339 QPen oldPen = d->state->pen;
3352 Draws the given painter \a path using the current pen for outline
3353 and the current brush for filling.
3357 \li \inlineimage qpainter-path.png
3359 \snippet code/src_gui_painting_qpainter.cpp 5
3362 \sa {painting/painterpaths}{the Painter Paths
3363 example},{painting/deform}{the Vector Deformation example}
3365 void QPainter::drawPath(const QPainterPath &path)
3367 #ifdef QT_DEBUG_DRAW
3368 QRectF pathBounds = path.boundingRect();
3369 if (qt_show_painter_debug_output)
3370 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3371 path.elementCount(),
3372 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3378 qWarning("QPainter::drawPath: Painter not active");
3383 d->extended->drawPath(path);
3386 d->updateState(d->state);
3388 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3389 d->engine->drawPath(path);
3391 d->draw_helper(path);
3396 \fn void QPainter::drawLine(const QLineF &line)
3398 Draws a line defined by \a line.
3402 \li \inlineimage qpainter-line.png
3404 \snippet code/src_gui_painting_qpainter.cpp 6
3407 \sa drawLines(), drawPolyline(), {Coordinate System}
3411 \fn void QPainter::drawLine(const QLine &line)
3414 Draws a line defined by \a line.
3418 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3421 Draws a line from \a p1 to \a p2.
3425 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3428 Draws a line from \a p1 to \a p2.
3432 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3435 Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3436 current pen position to (\a x2, \a y2).
3440 \fn void QPainter::drawRect(const QRectF &rectangle)
3442 Draws the current \a rectangle with the current pen and brush.
3444 A filled rectangle has a size of \a{rectangle}.size(). A stroked
3445 rectangle has a size of \a{rectangle}.size() plus the pen width.
3449 \li \inlineimage qpainter-rectangle.png
3451 \snippet code/src_gui_painting_qpainter.cpp 7
3454 \sa drawRects(), drawPolygon(), {Coordinate System}
3458 \fn void QPainter::drawRect(const QRect &rectangle)
3462 Draws the current \a rectangle with the current pen and brush.
3466 \fn void QPainter::drawRect(int x, int y, int width, int height)
3470 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3471 with the given \a width and \a height.
3475 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3477 Draws the first \a rectCount of the given \a rectangles using the
3478 current pen and brush.
3482 void QPainter::drawRects(const QRectF *rects, int rectCount)
3484 #ifdef QT_DEBUG_DRAW
3485 if (qt_show_painter_debug_output)
3486 printf("QPainter::drawRects(), count=%d\n", rectCount);
3491 qWarning("QPainter::drawRects: Painter not active");
3499 d->extended->drawRects(rects, rectCount);
3503 d->updateState(d->state);
3505 if (!d->state->emulationSpecifier) {
3506 d->engine->drawRects(rects, rectCount);
3510 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3511 && d->state->matrix.type() == QTransform::TxTranslate) {
3512 for (int i=0; i<rectCount; ++i) {
3513 QRectF r(rects[i].x() + d->state->matrix.dx(),
3514 rects[i].y() + d->state->matrix.dy(),
3517 d->engine->drawRects(&r, 1);
3520 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3521 for (int i=0; i<rectCount; ++i) {
3522 QPainterPath rectPath;
3523 rectPath.addRect(rects[i]);
3524 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3527 QPainterPath rectPath;
3528 for (int i=0; i<rectCount; ++i)
3529 rectPath.addRect(rects[i]);
3530 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3536 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3539 Draws the first \a rectCount of the given \a rectangles using the
3540 current pen and brush.
3542 void QPainter::drawRects(const QRect *rects, int rectCount)
3544 #ifdef QT_DEBUG_DRAW
3545 if (qt_show_painter_debug_output)
3546 printf("QPainter::drawRects(), count=%d\n", rectCount);
3551 qWarning("QPainter::drawRects: Painter not active");
3559 d->extended->drawRects(rects, rectCount);
3563 d->updateState(d->state);
3565 if (!d->state->emulationSpecifier) {
3566 d->engine->drawRects(rects, rectCount);
3570 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3571 && d->state->matrix.type() == QTransform::TxTranslate) {
3572 for (int i=0; i<rectCount; ++i) {
3573 QRectF r(rects[i].x() + d->state->matrix.dx(),
3574 rects[i].y() + d->state->matrix.dy(),
3578 d->engine->drawRects(&r, 1);
3581 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3582 for (int i=0; i<rectCount; ++i) {
3583 QPainterPath rectPath;
3584 rectPath.addRect(rects[i]);
3585 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3588 QPainterPath rectPath;
3589 for (int i=0; i<rectCount; ++i)
3590 rectPath.addRect(rects[i]);
3592 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3598 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3601 Draws the given \a rectangles using the current pen and brush.
3605 \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3609 Draws the given \a rectangles using the current pen and brush.
3613 \fn void QPainter::drawPoint(const QPointF &position)
3615 Draws a single point at the given \a position using the current
3618 \sa {Coordinate System}
3622 \fn void QPainter::drawPoint(const QPoint &position)
3625 Draws a single point at the given \a position using the current
3629 /*! \fn void QPainter::drawPoint(int x, int y)
3633 Draws a single point at position (\a x, \a y).
3637 Draws the first \a pointCount points in the array \a points using
3638 the current pen's color.
3640 \sa {Coordinate System}
3642 void QPainter::drawPoints(const QPointF *points, int pointCount)
3644 #ifdef QT_DEBUG_DRAW
3645 if (qt_show_painter_debug_output)
3646 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3651 qWarning("QPainter::drawPoints: Painter not active");
3655 if (pointCount <= 0)
3659 d->extended->drawPoints(points, pointCount);
3663 d->updateState(d->state);
3665 if (!d->state->emulationSpecifier) {
3666 d->engine->drawPoints(points, pointCount);
3670 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3671 && d->state->matrix.type() == QTransform::TxTranslate) {
3672 // ### use drawPoints function
3673 for (int i=0; i<pointCount; ++i) {
3674 QPointF pt(points[i].x() + d->state->matrix.dx(),
3675 points[i].y() + d->state->matrix.dy());
3676 d->engine->drawPoints(&pt, 1);
3679 QPen pen = d->state->pen;
3680 bool flat_pen = pen.capStyle() == Qt::FlatCap;
3683 pen.setCapStyle(Qt::SquareCap);
3687 for (int i=0; i<pointCount; ++i) {
3688 path.moveTo(points[i].x(), points[i].y());
3689 path.lineTo(points[i].x() + 0.0001, points[i].y());
3691 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3700 Draws the first \a pointCount points in the array \a points using
3701 the current pen's color.
3704 void QPainter::drawPoints(const QPoint *points, int pointCount)
3706 #ifdef QT_DEBUG_DRAW
3707 if (qt_show_painter_debug_output)
3708 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3713 qWarning("QPainter::drawPoints: Painter not active");
3717 if (pointCount <= 0)
3721 d->extended->drawPoints(points, pointCount);
3725 d->updateState(d->state);
3727 if (!d->state->emulationSpecifier) {
3728 d->engine->drawPoints(points, pointCount);
3732 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3733 && d->state->matrix.type() == QTransform::TxTranslate) {
3734 // ### use drawPoints function
3735 for (int i=0; i<pointCount; ++i) {
3736 QPointF pt(points[i].x() + d->state->matrix.dx(),
3737 points[i].y() + d->state->matrix.dy());
3738 d->engine->drawPoints(&pt, 1);
3741 QPen pen = d->state->pen;
3742 bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3745 pen.setCapStyle(Qt::SquareCap);
3749 for (int i=0; i<pointCount; ++i) {
3750 path.moveTo(points[i].x(), points[i].y());
3751 path.lineTo(points[i].x() + 0.0001, points[i].y());
3753 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3760 \fn void QPainter::drawPoints(const QPolygonF &points)
3764 Draws the points in the vector \a points.
3768 \fn void QPainter::drawPoints(const QPolygon &points)
3772 Draws the points in the vector \a points.
3776 Sets the background mode of the painter to the given \a mode
3778 Qt::TransparentMode (the default) draws stippled lines and text
3779 without setting the background pixels. Qt::OpaqueMode fills these
3780 space with the current background color.
3782 Note that in order to draw a bitmap or pixmap transparently, you
3783 must use QPixmap::setMask().
3785 \sa backgroundMode(), setBackground(),
3786 {QPainter#Settings}{Settings}
3789 void QPainter::setBackgroundMode(Qt::BGMode mode)
3791 #ifdef QT_DEBUG_DRAW
3792 if (qt_show_painter_debug_output)
3793 printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3798 qWarning("QPainter::setBackgroundMode: Painter not active");
3801 if (d->state->bgMode == mode)
3804 d->state->bgMode = mode;
3806 d->checkEmulation();
3808 d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3813 Returns the current background mode.
3815 \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3817 Qt::BGMode QPainter::backgroundMode() const
3819 Q_D(const QPainter);
3821 qWarning("QPainter::backgroundMode: Painter not active");
3822 return Qt::TransparentMode;
3824 return d->state->bgMode;
3831 Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3835 void QPainter::setPen(const QColor &color)
3837 #ifdef QT_DEBUG_DRAW
3838 if (qt_show_painter_debug_output)
3839 printf("QPainter::setPen(), color=%04x\n", color.rgb());
3843 qWarning("QPainter::setPen: Painter not active");
3847 if (d->state->pen.style() == Qt::SolidLine
3848 && d->state->pen.widthF() == 0
3849 && d->state->pen.isSolid()
3850 && d->state->pen.color() == color)
3853 QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
3855 d->state->pen = pen;
3857 d->extended->penChanged();
3859 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3863 Sets the painter's pen to be the given \a pen.
3865 The \a pen defines how to draw lines and outlines, and it also
3866 defines the text color.
3868 \sa pen(), {QPainter#Settings}{Settings}
3871 void QPainter::setPen(const QPen &pen)
3874 #ifdef QT_DEBUG_DRAW
3875 if (qt_show_painter_debug_output)
3876 printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3877 pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3881 qWarning("QPainter::setPen: Painter not active");
3885 if (d->state->pen == pen)
3888 d->state->pen = pen;
3891 d->checkEmulation();
3892 d->extended->penChanged();
3896 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3902 Sets the painter's pen to have the given \a style, width 0 and
3906 void QPainter::setPen(Qt::PenStyle style)
3910 qWarning("QPainter::setPen: Painter not active");
3914 if (d->state->pen.style() == style
3915 && (style == Qt::NoPen || (d->state->pen.widthF() == 0
3916 && d->state->pen.isSolid()
3917 && d->state->pen.color() == QColor(Qt::black))))
3920 // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
3921 // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
3922 d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
3925 d->extended->penChanged();
3927 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3932 Returns the painter's current pen.
3934 \sa setPen(), {QPainter#Settings}{Settings}
3937 const QPen &QPainter::pen() const
3939 Q_D(const QPainter);
3941 qWarning("QPainter::pen: Painter not active");
3942 return d->fakeState()->pen;
3944 return d->state->pen;
3949 Sets the painter's brush to the given \a brush.
3951 The painter's brush defines how shapes are filled.
3953 \sa brush(), {QPainter#Settings}{Settings}
3956 void QPainter::setBrush(const QBrush &brush)
3958 #ifdef QT_DEBUG_DRAW
3959 if (qt_show_painter_debug_output)
3960 printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
3964 qWarning("QPainter::setBrush: Painter not active");
3968 if (d->state->brush.d == brush.d)
3972 d->state->brush = brush;
3973 d->checkEmulation();
3974 d->extended->brushChanged();
3978 d->state->brush = brush;
3979 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
3986 Sets the painter's brush to black color and the specified \a
3990 void QPainter::setBrush(Qt::BrushStyle style)
3994 qWarning("QPainter::setBrush: Painter not active");
3997 if (d->state->brush.style() == style &&
3998 (style == Qt::NoBrush
3999 || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
4001 d->state->brush = QBrush(Qt::black, style);
4003 d->extended->brushChanged();
4005 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4009 Returns the painter's current brush.
4011 \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
4014 const QBrush &QPainter::brush() const
4016 Q_D(const QPainter);
4018 qWarning("QPainter::brush: Painter not active");
4019 return d->fakeState()->brush;
4021 return d->state->brush;
4025 \fn void QPainter::setBackground(const QBrush &brush)
4027 Sets the background brush of the painter to the given \a brush.
4029 The background brush is the brush that is filled in when drawing
4030 opaque text, stippled lines and bitmaps. The background brush has
4031 no effect in transparent background mode (which is the default).
4033 \sa background(), setBackgroundMode(),
4034 {QPainter#Settings}{Settings}
4037 void QPainter::setBackground(const QBrush &bg)
4039 #ifdef QT_DEBUG_DRAW
4040 if (qt_show_painter_debug_output)
4041 printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4046 qWarning("QPainter::setBackground: Painter not active");
4049 d->state->bgBrush = bg;
4051 d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4055 Sets the painter's font to the given \a font.
4057 This font is used by subsequent drawText() functions. The text
4058 color is the same as the pen color.
4060 If you set a font that isn't available, Qt finds a close match.
4061 font() will return what you set using setFont() and fontInfo() returns the
4062 font actually being used (which may be the same).
4064 \sa font(), drawText(), {QPainter#Settings}{Settings}
4067 void QPainter::setFont(const QFont &font)
4071 #ifdef QT_DEBUG_DRAW
4072 if (qt_show_painter_debug_output)
4073 printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4077 qWarning("QPainter::setFont: Painter not active");
4081 d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4083 d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4087 Returns the currently set font used for drawing text.
4089 \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4091 const QFont &QPainter::font() const
4093 Q_D(const QPainter);
4095 qWarning("QPainter::font: Painter not active");
4096 return d->fakeState()->font;
4098 return d->state->font;
4104 Draws the given rectangle \a rect with rounded corners.
4106 The \a xRadius and \a yRadius arguments specify the radii
4107 of the ellipses defining the corners of the rounded rectangle.
4108 When \a mode is Qt::RelativeSize, \a xRadius and
4109 \a yRadius are specified in percentage of half the rectangle's
4110 width and height respectively, and should be in the range
4113 A filled rectangle has a size of rect.size(). A stroked rectangle
4114 has a size of rect.size() plus the pen width.
4118 \li \inlineimage qpainter-roundrect.png
4120 \snippet code/src_gui_painting_qpainter.cpp 8
4123 \sa drawRect(), QPen
4125 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4127 #ifdef QT_DEBUG_DRAW
4128 if (qt_show_painter_debug_output)
4129 printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4136 if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
4142 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4147 path.addRoundedRect(rect, xRadius, yRadius, mode);
4152 \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4153 Qt::SizeMode mode = Qt::AbsoluteSize);
4157 Draws the given rectangle \a rect with rounded corners.
4161 \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4162 Qt::SizeMode mode = Qt::AbsoluteSize);
4166 Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4172 Draws a rectangle \a r with rounded corners.
4174 The \a xRnd and \a yRnd arguments specify how rounded the corners
4175 should be. 0 is angled corners, 99 is maximum roundedness.
4177 A filled rectangle has a size of r.size(). A stroked rectangle
4178 has a size of r.size() plus the pen width.
4180 \sa drawRoundedRect()
4182 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4184 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4189 \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4194 Draws the rectangle \a r with rounded corners.
4200 \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4204 Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4208 \fn void QPainter::drawEllipse(const QRectF &rectangle)
4210 Draws the ellipse defined by the given \a rectangle.
4212 A filled ellipse has a size of \a{rectangle}.\l
4213 {QRect::size()}{size()}. A stroked ellipse has a size of
4214 \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4218 \li \inlineimage qpainter-ellipse.png
4220 \snippet code/src_gui_painting_qpainter.cpp 9
4223 \sa drawPie(), {Coordinate System}
4225 void QPainter::drawEllipse(const QRectF &r)
4227 #ifdef QT_DEBUG_DRAW
4228 if (qt_show_painter_debug_output)
4229 printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4236 QRectF rect(r.normalized());
4239 d->extended->drawEllipse(rect);
4243 d->updateState(d->state);
4244 if (d->state->emulationSpecifier) {
4245 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4246 && d->state->matrix.type() == QTransform::TxTranslate) {
4247 rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4250 path.addEllipse(rect);
4251 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4256 d->engine->drawEllipse(rect);
4260 \fn QPainter::drawEllipse(const QRect &rectangle)
4264 Draws the ellipse defined by the given \a rectangle.
4266 void QPainter::drawEllipse(const QRect &r)
4268 #ifdef QT_DEBUG_DRAW
4269 if (qt_show_painter_debug_output)
4270 printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4277 QRect rect(r.normalized());
4280 d->extended->drawEllipse(rect);
4284 d->updateState(d->state);
4286 if (d->state->emulationSpecifier) {
4287 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4288 && d->state->matrix.type() == QTransform::TxTranslate) {
4289 rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4292 path.addEllipse(rect);
4293 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4298 d->engine->drawEllipse(rect);
4302 \fn QPainter::drawEllipse(int x, int y, int width, int height)
4306 Draws the ellipse defined by the rectangle beginning at (\a{x},
4307 \a{y}) with the given \a width and \a height.
4313 \fn QPainter::drawEllipse(const QPointF ¢er, qreal rx, qreal ry)
4317 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4323 \fn QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)
4327 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4331 \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4333 Draws the arc defined by the given \a rectangle, \a startAngle and
4336 The \a startAngle and \a spanAngle must be specified in 1/16th of
4337 a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4338 values for the angles mean counter-clockwise while negative values
4339 mean the clockwise direction. Zero degrees is at the 3 o'clock
4344 \li \inlineimage qpainter-arc.png
4346 \snippet code/src_gui_painting_qpainter.cpp 10
4349 \sa drawPie(), drawChord(), {Coordinate System}
4352 void QPainter::drawArc(const QRectF &r, int a, int alen)
4354 #ifdef QT_DEBUG_DRAW
4355 if (qt_show_painter_debug_output)
4356 printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4357 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4364 QRectF rect = r.normalized();
4367 path.arcMoveTo(rect, a/16.0);
4368 path.arcTo(rect, a/16.0, alen/16.0);
4369 strokePath(path, d->state->pen);
4372 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4377 Draws the arc defined by the given \a rectangle, \a startAngle and
4382 \fn void QPainter::drawArc(int x, int y, int width, int height,
4383 int startAngle, int spanAngle)
4387 Draws the arc defined by the rectangle beginning at (\a x, \a y)
4388 with the specified \a width and \a height, and the given \a
4389 startAngle and \a spanAngle.
4393 \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4395 Draws a pie defined by the given \a rectangle, \a startAngle and \a spanAngle.
4397 The pie is filled with the current brush().
4399 The startAngle and spanAngle must be specified in 1/16th of a
4400 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4401 for the angles mean counter-clockwise while negative values mean
4402 the clockwise direction. Zero degrees is at the 3 o'clock
4407 \li \inlineimage qpainter-pie.png
4409 \snippet code/src_gui_painting_qpainter.cpp 11
4412 \sa drawEllipse(), drawChord(), {Coordinate System}
4414 void QPainter::drawPie(const QRectF &r, int a, int alen)
4416 #ifdef QT_DEBUG_DRAW
4417 if (qt_show_painter_debug_output)
4418 printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4419 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4430 if (a < 0) a += (360*16);
4433 QRectF rect = r.normalized();
4436 path.moveTo(rect.center());
4437 path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4438 path.closeSubpath();
4444 \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4447 Draws a pie defined by the given \a rectangle, \a startAngle and
4452 \fn void QPainter::drawPie(int x, int y, int width, int height, int
4453 startAngle, int spanAngle)
4457 Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4458 the specified \a width and \a height, and the given \a startAngle and
4463 \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4465 Draws the chord defined by the given \a rectangle, \a startAngle and
4466 \a spanAngle. The chord is filled with the current brush().
4468 The startAngle and spanAngle must be specified in 1/16th of a
4469 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4470 for the angles mean counter-clockwise while negative values mean
4471 the clockwise direction. Zero degrees is at the 3 o'clock
4476 \li \inlineimage qpainter-chord.png
4478 \snippet code/src_gui_painting_qpainter.cpp 12
4481 \sa drawArc(), drawPie(), {Coordinate System}
4483 void QPainter::drawChord(const QRectF &r, int a, int alen)
4485 #ifdef QT_DEBUG_DRAW
4486 if (qt_show_painter_debug_output)
4487 printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4488 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4495 QRectF rect = r.normalized();
4498 path.arcMoveTo(rect, a/16.0);
4499 path.arcTo(rect, a/16.0, alen/16.0);
4500 path.closeSubpath();
4504 \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4508 Draws the chord defined by the given \a rectangle, \a startAngle and
4513 \fn void QPainter::drawChord(int x, int y, int width, int height, int
4514 startAngle, int spanAngle)
4518 Draws the chord defined by the rectangle beginning at (\a x, \a y)
4519 with the specified \a width and \a height, and the given \a
4520 startAngle and \a spanAngle.
4525 Draws the first \a lineCount lines in the array \a lines
4526 using the current pen.
4528 \sa drawLine(), drawPolyline()
4530 void QPainter::drawLines(const QLineF *lines, int lineCount)
4532 #ifdef QT_DEBUG_DRAW
4533 if (qt_show_painter_debug_output)
4534 printf("QPainter::drawLines(), line count=%d\n", lineCount);
4539 if (!d->engine || lineCount < 1)
4543 d->extended->drawLines(lines, lineCount);
4547 d->updateState(d->state);
4549 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4551 if (lineEmulation) {
4552 if (lineEmulation == QPaintEngine::PrimitiveTransform
4553 && d->state->matrix.type() == QTransform::TxTranslate) {
4554 for (int i = 0; i < lineCount; ++i) {
4555 QLineF line = lines[i];
4556 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4557 d->engine->drawLines(&line, 1);
4560 QPainterPath linePath;
4561 for (int i = 0; i < lineCount; ++i) {
4562 linePath.moveTo(lines[i].p1());
4563 linePath.lineTo(lines[i].p2());
4565 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4569 d->engine->drawLines(lines, lineCount);
4573 \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4576 Draws the first \a lineCount lines in the array \a lines
4577 using the current pen.
4579 void QPainter::drawLines(const QLine *lines, int lineCount)
4581 #ifdef QT_DEBUG_DRAW
4582 if (qt_show_painter_debug_output)
4583 printf("QPainter::drawLine(), line count=%d\n", lineCount);
4588 if (!d->engine || lineCount < 1)
4592 d->extended->drawLines(lines, lineCount);
4596 d->updateState(d->state);
4598 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4600 if (lineEmulation) {
4601 if (lineEmulation == QPaintEngine::PrimitiveTransform
4602 && d->state->matrix.type() == QTransform::TxTranslate) {
4603 for (int i = 0; i < lineCount; ++i) {
4604 QLineF line = lines[i];
4605 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4606 d->engine->drawLines(&line, 1);
4609 QPainterPath linePath;
4610 for (int i = 0; i < lineCount; ++i) {
4611 linePath.moveTo(lines[i].p1());
4612 linePath.lineTo(lines[i].p2());
4614 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4618 d->engine->drawLines(lines, lineCount);
4624 Draws the first \a lineCount lines in the array \a pointPairs
4625 using the current pen. The lines are specified as pairs of points
4626 so the number of entries in \a pointPairs must be at least \a
4629 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4631 Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4633 drawLines((QLineF*)pointPairs, lineCount);
4639 Draws the first \a lineCount lines in the array \a pointPairs
4640 using the current pen.
4642 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4644 Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4646 drawLines((QLine*)pointPairs, lineCount);
4651 \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4654 Draws a line for each pair of points in the vector \a pointPairs
4655 using the current pen. If there is an odd number of points in the
4656 array, the last point will be ignored.
4660 \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4663 Draws a line for each pair of points in the vector \a pointPairs
4664 using the current pen.
4668 \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4671 Draws the set of lines defined by the list \a lines using the
4672 current pen and brush.
4676 \fn void QPainter::drawLines(const QVector<QLine> &lines)
4679 Draws the set of lines defined by the list \a lines using the
4680 current pen and brush.
4684 Draws the polyline defined by the first \a pointCount points in \a
4685 points using the current pen.
4687 Note that unlike the drawPolygon() function the last point is \e
4688 not connected to the first, neither is the polyline filled.
4693 \snippet code/src_gui_painting_qpainter.cpp 13
4696 \sa drawLines(), drawPolygon(), {Coordinate System}
4698 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4700 #ifdef QT_DEBUG_DRAW
4701 if (qt_show_painter_debug_output)
4702 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4706 if (!d->engine || pointCount < 2)
4710 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4714 d->updateState(d->state);
4716 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4718 if (lineEmulation) {
4720 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4721 // && d->state->matrix.type() == QTransform::TxTranslate) {
4723 QPainterPath polylinePath(points[0]);
4724 for (int i=1; i<pointCount; ++i)
4725 polylinePath.lineTo(points[i]);
4726 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4729 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4736 Draws the polyline defined by the first \a pointCount points in \a
4737 points using the current pen.
4739 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4741 #ifdef QT_DEBUG_DRAW
4742 if (qt_show_painter_debug_output)
4743 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4747 if (!d->engine || pointCount < 2)
4751 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4755 d->updateState(d->state);
4757 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4759 if (lineEmulation) {
4761 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4762 // && d->state->matrix.type() == QTransform::TxTranslate) {
4764 QPainterPath polylinePath(points[0]);
4765 for (int i=1; i<pointCount; ++i)
4766 polylinePath.lineTo(points[i]);
4767 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4770 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4775 \fn void QPainter::drawPolyline(const QPolygonF &points)
4779 Draws the polyline defined by the given \a points using the
4784 \fn void QPainter::drawPolyline(const QPolygon &points)
4788 Draws the polyline defined by the given \a points using the
4793 Draws the polygon defined by the first \a pointCount points in the
4794 array \a points using the current pen and brush.
4798 \li \inlineimage qpainter-polygon.png
4800 \snippet code/src_gui_painting_qpainter.cpp 14
4803 The first point is implicitly connected to the last point, and the
4804 polygon is filled with the current brush().
4806 If \a fillRule is Qt::WindingFill, the polygon is filled using the
4807 winding fill algorithm. If \a fillRule is Qt::OddEvenFill, the
4808 polygon is filled using the odd-even fill algorithm. See
4809 \l{Qt::FillRule} for a more detailed description of these fill
4812 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
4814 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
4816 #ifdef QT_DEBUG_DRAW
4817 if (qt_show_painter_debug_output)
4818 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4823 if (!d->engine || pointCount < 2)
4827 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4831 d->updateState(d->state);
4833 uint emulationSpecifier = d->state->emulationSpecifier;
4835 if (emulationSpecifier) {
4836 QPainterPath polygonPath(points[0]);
4837 for (int i=1; i<pointCount; ++i)
4838 polygonPath.lineTo(points[i]);
4839 polygonPath.closeSubpath();
4840 polygonPath.setFillRule(fillRule);
4841 d->draw_helper(polygonPath);
4845 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4850 Draws the polygon defined by the first \a pointCount points in the
4853 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
4855 #ifdef QT_DEBUG_DRAW
4856 if (qt_show_painter_debug_output)
4857 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4862 if (!d->engine || pointCount < 2)
4866 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4870 d->updateState(d->state);
4872 uint emulationSpecifier = d->state->emulationSpecifier;
4874 if (emulationSpecifier) {
4875 QPainterPath polygonPath(points[0]);
4876 for (int i=1; i<pointCount; ++i)
4877 polygonPath.lineTo(points[i]);
4878 polygonPath.closeSubpath();
4879 polygonPath.setFillRule(fillRule);
4880 d->draw_helper(polygonPath);
4884 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4887 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
4891 Draws the polygon defined by the given \a points using the fill
4895 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
4899 Draws the polygon defined by the given \a points using the fill
4904 \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4906 Draws the convex polygon defined by the first \a pointCount points
4907 in the array \a points using the current pen.
4911 \li \inlineimage qpainter-polygon.png
4913 \snippet code/src_gui_painting_qpainter.cpp 15
4916 The first point is implicitly connected to the last point, and the
4917 polygon is filled with the current brush(). If the supplied
4918 polygon is not convex, i.e. it contains at least one angle larger
4919 than 180 degrees, the results are undefined.
4921 On some platforms (e.g. X11), the drawConvexPolygon() function can
4922 be faster than the drawPolygon() function.
4924 \sa drawPolygon(), drawPolyline(), {Coordinate System}
4928 \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4931 Draws the convex polygon defined by the first \a pointCount points
4932 in the array \a points using the current pen.
4936 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
4940 Draws the convex polygon defined by \a polygon using the current
4945 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
4948 Draws the convex polygon defined by \a polygon using the current
4952 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4954 #ifdef QT_DEBUG_DRAW
4955 if (qt_show_painter_debug_output)
4956 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4961 if (!d->engine || pointCount < 2)
4965 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4969 d->updateState(d->state);
4971 uint emulationSpecifier = d->state->emulationSpecifier;
4973 if (emulationSpecifier) {
4974 QPainterPath polygonPath(points[0]);
4975 for (int i=1; i<pointCount; ++i)
4976 polygonPath.lineTo(points[i]);
4977 polygonPath.closeSubpath();
4978 polygonPath.setFillRule(Qt::WindingFill);
4979 d->draw_helper(polygonPath);
4983 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4986 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4988 #ifdef QT_DEBUG_DRAW
4989 if (qt_show_painter_debug_output)
4990 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4995 if (!d->engine || pointCount < 2)
4999 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5003 d->updateState(d->state);
5005 uint emulationSpecifier = d->state->emulationSpecifier;
5007 if (emulationSpecifier) {
5008 QPainterPath polygonPath(points[0]);
5009 for (int i=1; i<pointCount; ++i)
5010 polygonPath.lineTo(points[i]);
5011 polygonPath.closeSubpath();
5012 polygonPath.setFillRule(Qt::WindingFill);
5013 d->draw_helper(polygonPath);
5017 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5020 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5022 return m.inverted().map(QPointF(m.map(p).toPoint()));
5026 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5028 Draws the rectangular portion \a source of the given \a pixmap
5029 into the given \a target in the paint device.
5031 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5036 \snippet code/src_gui_painting_qpainter.cpp 16
5039 If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5040 using the pens color. If backgroundMode is Qt::OpaqueMode, the
5041 "unset" bits are drawn using the color of the background brush; if
5042 backgroundMode is Qt::TransparentMode, the "unset" bits are
5043 transparent. Drawing bitmaps with gradient or texture colors is
5048 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5050 #if defined QT_DEBUG_DRAW
5051 if (qt_show_painter_debug_output)
5052 printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5054 pm.width(), pm.height());
5059 if (!d->engine || pm.isNull())
5063 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5067 d->extended->drawPixmap(p, pm);
5075 int h = pm.height();
5080 // Emulate opaque background for bitmaps
5081 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5082 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5085 d->updateState(d->state);
5087 if ((d->state->matrix.type() > QTransform::TxTranslate
5088 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5089 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5090 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5093 // If there is no rotation involved we have to make sure we use the
5094 // antialiased and not the aliased coordinate system by rounding the coordinates.
5095 if (d->state->matrix.type() <= QTransform::TxScale) {
5096 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5101 setBackgroundMode(Qt::TransparentMode);
5102 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5103 QBrush brush(d->state->pen.color(), pm);
5106 setBrushOrigin(QPointF(0, 0));
5108 drawRect(pm.rect());
5111 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5112 x += d->state->matrix.dx();
5113 y += d->state->matrix.dy();
5115 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5119 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5121 #if defined QT_DEBUG_DRAW
5122 if (qt_show_painter_debug_output)
5123 printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5124 r.x(), r.y(), r.width(), r.height(),
5125 pm.width(), pm.height(),
5126 sr.x(), sr.y(), sr.width(), sr.height());
5130 if (!d->engine || pm.isNull())
5133 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5138 qreal w = r.width();
5139 qreal h = r.height();
5142 qreal sw = sr.width();
5143 qreal sh = sr.height();
5145 // Sanity-check clipping
5147 sw = pm.width() - sx;
5150 sh = pm.height() - sy;
5158 qreal w_ratio = sx * w/sw;
5166 qreal h_ratio = sy * h/sh;
5173 if (sw + sx > pm.width()) {
5174 qreal delta = sw - (pm.width() - sx);
5175 qreal w_ratio = delta * w/sw;
5180 if (sh + sy > pm.height()) {
5181 qreal delta = sh - (pm.height() - sy);
5182 qreal h_ratio = delta * h/sh;
5187 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5191 d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5195 // Emulate opaque background for bitmaps
5196 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5197 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5199 d->updateState(d->state);
5201 if ((d->state->matrix.type() > QTransform::TxTranslate
5202 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5203 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5204 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5205 || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5208 // If there is no rotation involved we have to make sure we use the
5209 // antialiased and not the aliased coordinate system by rounding the coordinates.
5210 if (d->state->matrix.type() <= QTransform::TxScale) {
5211 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5216 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5224 scale(w / sw, h / sh);
5225 setBackgroundMode(Qt::TransparentMode);
5226 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5229 if (sw == pm.width() && sh == pm.height())
5230 brush = QBrush(d->state->pen.color(), pm);
5232 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5237 drawRect(QRectF(0, 0, sw, sh));
5240 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5241 x += d->state->matrix.dx();
5242 y += d->state->matrix.dy();
5244 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5250 \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5251 const QRect &source)
5254 Draws the rectangular portion \a source of the given \a pixmap
5255 into the given \a target in the paint device.
5257 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5261 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5262 const QRectF &source)
5265 Draws the rectangular portion \a source of the given \a pixmap
5266 with its origin at the given \a point.
5270 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5271 const QRect &source)
5275 Draws the rectangular portion \a source of the given \a pixmap
5276 with its origin at the given \a point.
5280 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5283 Draws the given \a pixmap with its origin at the given \a point.
5287 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5290 Draws the given \a pixmap with its origin at the given \a point.
5294 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5298 Draws the given \a pixmap at position (\a{x}, \a{y}).
5302 \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5305 Draws the given \a pixmap into the given \a rectangle.
5307 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5311 \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5312 const QPixmap &pixmap)
5316 Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5317 with the given \a width and \a height.
5321 \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5322 int sx, int sy, int sw, int sh)
5326 Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5327 width \a sw and height \a sh, of the given \a pixmap , at the
5328 point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5329 If sw or sh are equal to zero the width/height of the pixmap
5330 is used and adjusted by the offset sx/sy;
5334 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5335 int sx, int sy, int sw, int sh)
5339 Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5340 pixmap into the paint device.
5342 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5343 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5344 pixmap that is to be drawn. The default is (0, 0).
5346 (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5347 The default, (0, 0) (and negative) means all the way to the
5348 bottom-right of the pixmap.
5351 void QPainter::drawImage(const QPointF &p, const QImage &image)
5355 if (!d->engine || image.isNull())
5359 d->extended->drawImage(p, image);
5366 int w = image.width();
5367 int h = image.height();
5369 d->updateState(d->state);
5371 if (((d->state->matrix.type() > QTransform::TxTranslate)
5372 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5373 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5374 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5377 // If there is no rotation involved we have to make sure we use the
5378 // antialiased and not the aliased coordinate system by rounding the coordinates.
5379 if (d->state->matrix.type() <= QTransform::TxScale) {
5380 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5385 setBackgroundMode(Qt::TransparentMode);
5386 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5387 QBrush brush(image);
5390 setBrushOrigin(QPointF(0, 0));
5392 drawRect(image.rect());
5397 if (d->state->matrix.type() == QTransform::TxTranslate
5398 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5399 x += d->state->matrix.dx();
5400 y += d->state->matrix.dy();
5403 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5406 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5407 Qt::ImageConversionFlags flags)
5411 if (!d->engine || image.isNull())
5414 qreal x = targetRect.x();
5415 qreal y = targetRect.y();
5416 qreal w = targetRect.width();
5417 qreal h = targetRect.height();
5418 qreal sx = sourceRect.x();
5419 qreal sy = sourceRect.y();
5420 qreal sw = sourceRect.width();
5421 qreal sh = sourceRect.height();
5423 // Sanity-check clipping
5425 sw = image.width() - sx;
5428 sh = image.height() - sy;
5436 qreal w_ratio = sx * w/sw;
5444 qreal h_ratio = sy * h/sh;
5451 if (sw + sx > image.width()) {
5452 qreal delta = sw - (image.width() - sx);
5453 qreal w_ratio = delta * w/sw;
5458 if (sh + sy > image.height()) {
5459 qreal delta = sh - (image.height() - sy);
5460 qreal h_ratio = delta * h/sh;
5465 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5469 d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5473 d->updateState(d->state);
5475 if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5476 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5477 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5478 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5481 // If there is no rotation involved we have to make sure we use the
5482 // antialiased and not the aliased coordinate system by rounding the coordinates.
5483 if (d->state->matrix.type() <= QTransform::TxScale) {
5484 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5489 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5496 scale(w / sw, h / sh);
5497 setBackgroundMode(Qt::TransparentMode);
5498 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5499 QBrush brush(image);
5502 setBrushOrigin(QPointF(-sx, -sy));
5504 drawRect(QRectF(0, 0, sw, sh));
5509 if (d->state->matrix.type() == QTransform::TxTranslate
5510 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5511 x += d->state->matrix.dx();
5512 y += d->state->matrix.dy();
5515 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5519 \fn void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphs)
5521 Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5522 edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5523 selected on \a glyphs and at offsets given by the positions in \a glyphs.
5527 \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes()
5529 #if !defined(QT_NO_RAWFONT)
5530 void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
5534 QRawFont font = glyphRun.rawFont();
5535 if (!font.isValid())
5538 QGlyphRunPrivate *glyphRun_d = QGlyphRunPrivate::get(glyphRun);
5540 const quint32 *glyphIndexes = glyphRun_d->glyphIndexData;
5541 const QPointF *glyphPositions = glyphRun_d->glyphPositionData;
5543 int count = qMin(glyphRun_d->glyphIndexDataSize, glyphRun_d->glyphPositionDataSize);
5544 QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5546 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5547 bool supportsTransformations = d->extended
5548 ? d->extended->supportsTransformations(fontD->fontEngine, d->state->matrix)
5549 : d->engine->type() == QPaintEngine::CoreGraphics || d->state->matrix.isAffine();
5551 for (int i=0; i<count; ++i) {
5552 QPointF processedPosition = position + glyphPositions[i];
5553 if (!supportsTransformations)
5554 processedPosition = d->state->transform().map(processedPosition);
5555 fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5558 d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, font, glyphRun.overline(),
5559 glyphRun.underline(), glyphRun.strikeOut());
5562 void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions,
5564 const QRawFont &font, bool overline, bool underline,
5571 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5572 QFontEngine *fontEngine = fontD->fontEngine;
5577 for (int i=0; i<glyphCount; ++i) {
5578 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5579 if (i == 0 || leftMost > positions[i].x)
5580 leftMost = positions[i].x;
5582 // We don't support glyphs that do not share a common baseline. If this turns out to
5583 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5584 // and do a drawTextItemDecorations call per cluster.
5585 if (i == 0 || baseLine < positions[i].y)
5586 baseLine = positions[i].y;
5588 // We use the advance rather than the actual bounds to match the algorithm in drawText()
5589 if (i == 0 || rightMost < positions[i].x + gm.xoff)
5590 rightMost = positions[i].x + gm.xoff;
5593 QFixed width = rightMost - leftMost;
5595 if (extended != 0 && state->matrix.isAffine()) {
5596 QStaticTextItem staticTextItem;
5597 staticTextItem.color = state->pen.color();
5598 staticTextItem.font = state->font;
5599 staticTextItem.setFontEngine(fontEngine);
5600 staticTextItem.numGlyphs = glyphCount;
5601 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5602 staticTextItem.glyphPositions = positions;
5604 extended->drawStaticTextItem(&staticTextItem);
5606 QTextItemInt textItem;
5607 textItem.fontEngine = fontEngine;
5609 QVarLengthArray<QFixed, 128> advances(glyphCount);
5610 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5611 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5612 memset(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5613 memset(advances.data(), 0, advances.size() * sizeof(QFixed));
5614 memset(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5616 textItem.glyphs.numGlyphs = glyphCount;
5617 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5618 textItem.glyphs.offsets = positions;
5619 textItem.glyphs.advances_x = advances.data();
5620 textItem.glyphs.advances_y = advances.data();
5621 textItem.glyphs.justifications = glyphJustifications.data();
5622 textItem.glyphs.attributes = glyphAttributes.data();
5624 engine->drawTextItem(QPointF(0, 0), textItem);
5627 QTextItemInt::RenderFlags flags;
5629 flags |= QTextItemInt::Underline;
5631 flags |= QTextItemInt::Overline;
5633 flags |= QTextItemInt::StrikeOut;
5635 drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5639 ? QTextCharFormat::SingleUnderline
5640 : QTextCharFormat::NoUnderline),
5641 flags, width.toReal(), QTextCharFormat());
5643 #endif // QT_NO_RAWFONT
5647 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5651 Draws the \a staticText at the \a topLeftPosition.
5653 \note The y-position is used as the top of the font.
5658 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5662 Draws the \a staticText at coordinates \a left and \a top.
5664 \note The y-position is used as the top of the font.
5668 \fn void QPainter::drawText(const QPointF &position, const QString &text)
5670 Draws the given \a text with the currently defined text direction,
5671 beginning at the given \a position.
5673 This function does not handle the newline character (\\n), as it cannot
5674 break text into multiple lines, and it cannot display the newline character.
5675 Use the QPainter::drawText() overload that takes a rectangle instead
5676 if you want to draw multiple lines of text with the newline character, or
5677 if you want the text to be wrapped.
5679 By default, QPainter draws text anti-aliased.
5681 \note The y-position is used as the baseline of the font.
5683 \sa setFont(), setPen()
5686 void QPainter::drawText(const QPointF &p, const QString &str)
5688 drawText(p, str, 0, 0);
5694 Draws the given \a staticText at the given \a topLeftPosition.
5696 The text will be drawn using the font and the transformation set on the painter. If the
5697 font and/or transformation set on the painter are different from the ones used to initialize
5698 the layout of the QStaticText, then the layout will have to be recalculated. Use
5699 QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5700 it will later be drawn.
5702 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5703 last drawn, then there will be a slight overhead when translating the text to its new position.
5705 \note If the painter's transformation is not affine, then \a staticText will be drawn using
5706 regular calls to drawText(), losing any potential for performance improvement.
5708 \note The y-position is used as the top of the font.
5712 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5715 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5718 QStaticTextPrivate *staticText_d =
5719 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5721 if (font() != staticText_d->font) {
5722 staticText_d->font = font();
5723 staticText_d->needsRelayout = true;
5726 // If we don't have an extended paint engine, or if the painter is projected,
5727 // we go through standard code path
5728 if (d->extended == 0 || !d->state->matrix.isAffine()) {
5729 staticText_d->paintText(topLeftPosition, this);
5733 QFontEngine *fe = staticText_d->font.d->engineForScript(QUnicodeTables::Common);
5734 if (fe->type() == QFontEngine::Multi)
5735 fe = static_cast<QFontEngineMulti *>(fe)->engine(0);
5736 bool supportsTransformations = d->extended->supportsTransformations(fe,
5738 if (supportsTransformations && !staticText_d->untransformedCoordinates) {
5739 staticText_d->untransformedCoordinates = true;
5740 staticText_d->needsRelayout = true;
5741 } else if (!supportsTransformations && staticText_d->untransformedCoordinates) {
5742 staticText_d->untransformedCoordinates = false;
5743 staticText_d->needsRelayout = true;
5746 // Don't recalculate entire layout because of translation, rather add the dx and dy
5747 // into the position to move each text item the correct distance.
5748 QPointF transformedPosition = topLeftPosition;
5749 if (!staticText_d->untransformedCoordinates)
5750 transformedPosition = transformedPosition * d->state->matrix;
5751 QTransform oldMatrix;
5753 // The translation has been applied to transformedPosition. Remove translation
5754 // component from matrix.
5755 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
5756 qreal m11 = d->state->matrix.m11();
5757 qreal m12 = d->state->matrix.m12();
5758 qreal m13 = d->state->matrix.m13();
5759 qreal m21 = d->state->matrix.m21();
5760 qreal m22 = d->state->matrix.m22();
5761 qreal m23 = d->state->matrix.m23();
5762 qreal m33 = d->state->matrix.m33();
5764 oldMatrix = d->state->matrix;
5765 d->state->matrix.setMatrix(m11, m12, m13,
5770 // If the transform is not identical to the text transform,
5771 // we have to relayout the text (for other transformations than plain translation)
5772 bool staticTextNeedsReinit = staticText_d->needsRelayout;
5773 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
5774 staticText_d->matrix = d->state->matrix;
5775 staticTextNeedsReinit = true;
5778 // Recreate the layout of the static text because the matrix or font has changed
5779 if (staticTextNeedsReinit)
5780 staticText_d->init();
5782 if (transformedPosition != staticText_d->position) { // Translate to actual position
5783 QFixed fx = QFixed::fromReal(transformedPosition.x());
5784 QFixed fy = QFixed::fromReal(transformedPosition.y());
5785 QFixed oldX = QFixed::fromReal(staticText_d->position.x());
5786 QFixed oldY = QFixed::fromReal(staticText_d->position.y());
5787 for (int item=0; item<staticText_d->itemCount;++item) {
5788 QStaticTextItem *textItem = staticText_d->items + item;
5789 for (int i=0; i<textItem->numGlyphs; ++i) {
5790 textItem->glyphPositions[i].x += fx - oldX;
5791 textItem->glyphPositions[i].y += fy - oldY;
5793 textItem->userDataNeedsUpdate = true;
5796 staticText_d->position = transformedPosition;
5799 QPen oldPen = d->state->pen;
5800 QColor currentColor = oldPen.color();
5801 for (int i=0; i<staticText_d->itemCount; ++i) {
5802 QStaticTextItem *item = staticText_d->items + i;
5803 if (item->color.isValid() && currentColor != item->color) {
5804 setPen(item->color);
5805 currentColor = item->color;
5807 d->extended->drawStaticTextItem(item);
5809 qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
5810 item->numGlyphs, item->fontEngine(), staticText_d->font,
5813 if (currentColor != oldPen.color())
5816 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
5817 d->state->matrix = oldMatrix;
5823 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
5825 #ifdef QT_DEBUG_DRAW
5826 if (qt_show_painter_debug_output)
5827 printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
5832 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
5835 if (tf & Qt::TextBypassShaping) {
5836 // Skip harfbuzz complex shaping, shape using glyph advances only
5837 int len = str.length();
5838 int numGlyphs = len;
5839 QVarLengthGlyphLayoutArray glyphs(len);
5840 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
5841 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
5842 glyphs.resize(numGlyphs);
5843 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
5844 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
5847 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
5848 drawTextItem(p, gf);
5852 QStackTextEngine engine(str, d->state->font);
5853 engine.option.setTextDirection(d->state->layoutDirection);
5854 if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
5855 engine.ignoreBidi = true;
5856 engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
5860 line.length = str.length();
5861 engine.shapeLine(line);
5863 int nItems = engine.layoutData->items.size();
5864 QVarLengthArray<int> visualOrder(nItems);
5865 QVarLengthArray<uchar> levels(nItems);
5866 for (int i = 0; i < nItems; ++i)
5867 levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
5868 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
5870 if (justificationPadding > 0) {
5871 engine.option.setAlignment(Qt::AlignJustify);
5872 engine.forceJustification = true;
5873 // this works because justify() is only interested in the difference between width and textWidth
5874 line.width = justificationPadding;
5875 engine.justify(line);
5877 QFixed x = QFixed::fromReal(p.x());
5879 for (int i = 0; i < nItems; ++i) {
5880 int item = visualOrder[i];
5881 const QScriptItem &si = engine.layoutData->items.at(item);
5882 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
5886 QFont f = engine.font(si);
5887 QTextItemInt gf(si, &f);
5888 gf.glyphs = engine.shapedGlyphs(&si);
5889 gf.chars = engine.layoutData->string.unicode() + si.position;
5890 gf.num_chars = engine.length(item);
5891 if (engine.forceJustification) {
5892 for (int j=0; j<gf.glyphs.numGlyphs; ++j)
5893 gf.width += gf.glyphs.effectiveAdvance(j);
5895 gf.width = si.width;
5897 gf.logClusters = engine.logClusters(&si);
5899 drawTextItem(QPointF(x.toReal(), p.y()), gf);
5905 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
5907 #ifdef QT_DEBUG_DRAW
5908 if (qt_show_painter_debug_output)
5909 printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
5910 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5915 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5919 d->updateState(d->state);
5922 qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
5924 *br = bounds.toAlignedRect();
5928 \fn void QPainter::drawText(const QPoint &position, const QString &text)
5932 Draws the given \a text with the currently defined text direction,
5933 beginning at the given \a position.
5935 By default, QPainter draws text anti-aliased.
5937 \note The y-position is used as the baseline of the font.
5939 \sa setFont(), setPen()
5943 \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
5946 Draws the given \a text within the provided \a rectangle.
5947 The \a rectangle along with alignment \a flags defines the anchors for the \a text.
5951 \li \inlineimage qpainter-text.png
5953 \snippet code/src_gui_painting_qpainter.cpp 17
5956 The \a boundingRect (if not null) is set to the what the bounding rectangle
5957 should be in order to enclose the whole text. The \a flags argument is a bitwise
5958 OR of the following flags:
5963 \li Qt::AlignHCenter
5964 \li Qt::AlignJustify
5967 \li Qt::AlignVCenter
5969 \li Qt::TextDontClip
5970 \li Qt::TextSingleLine
5971 \li Qt::TextExpandTabs
5972 \li Qt::TextShowMnemonic
5973 \li Qt::TextWordWrap
5974 \li Qt::TextIncludeTrailingSpaces
5977 \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
5979 By default, QPainter draws text anti-aliased.
5981 \note The y-coordinate of \a rectangle is used as the top of the font.
5983 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
5985 #ifdef QT_DEBUG_DRAW
5986 if (qt_show_painter_debug_output)
5987 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
5988 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5993 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5997 d->updateState(d->state);
5999 qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
6003 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
6006 Draws the given \a text within the provided \a rectangle according
6007 to the specified \a flags. The \a boundingRect (if not null) is set to
6008 the what the bounding rectangle should be in order to enclose the whole text.
6010 By default, QPainter draws text anti-aliased.
6012 \note The y-coordinate of \a rectangle is used as the top of the font.
6014 \sa setFont(), setPen()
6018 \fn void QPainter::drawText(int x, int y, const QString &text)
6022 Draws the given \a text at position (\a{x}, \a{y}), using the painter's
6023 currently defined text direction.
6025 By default, QPainter draws text anti-aliased.
6027 \note The y-position is used as the baseline of the font.
6029 \sa setFont(), setPen()
6033 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6034 const QString &text, QRect *boundingRect)
6038 Draws the given \a text within the rectangle with origin (\a{x},
6039 \a{y}), \a width and \a height.
6041 The \a boundingRect (if not null) is set to the actual bounding
6042 rectangle of the output. The \a flags argument is a bitwise OR of
6043 the following flags:
6048 \li Qt::AlignHCenter
6049 \li Qt::AlignJustify
6052 \li Qt::AlignVCenter
6054 \li Qt::TextSingleLine
6055 \li Qt::TextExpandTabs
6056 \li Qt::TextShowMnemonic
6057 \li Qt::TextWordWrap
6060 By default, QPainter draws text anti-aliased.
6062 \note The y-position is used as the top of the font.
6064 \sa Qt::AlignmentFlag, Qt::TextFlag, setFont(), setPen()
6068 \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6069 const QTextOption &option)
6072 Draws the given \a text in the \a rectangle specified using the \a option
6073 to control its positioning and orientation.
6075 By default, QPainter draws text anti-aliased.
6077 \note The y-coordinate of \a rectangle is used as the top of the font.
6079 \sa setFont(), setPen()
6081 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6083 #ifdef QT_DEBUG_DRAW
6084 if (qt_show_painter_debug_output)
6085 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6086 r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6091 if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6095 d->updateState(d->state);
6097 qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6101 \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6108 \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6113 Draws the text item \a ti at position \a p.
6117 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6122 Draws the text item \a ti at position \a p.
6124 This method ignores the painters background mode and
6125 color. drawText and qt_format_text have to do it themselves, as
6126 only they know the extents of the complete string.
6128 It ignores the font set on the painter as the text item has one of its own.
6130 The underline and strikeout parameters of the text items font are
6131 ignored aswell. You'll need to pass in the correct flags to get
6132 underlining and strikeout.
6135 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6137 const qreal radiusBase = qMax(qreal(1), maxRadius);
6139 QString key = QLatin1String("WaveUnderline-")
6140 % pen.color().name()
6141 % HexString<qreal>(radiusBase);
6144 if (QPixmapCache::find(key, pixmap))
6147 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6148 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6149 const int radius = qFloor(radiusBase);
6156 while (xs < width) {
6159 path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6162 pixmap = QPixmap(width, radius * 2);
6163 pixmap.fill(Qt::transparent);
6166 wavePen.setCapStyle(Qt::SquareCap);
6168 // This is to protect against making the line too fat, as happens on Mac OS X
6169 // due to it having a rather thick width for the regular underline.
6170 const qreal maxPenWidth = .8 * radius;
6171 if (wavePen.widthF() > maxPenWidth)
6172 wavePen.setWidth(maxPenWidth);
6174 QPainter imgPainter(&pixmap);
6175 imgPainter.setPen(wavePen);
6176 imgPainter.setRenderHint(QPainter::Antialiasing);
6177 imgPainter.translate(0, radius);
6178 imgPainter.drawPath(path);
6181 QPixmapCache::insert(key, pixmap);
6186 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
6187 QTextCharFormat::UnderlineStyle underlineStyle,
6188 QTextItem::RenderFlags flags, qreal width,
6189 const QTextCharFormat &charFormat)
6191 if (underlineStyle == QTextCharFormat::NoUnderline
6192 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6195 const QPen oldPen = painter->pen();
6196 const QBrush oldBrush = painter->brush();
6197 painter->setBrush(Qt::NoBrush);
6199 pen.setStyle(Qt::SolidLine);
6200 pen.setWidthF(fe->lineThickness().toReal());
6201 pen.setCapStyle(Qt::FlatCap);
6203 QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6205 const qreal underlineOffset = fe->underlinePosition().toReal();
6206 // deliberately ceil the offset to avoid the underline coming too close to
6207 // the text above it.
6208 const qreal underlinePos = pos.y() + qCeil(underlineOffset);
6210 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6211 QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
6213 underlineStyle = QTextCharFormat::UnderlineStyle(theme->themeHint(QPlatformTheme::SpellCheckUnderlineStyle).toInt());
6216 if (underlineStyle == QTextCharFormat::WaveUnderline) {
6218 painter->translate(0, pos.y() + 1);
6220 QColor uc = charFormat.underlineColor();
6224 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6225 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6226 const int descent = (int) fe->descent().toReal();
6228 painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6229 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6231 } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6232 QColor uc = charFormat.underlineColor();
6236 pen.setStyle((Qt::PenStyle)(underlineStyle));
6237 painter->setPen(pen);
6238 QLineF underline(line.x1(), underlinePos, line.x2(), underlinePos);
6240 textEngine->addUnderline(painter, underline);
6242 painter->drawLine(underline);
6245 pen.setStyle(Qt::SolidLine);
6246 pen.setColor(oldPen.color());
6248 if (flags & QTextItem::StrikeOut) {
6249 QLineF strikeOutLine = line;
6250 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6251 painter->setPen(pen);
6253 textEngine->addStrikeOut(painter, strikeOutLine);
6255 painter->drawLine(strikeOutLine);
6258 if (flags & QTextItem::Overline) {
6259 QLineF overline = line;
6260 overline.translate(0., - fe->ascent().toReal());
6261 painter->setPen(pen);
6263 textEngine->addOverline(painter, overline);
6265 painter->drawLine(overline);
6268 painter->setPen(oldPen);
6269 painter->setBrush(oldBrush);
6272 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6273 const QFixedPoint *positions, int glyphCount,
6274 QFontEngine *fontEngine, const QFont &font,
6275 const QTextCharFormat &charFormat)
6277 if (!(font.underline() || font.strikeOut() || font.overline()))
6283 for (int i=0; i<glyphCount; ++i) {
6284 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6285 if (i == 0 || leftMost > positions[i].x)
6286 leftMost = positions[i].x;
6288 // We don't support glyphs that do not share a common baseline. If this turns out to
6289 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6290 // and do a drawTextItemDecoration call per cluster.
6291 if (i == 0 || baseLine < positions[i].y)
6292 baseLine = positions[i].y;
6294 // We use the advance rather than the actual bounds to match the algorithm in drawText()
6295 if (i == 0 || rightMost < positions[i].x + gm.xoff)
6296 rightMost = positions[i].x + gm.xoff;
6299 QFixed width = rightMost - leftMost;
6300 QTextItem::RenderFlags flags = 0;
6302 if (font.underline())
6303 flags |= QTextItem::Underline;
6304 if (font.overline())
6305 flags |= QTextItem::Overline;
6306 if (font.strikeOut())
6307 flags |= QTextItem::StrikeOut;
6309 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6312 font.underline() ? QTextCharFormat::SingleUnderline
6313 : QTextCharFormat::NoUnderline, flags,
6314 width.toReal(), charFormat);
6317 void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6321 d->drawTextItem(p, ti, static_cast<QTextEngine *>(0));
6324 void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine)
6326 #ifdef QT_DEBUG_DRAW
6327 if (qt_show_painter_debug_output)
6328 printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6329 p.x(), p.y(), qPrintable(_ti.text()));
6338 qt_painter_thread_test(device->devType(),
6340 QFontDatabase::supportsThreadedFontRendering());
6343 QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6345 if (!extended && state->bgMode == Qt::OpaqueMode) {
6346 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6347 q->fillRect(rect, state->bgBrush);
6350 if (q->pen().style() == Qt::NoPen)
6353 const QPainter::RenderHints oldRenderHints = state->renderHints;
6354 if (!state->renderHints & QPainter::Antialiasing && state->matrix.type() >= QTransform::TxScale) {
6355 // draw antialias decoration (underline/overline/strikeout) with
6359 const QTransform &m = state->matrix;
6360 if (state->matrix.type() < QTransform::TxShear) {
6361 bool isPlain90DegreeRotation =
6362 (qFuzzyIsNull(m.m11())
6363 && qFuzzyIsNull(m.m12() - qreal(1))
6364 && qFuzzyIsNull(m.m21() + qreal(1))
6365 && qFuzzyIsNull(m.m22())
6368 (qFuzzyIsNull(m.m11() + qreal(1))
6369 && qFuzzyIsNull(m.m12())
6370 && qFuzzyIsNull(m.m21())
6371 && qFuzzyIsNull(m.m22() + qreal(1))
6374 (qFuzzyIsNull(m.m11())
6375 && qFuzzyIsNull(m.m12() + qreal(1))
6376 && qFuzzyIsNull(m.m21() - qreal(1))
6377 && qFuzzyIsNull(m.m22())
6380 aa = !isPlain90DegreeRotation;
6383 q->setRenderHint(QPainter::Antialiasing, true);
6389 if (!ti.glyphs.numGlyphs) {
6391 } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6392 QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6394 const QGlyphLayout &glyphs = ti.glyphs;
6395 int which = glyphs.glyphs[0] >> 24;
6400 bool rtl = ti.flags & QTextItem::RightToLeft;
6402 x += ti.width.toReal();
6406 for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6407 const int e = glyphs.glyphs[end] >> 24;
6412 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6414 // set the high byte to zero and calc the width
6415 for (i = start; i < end; ++i) {
6416 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6417 ti2.width += ti.glyphs.effectiveAdvance(i);
6421 x -= ti2.width.toReal();
6423 engine->drawTextItem(QPointF(x, y), ti2);
6426 x += ti2.width.toReal();
6428 // reset the high byte for all glyphs and advance to the next sub-string
6429 const int hi = which << 24;
6430 for (i = start; i < end; ++i) {
6431 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6439 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6441 // set the high byte to zero and calc the width
6442 for (i = start; i < end; ++i) {
6443 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6444 ti2.width += ti.glyphs.effectiveAdvance(i);
6448 x -= ti2.width.toReal();
6451 extended->drawTextItem(QPointF(x, y), ti2);
6453 engine->drawTextItem(QPointF(x,y), ti2);
6455 // reset the high byte for all glyphs
6456 const int hi = which << 24;
6457 for (i = start; i < end; ++i)
6458 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6462 extended->drawTextItem(p, ti);
6464 engine->drawTextItem(p, ti);
6466 drawTextItemDecoration(q, p, ti.fontEngine, textEngine, ti.underlineStyle,
6467 ti.flags, ti.width.toReal(), ti.charFormat);
6469 if (state->renderHints != oldRenderHints) {
6470 state->renderHints = oldRenderHints;
6472 extended->renderHintsChanged();
6474 state->dirtyFlags |= QPaintEngine::DirtyHints;
6479 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6481 Returns the bounding rectangle of the \a text as it will appear
6482 when drawn inside the given \a rectangle with the specified \a
6483 flags using the currently set font(); i.e the function tells you
6484 where the drawText() function will draw when given the same
6487 If the \a text does not fit within the given \a rectangle using
6488 the specified \a flags, the function returns the required
6491 The \a flags argument is a bitwise OR of the following flags:
6495 \li Qt::AlignHCenter
6498 \li Qt::AlignVCenter
6500 \li Qt::TextSingleLine
6501 \li Qt::TextExpandTabs
6502 \li Qt::TextShowMnemonic
6503 \li Qt::TextWordWrap
6504 \li Qt::TextIncludeTrailingSpaces
6506 If several of the horizontal or several of the vertical alignment
6507 flags are set, the resulting alignment is undefined.
6509 \sa drawText(), Qt::Alignment, Qt::TextFlag
6513 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6514 const QString &text)
6518 Returns the bounding rectangle of the \a text as it will appear
6519 when drawn inside the given \a rectangle with the specified \a
6520 flags using the currently set font().
6524 \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6525 const QString &text);
6529 Returns the bounding rectangle of the given \a text as it will
6530 appear when drawn inside the rectangle beginning at the point
6531 (\a{x}, \a{y}) with width \a w and height \a h.
6533 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6536 return QRect(rect.x(),rect.y(), 0,0);
6538 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6544 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6547 return QRectF(rect.x(),rect.y(), 0,0);
6549 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6554 \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6555 const QString &text, const QTextOption &option)
6559 Instead of specifying flags as a bitwise OR of the
6560 Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6561 an \a option argument. The QTextOption class provides a
6562 description of general rich text properties.
6566 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6570 if (!d->engine || text.length() == 0)
6571 return QRectF(r.x(),r.y(), 0,0);
6574 qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6579 \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6581 Draws a tiled \a pixmap, inside the given \a rectangle with its
6582 origin at the given \a position.
6584 Calling drawTiledPixmap() is similar to calling drawPixmap()
6585 several times to fill (tile) an area with a pixmap, but is
6586 potentially much more efficient depending on the underlying window
6591 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6593 #ifdef QT_DEBUG_DRAW
6594 if (qt_show_painter_debug_output)
6595 printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6596 r.x(), r.y(), r.width(), r.height(),
6597 pixmap.width(), pixmap.height(),
6602 if (!d->engine || pixmap.isNull() || r.isEmpty())
6606 qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6609 qreal sw = pixmap.width();
6610 qreal sh = pixmap.height();
6614 sx = qRound(sw) - qRound(-sx) % qRound(sw);
6616 sx = qRound(sx) % qRound(sw);
6618 sy = qRound(sh) - -qRound(sy) % qRound(sh);
6620 sy = qRound(sy) % qRound(sh);
6624 d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6628 if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6629 fillRect(r, d->state->bgBrush);
6631 d->updateState(d->state);
6632 if ((d->state->matrix.type() > QTransform::TxTranslate
6633 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6634 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6637 setBackgroundMode(Qt::TransparentMode);
6638 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6639 setBrush(QBrush(d->state->pen.color(), pixmap));
6642 // If there is no rotation involved we have to make sure we use the
6643 // antialiased and not the aliased coordinate system by rounding the coordinates.
6644 if (d->state->matrix.type() <= QTransform::TxScale) {
6645 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6647 if (d->state->matrix.type() <= QTransform::TxTranslate) {
6652 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6653 drawRect(QRectF(p, r.size()));
6655 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6664 if (d->state->matrix.type() == QTransform::TxTranslate
6665 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6666 x += d->state->matrix.dx();
6667 y += d->state->matrix.dy();
6670 d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6674 \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6675 const QPoint &position = QPoint())
6678 Draws a tiled \a pixmap, inside the given \a rectangle with its
6679 origin at the given \a position.
6683 \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6684 QPixmap &pixmap, int sx, int sy);
6687 Draws a tiled \a pixmap in the specified rectangle.
6689 (\a{x}, \a{y}) specifies the top-left point in the paint device
6690 that is to be drawn onto; with the given \a width and \a
6691 height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6692 pixmap that is to be drawn; this defaults to (0, 0).
6695 #ifndef QT_NO_PICTURE
6698 \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6700 Replays the given \a picture at the given \a point.
6702 The QPicture class is a paint device that records and replays
6703 QPainter commands. A picture serializes the painter commands to an
6704 IO device in a platform-independent format. Everything that can be
6705 painted on a widget or pixmap can also be stored in a picture.
6707 This function does exactly the same as QPicture::play() when
6708 called with \a point = QPoint(0, 0).
6713 \snippet code/src_gui_painting_qpainter.cpp 18
6716 \sa QPicture::play()
6719 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6727 d->updateState(d->state);
6731 const_cast<QPicture *>(&picture)->play(this);
6736 \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6739 Replays the given \a picture at the given \a point.
6743 \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6746 Draws the given \a picture at point (\a x, \a y).
6749 #endif // QT_NO_PICTURE
6752 \fn void QPainter::eraseRect(const QRectF &rectangle)
6754 Erases the area inside the given \a rectangle. Equivalent to
6756 \snippet code/src_gui_painting_qpainter.cpp 19
6760 void QPainter::eraseRect(const QRectF &r)
6764 fillRect(r, d->state->bgBrush);
6767 static inline bool needsResolving(const QBrush &brush)
6769 Qt::BrushStyle s = brush.style();
6770 return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
6771 s == Qt::ConicalGradientPattern) &&
6772 brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
6776 \fn void QPainter::eraseRect(const QRect &rectangle)
6779 Erases the area inside the given \a rectangle.
6783 \fn void QPainter::eraseRect(int x, int y, int width, int height)
6786 Erases the area inside the rectangle beginning at (\a x, \a y)
6787 with the given \a width and \a height.
6792 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
6795 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6796 width and \a height, using the brush \a style specified.
6802 \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
6805 Fills the given \a rectangle with the brush \a style specified.
6811 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
6814 Fills the given \a rectangle with the brush \a style specified.
6820 \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
6822 Fills the given \a rectangle with the \a brush specified.
6824 Alternatively, you can specify a QColor instead of a QBrush; the
6825 QBrush constructor (taking a QColor argument) will automatically
6826 create a solid pattern brush.
6830 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
6838 const QGradient *g = brush.gradient();
6839 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6840 d->extended->fillRect(r, brush);
6845 QPen oldPen = pen();
6846 QBrush oldBrush = this->brush();
6848 if (brush.style() == Qt::SolidPattern) {
6849 d->colorBrush.setStyle(Qt::SolidPattern);
6850 d->colorBrush.setColor(brush.color());
6851 setBrush(d->colorBrush);
6862 \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
6865 Fills the given \a rectangle with the specified \a brush.
6868 void QPainter::fillRect(const QRect &r, const QBrush &brush)
6876 const QGradient *g = brush.gradient();
6877 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6878 d->extended->fillRect(r, brush);
6883 QPen oldPen = pen();
6884 QBrush oldBrush = this->brush();
6886 if (brush.style() == Qt::SolidPattern) {
6887 d->colorBrush.setStyle(Qt::SolidPattern);
6888 d->colorBrush.setColor(brush.color());
6889 setBrush(d->colorBrush);
6902 \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
6905 Fills the given \a rectangle with the \a color specified.
6909 void QPainter::fillRect(const QRect &r, const QColor &color)
6917 d->extended->fillRect(r, color);
6921 fillRect(r, QBrush(color));
6926 \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
6929 Fills the given \a rectangle with the \a color specified.
6933 void QPainter::fillRect(const QRectF &r, const QColor &color)
6941 d->extended->fillRect(r, color);
6945 fillRect(r, QBrush(color));
6949 \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
6953 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6954 width and \a height, using the given \a brush.
6958 \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
6962 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6963 width and \a height, using the given \a color.
6969 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
6973 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6974 width and \a height, using the given \a color.
6980 \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
6984 Fills the given \a rectangle with the specified \a color.
6990 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
6994 Fills the given \a rectangle with the specified \a color.
7000 Sets the given render \a hint on the painter if \a on is true;
7001 otherwise clears the render hint.
7003 \sa setRenderHints(), renderHints(), {QPainter#Rendering
7004 Quality}{Rendering Quality}
7006 void QPainter::setRenderHint(RenderHint hint, bool on)
7008 #ifdef QT_DEBUG_DRAW
7009 if (qt_show_painter_debug_output)
7010 printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
7014 static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
7015 if (hint == QPainter::Antialiasing && antialiasingDisabled)
7019 setRenderHints(hint, on);
7025 Sets the given render \a hints on the painter if \a on is true;
7026 otherwise clears the render hints.
7028 \sa setRenderHint(), renderHints(), {QPainter#Rendering
7029 Quality}{Rendering Quality}
7032 void QPainter::setRenderHints(RenderHints hints, bool on)
7037 qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7042 d->state->renderHints |= hints;
7044 d->state->renderHints &= ~hints;
7047 d->extended->renderHintsChanged();
7049 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7053 Returns a flag that specifies the rendering hints that are set for
7056 \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7058 QPainter::RenderHints QPainter::renderHints() const
7060 Q_D(const QPainter);
7065 return d->state->renderHints;
7069 \fn bool QPainter::testRenderHint(RenderHint hint) const
7072 Returns true if \a hint is set; otherwise returns false.
7074 \sa renderHints(), setRenderHint()
7078 Returns true if view transformation is enabled; otherwise returns
7081 \sa setViewTransformEnabled(), worldTransform()
7084 bool QPainter::viewTransformEnabled() const
7086 Q_D(const QPainter);
7088 qWarning("QPainter::viewTransformEnabled: Painter not active");
7091 return d->state->VxF;
7095 \fn void QPainter::setWindow(const QRect &rectangle)
7097 Sets the painter's window to the given \a rectangle, and enables
7098 view transformations.
7100 The window rectangle is part of the view transformation. The
7101 window specifies the logical coordinate system. Its sister, the
7102 viewport(), specifies the device coordinate system.
7104 The default window rectangle is the same as the device's
7107 \sa window(), viewTransformEnabled(), {Coordinate
7108 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7112 \fn void QPainter::setWindow(int x, int y, int width, int height)
7115 Sets the painter's window to the rectangle beginning at (\a x, \a
7116 y) and the given \a width and \a height.
7119 void QPainter::setWindow(const QRect &r)
7121 #ifdef QT_DEBUG_DRAW
7122 if (qt_show_painter_debug_output)
7123 printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7129 qWarning("QPainter::setWindow: Painter not active");
7133 d->state->wx = r.x();
7134 d->state->wy = r.y();
7135 d->state->ww = r.width();
7136 d->state->wh = r.height();
7138 d->state->VxF = true;
7143 Returns the window rectangle.
7145 \sa setWindow(), setViewTransformEnabled()
7148 QRect QPainter::window() const
7150 Q_D(const QPainter);
7152 qWarning("QPainter::window: Painter not active");
7155 return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7159 \fn void QPainter::setViewport(const QRect &rectangle)
7161 Sets the painter's viewport rectangle to the given \a rectangle,
7162 and enables view transformations.
7164 The viewport rectangle is part of the view transformation. The
7165 viewport specifies the device coordinate system. Its sister, the
7166 window(), specifies the logical coordinate system.
7168 The default viewport rectangle is the same as the device's
7171 \sa viewport(), viewTransformEnabled(), {Coordinate
7172 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7176 \fn void QPainter::setViewport(int x, int y, int width, int height)
7179 Sets the painter's viewport rectangle to be the rectangle
7180 beginning at (\a x, \a y) with the given \a width and \a height.
7183 void QPainter::setViewport(const QRect &r)
7185 #ifdef QT_DEBUG_DRAW
7186 if (qt_show_painter_debug_output)
7187 printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7193 qWarning("QPainter::setViewport: Painter not active");
7197 d->state->vx = r.x();
7198 d->state->vy = r.y();
7199 d->state->vw = r.width();
7200 d->state->vh = r.height();
7202 d->state->VxF = true;
7207 Returns the viewport rectangle.
7209 \sa setViewport(), setViewTransformEnabled()
7212 QRect QPainter::viewport() const
7214 Q_D(const QPainter);
7216 qWarning("QPainter::viewport: Painter not active");
7219 return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7223 Enables view transformations if \a enable is true, or disables
7224 view transformations if \a enable is false.
7226 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7227 Conversion}{Window-Viewport Conversion}
7230 void QPainter::setViewTransformEnabled(bool enable)
7232 #ifdef QT_DEBUG_DRAW
7233 if (qt_show_painter_debug_output)
7234 printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7240 qWarning("QPainter::setViewTransformEnabled: Painter not active");
7244 if (enable == d->state->VxF)
7247 d->state->VxF = enable;
7256 Please use QWidget::render() instead.
7258 Redirects all paint commands for the given paint \a device, to the
7259 \a replacement device. The optional point \a offset defines an
7260 offset within the source device.
7262 The redirection will not be effective until the begin() function
7263 has been called; make sure to call end() for the given \a
7264 device's painter (if any) before redirecting. Call
7265 restoreRedirected() to restore the previous redirection.
7267 \warning Making use of redirections in the QPainter API implies
7268 that QPainter::begin() and QPaintDevice destructors need to hold
7269 a mutex for a short period. This can impact performance. Use of
7270 QWidget::render is strongly encouraged.
7272 \sa redirected(), restoreRedirected()
7274 void QPainter::setRedirected(const QPaintDevice *device,
7275 QPaintDevice *replacement,
7276 const QPoint &offset)
7278 Q_ASSERT(device != 0);
7280 Q_UNUSED(replacement)
7282 qWarning("QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7290 Using QWidget::render() obsoletes the use of this function.
7292 Restores the previous redirection for the given \a device after a
7293 call to setRedirected().
7295 \warning Making use of redirections in the QPainter API implies
7296 that QPainter::begin() and QPaintDevice destructors need to hold
7297 a mutex for a short period. This can impact performance. Use of
7298 QWidget::render is strongly encouraged.
7302 void QPainter::restoreRedirected(const QPaintDevice *device)
7305 qWarning("QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7313 Using QWidget::render() obsoletes the use of this function.
7315 Returns the replacement for given \a device. The optional out
7316 parameter \a offset returns the offset within the replaced device.
7318 \warning Making use of redirections in the QPainter API implies
7319 that QPainter::begin() and QPaintDevice destructors need to hold
7320 a mutex for a short period. This can impact performance. Use of
7321 QWidget::render is strongly encouraged.
7323 \sa setRedirected(), restoreRedirected()
7325 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7332 void qt_format_text(const QFont &fnt, const QRectF &_r,
7333 int tf, const QString& str, QRectF *brect,
7334 int tabstops, int *ta, int tabarraylen,
7337 qt_format_text(fnt, _r,
7339 tabstops, ta, tabarraylen,
7342 void qt_format_text(const QFont &fnt, const QRectF &_r,
7343 int tf, const QTextOption *option, const QString& str, QRectF *brect,
7344 int tabstops, int *ta, int tabarraylen,
7348 Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
7351 tf |= option->alignment();
7352 if (option->wrapMode() != QTextOption::NoWrap)
7353 tf |= Qt::TextWordWrap;
7355 if (option->flags() & QTextOption::IncludeTrailingSpaces)
7356 tf |= Qt::TextIncludeTrailingSpaces;
7358 if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
7359 tf |= Qt::TextExpandTabs;
7362 // we need to copy r here to protect against the case (&r == brect).
7365 bool dontclip = (tf & Qt::TextDontClip);
7366 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
7367 bool singleline = (tf & Qt::TextSingleLine);
7368 bool showmnemonic = (tf & Qt::TextShowMnemonic);
7369 bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
7371 Qt::LayoutDirection layout_direction;
7372 if (tf & Qt::TextForceLeftToRight)
7373 layout_direction = Qt::LeftToRight;
7374 else if (tf & Qt::TextForceRightToLeft)
7375 layout_direction = Qt::RightToLeft;
7377 layout_direction = option->textDirection();
7379 layout_direction = painter->layoutDirection();
7381 layout_direction = Qt::LeftToRight;
7383 tf = QGuiApplicationPrivate::visualAlignment(layout_direction, QFlag(tf));
7385 bool isRightToLeft = layout_direction == Qt::RightToLeft;
7386 bool expandtabs = ((tf & Qt::TextExpandTabs) &&
7387 (((tf & Qt::AlignLeft) && !isRightToLeft) ||
7388 ((tf & Qt::AlignRight) && isRightToLeft)));
7391 tf |= Qt::TextDontPrint;
7393 uint maxUnderlines = 0;
7394 int numUnderlines = 0;
7395 QVarLengthArray<int, 32> underlinePositions(1);
7397 QFontMetricsF fm(fnt);
7400 start_lengthVariant:
7401 bool hasMoreLengthVariants = false;
7402 // compatible behaviour to the old implementation. Replace
7404 int old_offset = offset;
7405 for (; offset < text.length(); offset++) {
7406 QChar chr = text.at(offset);
7407 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
7408 text[offset] = QLatin1Char(' ');
7409 } else if (chr == QLatin1Char('\n')) {
7410 text[offset] = QChar::LineSeparator;
7411 } else if (chr == QLatin1Char('&')) {
7413 } else if (chr == QLatin1Char('\t')) {
7415 text[offset] = QLatin1Char(' ');
7416 } else if (!tabarraylen && !tabstops) {
7417 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
7419 } else if (chr == QChar(ushort(0x9c))) {
7420 // string with multiple length variants
7421 hasMoreLengthVariants = true;
7426 int length = offset - old_offset;
7427 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
7428 underlinePositions.resize(maxUnderlines + 1);
7430 QChar *cout = text.data() + old_offset;
7434 if (*cin == QLatin1Char('&')) {
7440 if (*cin != QLatin1Char('&') && !hidemnmemonic)
7441 underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
7450 // no need to do extra work for underlines if we don't paint
7451 if (tf & Qt::TextDontPrint)
7454 underlinePositions[numUnderlines] = -1;
7458 QString finalText = text.mid(old_offset, length);
7459 QStackTextEngine engine(finalText, fnt);
7461 engine.option = *option;
7464 if (engine.option.tabStop() < 0 && tabstops > 0)
7465 engine.option.setTabStop(tabstops);
7467 if (engine.option.tabs().isEmpty() && ta) {
7469 for (int i = 0; i < tabarraylen; i++)
7470 tabs.append(qreal(ta[i]));
7471 engine.option.setTabArray(tabs);
7474 engine.option.setTextDirection(layout_direction);
7475 if (tf & Qt::AlignJustify)
7476 engine.option.setAlignment(Qt::AlignJustify);
7478 engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
7480 if (!option && (tf & Qt::TextWrapAnywhere))
7481 engine.option.setWrapMode(QTextOption::WrapAnywhere);
7483 if (tf & Qt::TextJustificationForced)
7484 engine.forceJustification = true;
7485 QTextLayout textLayout(&engine);
7486 textLayout.setCacheEnabled(true);
7487 textLayout.engine()->underlinePositions = underlinePositions.data();
7489 if (finalText.isEmpty()) {
7490 height = fm.height();
7492 tf |= Qt::TextDontPrint;
7494 qreal lineWidth = 0x01000000;
7495 if (wordwrap || (tf & Qt::TextJustificationForced))
7496 lineWidth = qMax<qreal>(0, r.width());
7498 tf |= Qt::TextIncludeTrailingSpaces;
7499 textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
7500 textLayout.beginLayout();
7502 qreal leading = fm.leading();
7506 QTextLine l = textLayout.createLine();
7510 l.setLineWidth(lineWidth);
7512 l.setPosition(QPointF(0., height));
7513 height += l.height();
7514 width = qMax(width, l.naturalTextWidth());
7515 if (!dontclip && !brect && height >= r.height())
7518 textLayout.endLayout();
7523 if (tf & Qt::AlignBottom) {
7524 yoff = r.height() - height;
7525 } else if (tf & Qt::AlignVCenter) {
7526 yoff = (r.height() - height)/2;
7528 QTransform::TransformationType type = painter->transform().type();
7529 if (type <= QTransform::TxScale) {
7530 // do the rounding manually to work around inconsistencies
7531 // in the paint engines when drawing on floating point offsets
7532 const qreal scale = painter->transform().m22();
7534 yoff = -qRound(-yoff * scale) / scale;
7538 if (tf & Qt::AlignRight) {
7539 xoff = r.width() - width;
7540 } else if (tf & Qt::AlignHCenter) {
7541 xoff = (r.width() - width)/2;
7543 QTransform::TransformationType type = painter->transform().type();
7544 if (type <= QTransform::TxScale) {
7545 // do the rounding manually to work around inconsistencies
7546 // in the paint engines when drawing on floating point offsets
7547 const qreal scale = painter->transform().m11();
7549 xoff = qRound(xoff * scale) / scale;
7553 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
7555 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
7557 goto start_lengthVariant;
7562 if (!(tf & Qt::TextDontPrint)) {
7563 bool restore = false;
7564 if (!dontclip && !r.contains(bounds)) {
7567 painter->setClipRect(r, Qt::IntersectClip);
7570 for (int i = 0; i < textLayout.lineCount(); i++) {
7571 QTextLine line = textLayout.lineAt(i);
7572 QTextEngine *eng = textLayout.engine();
7573 eng->enableDelayDecorations();
7575 qreal advance = line.horizontalAdvance();
7577 if (tf & Qt::AlignRight) {
7578 xoff = r.width() - advance -
7579 eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
7581 else if (tf & Qt::AlignHCenter)
7582 xoff = (r.width() - advance) / 2;
7584 line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
7585 eng->drawDecorations(painter);
7595 Sets the layout direction used by the painter when drawing text,
7596 to the specified \a direction.
7598 The default is Qt::LayoutDirectionAuto, which will implicitly determine the
7599 direction from the text drawn.
7601 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
7603 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
7607 d->state->layoutDirection = direction;
7611 Returns the layout direction used by the painter when drawing text.
7613 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
7615 Qt::LayoutDirection QPainter::layoutDirection() const
7617 Q_D(const QPainter);
7618 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
7621 QPainterState::QPainterState(const QPainterState *s)
7622 : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
7623 pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
7624 clipRegion(s->clipRegion), clipPath(s->clipPath),
7625 clipOperation(s->clipOperation),
7626 renderHints(s->renderHints), clipInfo(s->clipInfo),
7627 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
7628 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
7629 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
7630 opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
7631 clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
7632 layoutDirection(s->layoutDirection),
7633 composition_mode(s->composition_mode),
7634 emulationSpecifier(s->emulationSpecifier), changeFlags(0)
7636 dirtyFlags = s->dirtyFlags;
7639 QPainterState::QPainterState()
7640 : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
7642 wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
7643 opacity(1), WxF(false), VxF(false), clipEnabled(true),
7644 bgMode(Qt::TransparentMode), painter(0),
7645 layoutDirection(QGuiApplication::layoutDirection()),
7646 composition_mode(QPainter::CompositionMode_SourceOver),
7647 emulationSpecifier(0), changeFlags(0)
7652 QPainterState::~QPainterState()
7656 void QPainterState::init(QPainter *p) {
7657 bgBrush = Qt::white;
7658 bgMode = Qt::TransparentMode;
7662 wx = wy = ww = wh = 0;
7663 vx = vy = vw = vh = 0;
7666 brushOrigin = QPointF(0, 0);
7668 font = deviceFont = QFont();
7669 clipRegion = QRegion();
7670 clipPath = QPainterPath();
7671 clipOperation = Qt::NoClip;
7673 worldMatrix.reset();
7675 layoutDirection = QGuiApplication::layoutDirection();
7676 composition_mode = QPainter::CompositionMode_SourceOver;
7677 emulationSpecifier = 0;
7685 \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
7686 Qt::ImageConversionFlags flags)
7688 Draws the rectangular portion \a source of the given \a image
7689 into the \a target rectangle in the paint device.
7691 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7693 If the image needs to be modified to fit in a lower-resolution
7694 result (e.g. converting from 32-bit to 8-bit), use the \a flags to
7695 specify how you would prefer this to happen.
7700 \snippet code/src_gui_painting_qpainter.cpp 20
7707 \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
7708 Qt::ImageConversionFlags flags)
7711 Draws the rectangular portion \a source of the given \a image
7712 into the \a target rectangle in the paint device.
7714 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7718 \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
7722 Draws the given \a image at the given \a point.
7726 \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
7730 Draws the given \a image at the given \a point.
7734 \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
7735 Qt::ImageConversionFlags flags = 0)
7739 Draws the rectangular portion \a source of the given \a image with
7740 its origin at the given \a point.
7744 \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
7745 Qt::ImageConversionFlags flags = 0)
7748 Draws the rectangular portion \a source of the given \a image with
7749 its origin at the given \a point.
7753 \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
7757 Draws the given \a image into the given \a rectangle.
7759 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7763 \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
7767 Draws the given \a image into the given \a rectangle.
7769 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7773 \fn void QPainter::drawImage(int x, int y, const QImage &image,
7774 int sx, int sy, int sw, int sh,
7775 Qt::ImageConversionFlags flags)
7778 Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
7781 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
7782 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
7783 image that is to be drawn. The default is (0, 0).
7785 (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
7786 The default, (0, 0) (and negative) means all the way to the
7787 bottom-right of the image.
7791 \class QPaintEngineState
7795 \brief The QPaintEngineState class provides information about the
7796 active paint engine's current state.
7799 QPaintEngineState records which properties that have changed since
7800 the last time the paint engine was updated, as well as their
7803 Which properties that have changed can at any time be retrieved
7804 using the state() function. This function returns an instance of
7805 the QPaintEngine::DirtyFlags type which stores an OR combination
7806 of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
7807 enum defines whether a property has changed since the last update
7810 If a property is marked with a dirty flag, its current value can
7811 be retrieved using the corresponding get function:
7816 \header \li Property Flag \li Current Property Value
7817 \row \li QPaintEngine::DirtyBackground \li backgroundBrush()
7818 \row \li QPaintEngine::DirtyBackgroundMode \li backgroundMode()
7819 \row \li QPaintEngine::DirtyBrush \li brush()
7820 \row \li QPaintEngine::DirtyBrushOrigin \li brushOrigin()
7821 \row \li QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
7823 \row \li QPaintEngine::DirtyClipPath \li clipPath()
7824 \row \li QPaintEngine::DirtyClipRegion \li clipRegion()
7825 \row \li QPaintEngine::DirtyCompositionMode \li compositionMode()
7826 \row \li QPaintEngine::DirtyFont \li font()
7827 \row \li QPaintEngine::DirtyTransform \li transform()
7828 \row \li QPaintEngine::DirtyClipEnabled \li isClipEnabled()
7829 \row \li QPaintEngine::DirtyPen \li pen()
7830 \row \li QPaintEngine::DirtyHints \li renderHints()
7833 The QPaintEngineState class also provide the painter() function
7834 which returns a pointer to the painter that is currently updating
7837 An instance of this class, representing the current state of the
7838 active paint engine, is passed as argument to the
7839 QPaintEngine::updateState() function. The only situation in which
7840 you will have to use this class directly is when implementing your
7848 \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
7850 Returns a combination of flags identifying the set of properties
7851 that need to be updated when updating the paint engine's state
7852 (i.e. during a call to the QPaintEngine::updateState() function).
7854 \sa QPaintEngine::updateState()
7859 Returns the pen in the current paint engine state.
7861 This variable should only be used when the state() returns a
7862 combination which includes the QPaintEngine::DirtyPen flag.
7864 \sa state(), QPaintEngine::updateState()
7867 QPen QPaintEngineState::pen() const
7869 return static_cast<const QPainterState *>(this)->pen;
7873 Returns the brush in the current paint engine state.
7875 This variable should only be used when the state() returns a
7876 combination which includes the QPaintEngine::DirtyBrush flag.
7878 \sa state(), QPaintEngine::updateState()
7881 QBrush QPaintEngineState::brush() const
7883 return static_cast<const QPainterState *>(this)->brush;
7887 Returns the brush origin in the current paint engine state.
7889 This variable should only be used when the state() returns a
7890 combination which includes the QPaintEngine::DirtyBrushOrigin flag.
7892 \sa state(), QPaintEngine::updateState()
7895 QPointF QPaintEngineState::brushOrigin() const
7897 return static_cast<const QPainterState *>(this)->brushOrigin;
7901 Returns the background brush in the current paint engine state.
7903 This variable should only be used when the state() returns a
7904 combination which includes the QPaintEngine::DirtyBackground flag.
7906 \sa state(), QPaintEngine::updateState()
7909 QBrush QPaintEngineState::backgroundBrush() const
7911 return static_cast<const QPainterState *>(this)->bgBrush;
7915 Returns the background mode in the current paint engine
7918 This variable should only be used when the state() returns a
7919 combination which includes the QPaintEngine::DirtyBackgroundMode flag.
7921 \sa state(), QPaintEngine::updateState()
7924 Qt::BGMode QPaintEngineState::backgroundMode() const
7926 return static_cast<const QPainterState *>(this)->bgMode;
7930 Returns the font in the current paint engine
7933 This variable should only be used when the state() returns a
7934 combination which includes the QPaintEngine::DirtyFont flag.
7936 \sa state(), QPaintEngine::updateState()
7939 QFont QPaintEngineState::font() const
7941 return static_cast<const QPainterState *>(this)->font;
7948 Returns the matrix in the current paint engine
7951 \note It is advisable to use transform() instead of this function to
7952 preserve the properties of perspective transformations.
7954 This variable should only be used when the state() returns a
7955 combination which includes the QPaintEngine::DirtyTransform flag.
7957 \sa state(), QPaintEngine::updateState()
7960 QMatrix QPaintEngineState::matrix() const
7962 const QPainterState *st = static_cast<const QPainterState *>(this);
7964 return st->matrix.toAffine();
7970 Returns the matrix in the current paint engine state.
7972 This variable should only be used when the state() returns a
7973 combination which includes the QPaintEngine::DirtyTransform flag.
7975 \sa state(), QPaintEngine::updateState()
7979 QTransform QPaintEngineState::transform() const
7981 const QPainterState *st = static_cast<const QPainterState *>(this);
7988 Returns the clip operation in the current paint engine
7991 This variable should only be used when the state() returns a
7992 combination which includes either the QPaintEngine::DirtyClipPath
7993 or the QPaintEngine::DirtyClipRegion flag.
7995 \sa state(), QPaintEngine::updateState()
7998 Qt::ClipOperation QPaintEngineState::clipOperation() const
8000 return static_cast<const QPainterState *>(this)->clipOperation;
8006 Returns whether the coordinate of the fill have been specified
8007 as bounded by the current rendering operation and have to be
8008 resolved (about the currently rendered primitive).
8010 bool QPaintEngineState::brushNeedsResolving() const
8012 const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
8013 return needsResolving(brush);
8020 Returns whether the coordinate of the stroke have been specified
8021 as bounded by the current rendering operation and have to be
8022 resolved (about the currently rendered primitive).
8024 bool QPaintEngineState::penNeedsResolving() const
8026 const QPen &pen = static_cast<const QPainterState *>(this)->pen;
8027 return needsResolving(pen.brush());
8031 Returns the clip region in the current paint engine state.
8033 This variable should only be used when the state() returns a
8034 combination which includes the QPaintEngine::DirtyClipRegion flag.
8036 \sa state(), QPaintEngine::updateState()
8039 QRegion QPaintEngineState::clipRegion() const
8041 return static_cast<const QPainterState *>(this)->clipRegion;
8045 Returns the clip path in the current paint engine state.
8047 This variable should only be used when the state() returns a
8048 combination which includes the QPaintEngine::DirtyClipPath flag.
8050 \sa state(), QPaintEngine::updateState()
8053 QPainterPath QPaintEngineState::clipPath() const
8055 return static_cast<const QPainterState *>(this)->clipPath;
8059 Returns whether clipping is enabled or not in the current paint
8062 This variable should only be used when the state() returns a
8063 combination which includes the QPaintEngine::DirtyClipEnabled
8066 \sa state(), QPaintEngine::updateState()
8069 bool QPaintEngineState::isClipEnabled() const
8071 return static_cast<const QPainterState *>(this)->clipEnabled;
8075 Returns the render hints in the current paint engine state.
8077 This variable should only be used when the state() returns a
8078 combination which includes the QPaintEngine::DirtyHints
8081 \sa state(), QPaintEngine::updateState()
8084 QPainter::RenderHints QPaintEngineState::renderHints() const
8086 return static_cast<const QPainterState *>(this)->renderHints;
8090 Returns the composition mode in the current paint engine state.
8092 This variable should only be used when the state() returns a
8093 combination which includes the QPaintEngine::DirtyCompositionMode
8096 \sa state(), QPaintEngine::updateState()
8099 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8101 return static_cast<const QPainterState *>(this)->composition_mode;
8106 Returns a pointer to the painter currently updating the paint
8110 QPainter *QPaintEngineState::painter() const
8112 return static_cast<const QPainterState *>(this)->painter;
8119 Returns the opacity in the current paint engine state.
8122 qreal QPaintEngineState::opacity() const
8124 return static_cast<const QPainterState *>(this)->opacity;
8130 Sets the world transformation matrix.
8131 If \a combine is true, the specified \a transform is combined with
8132 the current matrix; otherwise it replaces the current matrix.
8134 \sa transform(), setWorldTransform()
8137 void QPainter::setTransform(const QTransform &transform, bool combine )
8139 setWorldTransform(transform, combine);
8143 Returns the world transformation matrix.
8145 \sa worldTransform()
8148 const QTransform & QPainter::transform() const
8150 return worldTransform();
8155 Returns the matrix that transforms from logical coordinates to
8156 device coordinates of the platform dependent paint device.
8158 This function is \e only needed when using platform painting
8159 commands on the platform dependent handle (Qt::HANDLE), and the
8160 platform does not do transformations nativly.
8162 The QPaintEngine::PaintEngineFeature enum can be queried to
8163 determine whether the platform performs the transformations or
8166 \sa worldTransform(), QPaintEngine::hasFeature(),
8169 const QTransform & QPainter::deviceTransform() const
8171 Q_D(const QPainter);
8173 qWarning("QPainter::deviceTransform: Painter not active");
8174 return d->fakeState()->transform;
8176 return d->state->matrix;
8181 Resets any transformations that were made using translate(),
8182 scale(), shear(), rotate(), setWorldTransform(), setViewport()
8185 \sa {Coordinate Transformations}
8188 void QPainter::resetTransform()
8191 #ifdef QT_DEBUG_DRAW
8192 if (qt_show_painter_debug_output)
8193 printf("QPainter::resetMatrix()\n");
8196 qWarning("QPainter::resetMatrix: Painter not active");
8200 d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins
8201 d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
8202 d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
8203 d->state->worldMatrix = QTransform();
8204 setMatrixEnabled(false);
8205 setViewTransformEnabled(false);
8207 d->extended->transformChanged();
8209 d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
8213 Sets the world transformation matrix.
8214 If \a combine is true, the specified \a matrix is combined with the current matrix;
8215 otherwise it replaces the current matrix.
8217 \sa transform(), setTransform()
8220 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
8225 qWarning("QPainter::setWorldTransform: Painter not active");
8230 d->state->worldMatrix = matrix * d->state->worldMatrix; // combines
8232 d->state->worldMatrix = matrix; // set new matrix
8234 d->state->WxF = true;
8239 Returns the world transformation matrix.
8242 const QTransform & QPainter::worldTransform() const
8244 Q_D(const QPainter);
8246 qWarning("QPainter::worldTransform: Painter not active");
8247 return d->fakeState()->transform;
8249 return d->state->worldMatrix;
8253 Returns the transformation matrix combining the current
8254 window/viewport and world transformation.
8256 \sa setWorldTransform(), setWindow(), setViewport()
8259 QTransform QPainter::combinedTransform() const
8261 Q_D(const QPainter);
8263 qWarning("QPainter::combinedTransform: Painter not active");
8264 return QTransform();
8266 return d->state->worldMatrix * d->viewTransform();
8272 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
8273 at multiple positions with different scale, rotation and opacity. \a
8274 fragments is an array of \a fragmentCount elements specifying the
8275 parameters used to draw each pixmap fragment. The \a hints
8276 parameter can be used to pass in drawing hints.
8278 This function is potentially faster than multiple calls to drawPixmap(),
8279 since the backend can optimize state changes.
8281 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
8284 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
8285 const QPixmap &pixmap, PixmapFragmentHints hints)
8289 if (!d->engine || pixmap.isNull())
8293 for (int i = 0; i < fragmentCount; ++i) {
8294 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8295 fragments[i].width, fragments[i].height);
8296 if (!(QRectF(pixmap.rect()).contains(sourceRect)))
8297 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
8301 if (d->engine->isExtended()) {
8302 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
8304 qreal oldOpacity = opacity();
8305 QTransform oldTransform = transform();
8307 for (int i = 0; i < fragmentCount; ++i) {
8308 QTransform transform = oldTransform;
8311 if (fragments[i].rotation == 0) {
8312 xOffset = fragments[i].x;
8313 yOffset = fragments[i].y;
8315 transform.translate(fragments[i].x, fragments[i].y);
8316 transform.rotate(fragments[i].rotation);
8318 setOpacity(oldOpacity * fragments[i].opacity);
8319 setTransform(transform);
8321 qreal w = fragments[i].scaleX * fragments[i].width;
8322 qreal h = fragments[i].scaleY * fragments[i].height;
8323 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8324 fragments[i].width, fragments[i].height);
8325 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
8328 setOpacity(oldOpacity);
8329 setTransform(oldTransform);
8335 \class QPainter::PixmapFragment
8338 \brief This class is used in conjunction with the
8339 QPainter::drawPixmapFragments() function to specify how a pixmap, or
8340 sub-rect of a pixmap, is drawn.
8342 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
8343 as a source rectangle within the pixmap passed into the
8344 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
8345 width and \a height are used to calculate the target rectangle that is
8346 drawn. \a x and \a y denotes the center of the target rectangle. The \a
8347 width and \a height in the target rectangle is scaled by the \a scaleX and
8348 \a scaleY values. The resulting target rectangle is then rotated \a
8349 rotation degrees around the \a x, \a y center point.
8351 \sa QPainter::drawPixmapFragments()
8357 This is a convenience function that returns a QPainter::PixmapFragment that is
8358 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
8359 rotation, \a opacity parameters.
8362 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
8363 qreal scaleX, qreal scaleY, qreal rotation,
8366 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
8367 sourceRect.height(), scaleX, scaleY, rotation, opacity};
8372 \variable QPainter::PixmapFragment::x
8373 \brief the x coordinate of center point in the target rectangle.
8377 \variable QPainter::PixmapFragment::y
8378 \brief the y coordinate of the center point in the target rectangle.
8382 \variable QPainter::PixmapFragment::sourceLeft
8383 \brief the left coordinate of the source rectangle.
8387 \variable QPainter::PixmapFragment::sourceTop
8388 \brief the top coordinate of the source rectangle.
8392 \variable QPainter::PixmapFragment::width
8394 \brief the width of the source rectangle and is used to calculate the width
8395 of the target rectangle.
8399 \variable QPainter::PixmapFragment::height
8401 \brief the height of the source rectangle and is used to calculate the
8402 height of the target rectangle.
8406 \variable QPainter::PixmapFragment::scaleX
8407 \brief the horizontal scale of the target rectangle.
8411 \variable QPainter::PixmapFragment::scaleY
8412 \brief the vertical scale of the target rectangle.
8416 \variable QPainter::PixmapFragment::rotation
8418 \brief the rotation of the target rectangle in degrees. The target
8419 rectangle is rotated after it has been scaled.
8423 \variable QPainter::PixmapFragment::opacity
8425 \brief the opacity of the target rectangle, where 0.0 is fully transparent
8426 and 1.0 is fully opaque.
8432 \enum QPainter::PixmapFragmentHint
8434 \value OpaqueHint Indicates that the pixmap fragments to be drawn are
8435 opaque. Opaque fragments are potentially faster to draw.
8437 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
8440 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
8442 p->draw_helper(path, operation);