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;
900 } else if (newState->state() || engine->state!=newState) {
901 updateStateImpl(newState);
908 \brief The QPainter class performs low-level painting on widgets and
916 QPainter provides highly optimized functions to do most of the
917 drawing GUI programs require. It can draw everything from simple
918 lines to complex shapes like pies and chords. It can also draw
919 aligned text and pixmaps. Normally, it draws in a "natural"
920 coordinate system, but it can also do view and world
921 transformation. QPainter can operate on any object that inherits
922 the QPaintDevice class.
924 The common use of QPainter is inside a widget's paint event:
925 Construct and customize (e.g. set the pen or the brush) the
926 painter. Then draw. Remember to destroy the QPainter object after
927 drawing. For example:
929 \snippet code/src_gui_painting_qpainter.cpp 0
931 The core functionality of QPainter is drawing, but the class also
932 provide several functions that allows you to customize QPainter's
933 settings and its rendering quality, and others that enable
934 clipping. In addition you can control how different shapes are
935 merged together by specifying the painter's composition mode.
937 The isActive() function indicates whether the painter is active. A
938 painter is activated by the begin() function and the constructor
939 that takes a QPaintDevice argument. The end() function, and the
940 destructor, deactivates it.
942 Together with the QPaintDevice and QPaintEngine classes, QPainter
943 form the basis for Qt's paint system. QPainter is the class used
944 to perform drawing operations. QPaintDevice represents a device
945 that can be painted on using a QPainter. QPaintEngine provides the
946 interface that the painter uses to draw onto different types of
947 devices. If the painter is active, device() returns the paint
948 device on which the painter paints, and paintEngine() returns the
949 paint engine that the painter is currently operating on. For more
950 information, see the \l {Paint System}.
952 Sometimes it is desirable to make someone else paint on an unusual
953 QPaintDevice. QPainter supports a static function to do this,
956 \warning When the paintdevice is a widget, QPainter can only be
957 used inside a paintEvent() function or in a function called by
964 There are several settings that you can customize to make QPainter
965 draw according to your preferences:
969 \li font() is the font used for drawing text. If the painter
970 isActive(), you can retrieve information about the currently set
971 font, and its metrics, using the fontInfo() and fontMetrics()
972 functions respectively.
974 \li brush() defines the color or pattern that is used for filling
977 \li pen() defines the color or stipple that is used for drawing
980 \li backgroundMode() defines whether there is a background() or
981 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
983 \li background() only applies when backgroundMode() is \l
984 Qt::OpaqueMode and pen() is a stipple. In that case, it
985 describes the color of the background pixels in the stipple.
987 \li brushOrigin() defines the origin of the tiled brushes, normally
988 the origin of widget's background.
990 \li viewport(), window(), worldTransform() make up the painter's coordinate
991 transformation system. For more information, see the \l
992 {Coordinate Transformations} section and the \l {Coordinate
993 System} documentation.
995 \li hasClipping() tells whether the painter clips at all. (The paint
996 device clips, too.) If the painter clips, it clips to clipRegion().
998 \li layoutDirection() defines the layout direction used by the
999 painter when drawing text.
1001 \li worldMatrixEnabled() tells whether world transformation is enabled.
1003 \li viewTransformEnabled() tells whether view transformation is
1008 Note that some of these settings mirror settings in some paint
1009 devices, e.g. QWidget::font(). The QPainter::begin() function (or
1010 equivalently the QPainter constructor) copies these attributes
1011 from the paint device.
1013 You can at any time save the QPainter's state by calling the
1014 save() function which saves all the available settings on an
1015 internal stack. The restore() function pops them back.
1019 QPainter provides functions to draw most primitives: drawPoint(),
1020 drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1021 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1022 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
1023 convenience functions, drawRects() and drawLines(), draw the given
1024 number of rectangles or lines in the given array of \l
1025 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1028 The QPainter class also provides the fillRect() function which
1029 fills the given QRect, with the given QBrush, and the eraseRect()
1030 function that erases the area inside the given rectangle.
1032 All of these functions have both integer and floating point
1037 \li \inlineimage qpainter-basicdrawing.png
1039 \b {Basic Drawing Example}
1041 The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1042 display basic graphics primitives in a variety of styles using the
1047 If you need to draw a complex shape, especially if you need to do
1048 so repeatedly, consider creating a QPainterPath and drawing it
1054 \b {Painter Paths example}
1056 The QPainterPath class provides a container for painting
1057 operations, enabling graphical shapes to be constructed and
1060 The \l {painting/painterpaths}{Painter Paths} example shows how
1061 painter paths can be used to build complex shapes for rendering.
1063 \li \inlineimage qpainter-painterpaths.png
1066 QPainter also provides the fillPath() function which fills the
1067 given QPainterPath with the given QBrush, and the strokePath()
1068 function that draws the outline of the given path (i.e. strokes
1071 See also the \l {painting/deform}{Vector Deformation} example which
1072 shows how to use advanced vector techniques to draw text using a
1073 QPainterPath, the \l {painting/gradients}{Gradients} example which shows
1074 the different types of gradients that are available in Qt, and the \l
1075 {painting/pathstroke}{Path Stroking} example which shows Qt's built-in
1076 dash patterns and shows how custom patterns can be used to extend
1077 the range of available patterns.
1081 \li \l {painting/deform}{Vector Deformation}
1082 \li \l {painting/gradients}{Gradients}
1083 \li \l {painting/pathstroke}{Path Stroking}
1085 \li \inlineimage qpainter-vectordeformation.png
1086 \li \inlineimage qpainter-gradients.png
1087 \li \inlineimage qpainter-pathstroking.png
1091 There are functions to draw pixmaps/images, namely drawPixmap(),
1092 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1093 produce the same result, except that drawPixmap() is faster
1094 on-screen while drawImage() may be faster on a QPrinter or other
1097 Text drawing is done using drawText(). When you need
1098 fine-grained positioning, boundingRect() tells you where a given
1099 drawText() command will draw.
1101 There is a drawPicture() function that draws the contents of an
1102 entire QPicture. The drawPicture() function is the only function
1103 that disregards all the painter's settings as QPicture has its own
1106 \section1 Rendering Quality
1108 To get the optimal rendering result using QPainter, you should use
1109 the platform independent QImage as paint device; i.e. using QImage
1110 will ensure that the result has an identical pixel representation
1113 The QPainter class also provides a means of controlling the
1114 rendering quality through its RenderHint enum and the support for
1115 floating point precision: All the functions for drawing primitives
1116 has a floating point version. These are often used in combination
1117 with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1121 \li \inlineimage qpainter-concentriccircles.png
1123 \b {Concentric Circles Example}
1125 The \l {painting/concentriccircles}{Concentric Circles} example
1126 shows the improved rendering quality that can be obtained using
1127 floating point precision and anti-aliasing when drawing custom
1130 The application's main window displays several widgets which are
1131 drawn using the various combinations of precision and
1136 The RenderHint enum specifies flags to QPainter that may or may
1137 not be respected by any given engine. \l
1138 {RenderHint}{QPainter::Antialiasing} indicates that the engine
1139 should antialias edges of primitives if possible, \l
1140 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1141 should antialias text if possible, and the \l
1142 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1143 engine should use a smooth pixmap transformation algorithm.
1144 \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
1145 indicating that the engine should use fragment programs and offscreen
1146 rendering for antialiasing.
1148 The renderHints() function returns a flag that specifies the
1149 rendering hints that are set for this painter. Use the
1150 setRenderHint() function to set or clear the currently set
1153 \section1 Coordinate Transformations
1155 Normally, the QPainter operates on the device's own coordinate
1156 system (usually pixels), but QPainter has good support for
1157 coordinate transformations.
1161 \li nop \li rotate() \li scale() \li translate()
1163 \li \inlineimage qpainter-clock.png
1164 \li \inlineimage qpainter-rotation.png
1165 \li \inlineimage qpainter-scale.png
1166 \li \inlineimage qpainter-translation.png
1169 The most commonly used transformations are scaling, rotation,
1170 translation and shearing. Use the scale() function to scale the
1171 coordinate system by a given offset, the rotate() function to
1172 rotate it clockwise and translate() to translate it (i.e. adding a
1173 given offset to the points). You can also twist the coordinate
1174 system around the origin using the shear() function. See the \l
1175 {painting/affine}{Affine Transformations} example for a visualization of
1176 a sheared coordinate system.
1178 See also the \l {painting/transformations}{Transformations}
1179 example which shows how transformations influence the way that
1180 QPainter renders graphics primitives. In particular it shows how
1181 the order of transformations affects the result.
1186 \b {Affine Transformations Example}
1188 The \l {painting/affine}{Affine Transformations} example shows Qt's
1189 ability to perform affine transformations on painting
1190 operations. The demo also allows the user to experiment with the
1191 transformation operations and see the results immediately.
1193 \li \inlineimage qpainter-affinetransformations.png
1196 All the tranformation operations operate on the transformation
1197 worldTransform(). A matrix transforms a point in the plane to another
1198 point. For more information about the transformation matrix, see
1199 the \l {Coordinate System} and QTransform documentation.
1201 The setWorldTransform() function can replace or add to the currently
1202 set worldTransform(). The resetTransform() function resets any
1203 transformations that were made using translate(), scale(),
1204 shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1205 functions. The deviceTransform() returns the matrix that transforms
1206 from logical coordinates to device coordinates of the platform
1207 dependent paint device. The latter function is only needed when
1208 using platform painting commands on the platform dependent handle,
1209 and the platform does not do transformations nativly.
1211 When drawing with QPainter, we specify points using logical
1212 coordinates which then are converted into the physical coordinates
1213 of the paint device. The mapping of the logical coordinates to the
1214 physical coordinates are handled by QPainter's combinedTransform(), a
1215 combination of viewport() and window() and worldTransform(). The
1216 viewport() represents the physical coordinates specifying an
1217 arbitrary rectangle, the window() describes the same rectangle in
1218 logical coordinates, and the worldTransform() is identical with the
1219 transformation matrix.
1221 See also \l {Coordinate System}
1225 QPainter can clip any drawing operation to a rectangle, a region,
1226 or a vector path. The current clip is available using the
1227 functions clipRegion() and clipPath(). Whether paths or regions are
1228 preferred (faster) depends on the underlying paintEngine(). For
1229 example, the QImage paint engine prefers paths while the X11 paint
1230 engine prefers regions. Setting a clip is done in the painters
1231 logical coordinates.
1233 After QPainter's clipping, the paint device may also clip. For
1234 example, most widgets clip away the pixels used by child widgets,
1235 and most printers clip away an area near the edges of the paper.
1236 This additional clipping is not reflected by the return value of
1237 clipRegion() or hasClipping().
1239 \section1 Composition Modes
1240 \target Composition Modes
1242 QPainter provides the CompositionMode enum which defines the
1243 Porter-Duff rules for digital image compositing; it describes a
1244 model for combining the pixels in one image, the source, with the
1245 pixels in another image, the destination.
1247 The two most common forms of composition are \l
1248 {QPainter::CompositionMode}{Source} and \l
1249 {QPainter::CompositionMode}{SourceOver}. \l
1250 {QPainter::CompositionMode}{Source} is used to draw opaque objects
1251 onto a paint device. In this mode, each pixel in the source
1252 replaces the corresponding pixel in the destination. In \l
1253 {QPainter::CompositionMode}{SourceOver} composition mode, the
1254 source object is transparent and is drawn on top of the
1257 Note that composition transformation operates pixelwise. For that
1258 reason, there is a difference between using the graphic primitive
1259 itself and its bounding rectangle: The bounding rect contains
1260 pixels with alpha == 0 (i.e the pixels surrounding the
1261 primitive). These pixels will overwrite the other image's pixels,
1262 affectively clearing those, while the primitive only overwrites
1267 \li \inlineimage qpainter-compositiondemo.png
1270 \b {Composition Modes Example}
1272 The \l {painting/composition}{Composition Modes} example, available in
1273 Qt's examples directory, allows you to experiment with the various
1274 composition modes and see the results immediately.
1278 \section1 Limitations
1281 If you are using coordinates with Qt's raster-based paint engine, it is
1282 important to note that, while coordinates greater than +/- 2\sup 15 can
1283 be used, any painting performed with coordinates outside this range is not
1284 guaranteed to be shown; the drawing may be clipped. This is due to the
1285 use of \c{short int} in the implementation.
1287 The outlines generated by Qt's stroker are only an approximation when dealing
1288 with curved shapes. It is in most cases impossible to represent the outline of
1289 a bezier curve segment using another bezier curve segment, and so Qt approximates
1290 the curve outlines by using several smaller curves. For performance reasons there
1291 is a limit to how many curves Qt uses for these outlines, and thus when using
1292 large pen widths or scales the outline error increases. To generate outlines with
1293 smaller errors it is possible to use the QPainterPathStroker class, which has the
1294 setCurveThreshold member function which let's the user specify the error tolerance.
1295 Another workaround is to convert the paths to polygons first and then draw the
1298 \section1 Performance
1300 QPainter is a rich framework that allows developers to do a great
1301 variety of graphical operations, such as gradients, composition
1302 modes and vector graphics. And QPainter can do this across a
1303 variety of different hardware and software stacks. Naturally the
1304 underlying combination of hardware and software has some
1305 implications for performance, and ensuring that every single
1306 operation is fast in combination with all the various combinations
1307 of composition modes, brushes, clipping, transformation, etc, is
1308 close to an impossible task because of the number of
1309 permutations. As a compromise we have selected a subset of the
1310 QPainter API and backends, where performance is guaranteed to be as
1311 good as we can sensibly get it for the given combination of
1312 hardware and software.
1314 The backends we focus on as high-performance engines are:
1318 \li Raster - This backend implements all rendering in pure software
1319 and is always used to render into QImages. For optimal performance
1320 only use the format types QImage::Format_ARGB32_Premultiplied,
1321 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1322 including QImage::Format_ARGB32, has significantly worse
1323 performance. This engine is used by default for QWidget and QPixmap.
1325 \li OpenGL 2.0 (ES) - This backend is the primary backend for
1326 hardware accelerated graphics. It can be run on desktop machines
1327 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1328 specification. This includes most graphics chips produced in the
1329 last couple of years. The engine can be enabled by using QPainter
1330 onto a QOpenGLWidget or by passing \c {-graphicssystem opengl} on the
1331 command line when the underlying system supports it.
1333 \li OpenVG - This backend implements the Khronos standard for 2D
1334 and Vector Graphics. It is primarily for embedded devices with
1335 hardware support for OpenVG. The engine can be enabled by
1336 passing \c {-graphicssystem openvg} on the command line when
1337 the underlying system supports it.
1341 These operations are:
1345 \li Simple transformations, meaning translation and scaling, pluss
1346 0, 90, 180, 270 degree rotations.
1348 \li \c drawPixmap() in combination with simple transformations and
1349 opacity with non-smooth transformation mode
1350 (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1352 \li Rectangle fills with solid color, two-color linear gradients
1353 and simple transforms.
1355 \li Rectangular clipping with simple transformations and intersect
1358 \li Composition Modes \c QPainter::CompositionMode_Source and
1359 QPainter::CompositionMode_SourceOver
1361 \li Rounded rectangle filling using solid color and two-color
1362 linear gradients fills.
1364 \li 3x3 patched pixmaps, via qDrawBorderPixmap.
1368 This list gives an indication of which features to safely use in
1369 an application where performance is critical. For certain setups,
1370 other operations may be fast too, but before making extensive use
1371 of them, it is recommended to benchmark and verify them on the
1372 system where the software will run in the end. There are also
1373 cases where expensive operations are ok to use, for instance when
1374 the result is cached in a QPixmap.
1376 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
1377 {Drawing Utility Functions}
1381 \enum QPainter::RenderHint
1383 Renderhints are used to specify flags to QPainter that may or
1384 may not be respected by any given engine.
1386 \value Antialiasing Indicates that the engine should antialias
1387 edges of primitives if possible.
1389 \value TextAntialiasing Indicates that the engine should antialias
1390 text if possible. To forcibly disable antialiasing for text, do not
1391 use this hint. Instead, set QFont::NoAntialias on your font's style
1394 \value SmoothPixmapTransform Indicates that the engine should use
1395 a smooth pixmap transformation algorithm (such as bilinear) rather
1396 than nearest neighbor.
1398 \value HighQualityAntialiasing An OpenGL-specific rendering hint
1399 indicating that the engine should use fragment programs and offscreen
1400 rendering for antialiasing.
1402 \value NonCosmeticDefaultPen This value is obsolete, the default for QPen
1403 is now non-cosmetic.
1405 \value Qt4CompatiblePainting Compatibility hint telling the engine to use the
1406 same X11 based fill rules as in Qt 4, where aliased rendering is offset
1407 by slightly less than half a pixel. Also will treat default constructed pens
1408 as cosmetic. Potentially useful when porting a Qt 4 application to Qt 5.
1410 \sa renderHints(), setRenderHint(), {QPainter#Rendering
1411 Quality}{Rendering Quality}, {Concentric Circles Example}
1416 Constructs a painter.
1421 QPainter::QPainter()
1422 : d_ptr(new QPainterPrivate(this))
1427 \fn QPainter::QPainter(QPaintDevice *device)
1429 Constructs a painter that begins painting the paint \a device
1432 This constructor is convenient for short-lived painters, e.g. in a
1433 QWidget::paintEvent() and should be used only once. The
1434 constructor calls begin() for you and the QPainter destructor
1435 automatically calls end().
1437 Here's an example using begin() and end():
1438 \snippet code/src_gui_painting_qpainter.cpp 1
1440 The same example using this constructor:
1441 \snippet code/src_gui_painting_qpainter.cpp 2
1443 Since the constructor cannot provide feedback when the initialization
1444 of the painter failed you should rather use begin() and end() to paint
1445 on external devices, e.g. printers.
1450 QPainter::QPainter(QPaintDevice *pd)
1454 if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1455 d_ptr.reset(new QPainterPrivate(this));
1462 Destroys the painter.
1464 QPainter::~QPainter()
1466 d_ptr->inDestructor = true;
1470 else if (d_ptr->refcount > 1)
1471 d_ptr->detachPainterPrivate(this);
1473 // don't throw anything in the destructor.
1476 // Make sure we haven't messed things up.
1477 Q_ASSERT(d_ptr->inDestructor);
1478 d_ptr->inDestructor = false;
1479 Q_ASSERT(d_ptr->refcount == 1);
1481 free(d_ptr->d_ptrs);
1486 Returns the paint device on which this painter is currently
1487 painting, or 0 if the painter is not active.
1492 QPaintDevice *QPainter::device() const
1494 Q_D(const QPainter);
1495 if (isActive() && d->engine->d_func()->currentClipDevice)
1496 return d->engine->d_func()->currentClipDevice;
1497 return d->original_device;
1501 Returns true if begin() has been called and end() has not yet been
1502 called; otherwise returns false.
1504 \sa begin(), QPaintDevice::paintingActive()
1507 bool QPainter::isActive() const
1509 Q_D(const QPainter);
1514 Initializes the painters pen, background and font to the same as
1515 the given \a device.
1519 \sa begin(), {QPainter#Settings}{Settings}
1521 void QPainter::initFrom(const QPaintDevice *device)
1523 Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0");
1526 qWarning("QPainter::initFrom: Painter not active, aborted");
1530 device->initPainter(this);
1533 d->extended->penChanged();
1534 } else if (d->engine) {
1535 d->engine->setDirty(QPaintEngine::DirtyPen);
1536 d->engine->setDirty(QPaintEngine::DirtyBrush);
1537 d->engine->setDirty(QPaintEngine::DirtyFont);
1543 Saves the current painter state (pushes the state onto a stack). A
1544 save() must be followed by a corresponding restore(); the end()
1545 function unwinds the stack.
1550 void QPainter::save()
1552 #ifdef QT_DEBUG_DRAW
1553 if (qt_show_painter_debug_output)
1554 printf("QPainter::save()\n");
1558 qWarning("QPainter::save: Painter not active");
1563 d->state = d->extended->createState(d->states.back());
1564 d->extended->setState(d->state);
1566 d->updateState(d->state);
1567 d->state = new QPainterState(d->states.back());
1568 d->engine->state = d->state;
1570 d->states.push_back(d->state);
1574 Restores the current painter state (pops a saved state off the
1580 void QPainter::restore()
1582 #ifdef QT_DEBUG_DRAW
1583 if (qt_show_painter_debug_output)
1584 printf("QPainter::restore()\n");
1587 if (d->states.size()<=1) {
1588 qWarning("QPainter::restore: Unbalanced save/restore");
1590 } else if (!d->engine) {
1591 qWarning("QPainter::restore: Painter not active");
1595 QPainterState *tmp = d->state;
1596 d->states.pop_back();
1597 d->state = d->states.back();
1601 d->checkEmulation();
1602 d->extended->setState(d->state);
1607 // trigger clip update if the clip path/region has changed since
1609 if (!d->state->clipInfo.isEmpty()
1610 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1611 // reuse the tmp state to avoid any extra allocs...
1612 tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1613 tmp->clipOperation = Qt::NoClip;
1614 tmp->clipPath = QPainterPath();
1615 d->engine->updateState(*tmp);
1616 // replay the list of clip states,
1617 for (int i=0; i<d->state->clipInfo.size(); ++i) {
1618 const QPainterClipInfo &info = d->state->clipInfo.at(i);
1619 tmp->matrix = info.matrix;
1620 tmp->matrix *= d->state->redirectionMatrix;
1621 tmp->clipOperation = info.operation;
1622 if (info.clipType == QPainterClipInfo::RectClip) {
1623 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1624 tmp->clipRegion = info.rect;
1625 } else if (info.clipType == QPainterClipInfo::RegionClip) {
1626 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1627 tmp->clipRegion = info.region;
1628 } else { // clipType == QPainterClipInfo::PathClip
1629 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1630 tmp->clipPath = info.path;
1632 d->engine->updateState(*tmp);
1636 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1637 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1638 tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1639 tmp->changeFlags |= QPaintEngine::DirtyTransform;
1642 d->updateState(d->state);
1649 \fn bool QPainter::begin(QPaintDevice *device)
1651 Begins painting the paint \a device and returns true if
1652 successful; otherwise returns false.
1654 Notice that all painter settings (setPen(), setBrush() etc.) are reset
1655 to default values when begin() is called.
1657 The errors that can occur are serious problems, such as these:
1659 \snippet code/src_gui_painting_qpainter.cpp 3
1661 Note that most of the time, you can use one of the constructors
1662 instead of begin(), and that end() is automatically done at
1665 \warning A paint device can only be painted by one painter at a
1668 \warning Painting on a QImage with the format
1669 QImage::Format_Indexed8 is not supported.
1671 \sa end(), QPainter()
1674 static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1683 bool QPainter::begin(QPaintDevice *pd)
1687 if (pd->painters > 0) {
1688 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1692 if (d_ptr->engine) {
1693 qWarning("QPainter::begin: Painter already active");
1697 if (QPainterPrivate::attachPainterPrivate(this, pd))
1702 d->helper_device = pd;
1703 d->original_device = pd;
1705 QPoint redirectionOffset;
1706 QPaintDevice *rpd = pd->redirected(&redirectionOffset);
1710 #ifdef QT_DEBUG_DRAW
1711 if (qt_show_painter_debug_output)
1712 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1715 if (pd->devType() == QInternal::Pixmap)
1716 static_cast<QPixmap *>(pd)->detach();
1717 else if (pd->devType() == QInternal::Image)
1718 static_cast<QImage *>(pd)->detach();
1720 d->engine = pd->paintEngine();
1723 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1729 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1730 if (d->emulationEngine)
1731 d->emulationEngine->real_engine = d->extended;
1733 // Setup new state...
1734 Q_ASSERT(!d->state);
1735 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1736 d->state->painter = this;
1737 d->states.push_back(d->state);
1739 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1740 d->state->brushOrigin = QPointF();
1742 // Slip a painter state into the engine before we do any other operations
1744 d->extended->setState(d->state);
1746 d->engine->state = d->state;
1748 switch (pd->devType()) {
1749 case QInternal::Pixmap:
1751 QPixmap *pm = static_cast<QPixmap *>(pd);
1754 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1755 qt_cleanup_painter_state(d);
1759 if (pm->depth() == 1) {
1760 d->state->pen = QPen(Qt::color1);
1761 d->state->brush = QBrush(Qt::color0);
1765 case QInternal::Image:
1767 QImage *img = static_cast<QImage *>(pd);
1769 if (img->isNull()) {
1770 qWarning("QPainter::begin: Cannot paint on a null image");
1771 qt_cleanup_painter_state(d);
1773 } else if (img->format() == QImage::Format_Indexed8) {
1774 // Painting on indexed8 images is not supported.
1775 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1776 qt_cleanup_painter_state(d);
1779 if (img->depth() == 1) {
1780 d->state->pen = QPen(Qt::color1);
1781 d->state->brush = QBrush(Qt::color0);
1788 if (d->state->ww == 0) // For compat with 3.x painter defaults
1789 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1791 d->engine->setPaintDevice(pd);
1793 bool begun = d->engine->begin(pd);
1795 qWarning("QPainter::begin(): Returned false");
1796 if (d->engine->isActive()) {
1799 qt_cleanup_painter_state(d);
1803 d->engine->setActive(begun);
1806 // Copy painter properties from original paint device,
1807 // required for QPixmap::grabWidget()
1808 if (d->original_device->devType() == QInternal::Widget) {
1809 initFrom(d->original_device);
1811 d->state->layoutDirection = Qt::LayoutDirectionAuto;
1812 // make sure we have a font compatible with the paintdevice
1813 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1816 QRect systemRect = d->engine->systemRect();
1817 if (!systemRect.isEmpty()) {
1818 d->state->ww = d->state->vw = systemRect.width();
1819 d->state->wh = d->state->vh = systemRect.height();
1821 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1822 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1825 const QPoint coordinateOffset = d->engine->coordinateOffset();
1826 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1828 Q_ASSERT(d->engine->isActive());
1830 if (!d->state->redirectionMatrix.isIdentity())
1833 Q_ASSERT(d->engine->isActive());
1834 d->state->renderHints = QPainter::TextAntialiasing;
1835 ++d->device->painters;
1837 d->state->emulationSpecifier = 0;
1843 Ends painting. Any resources used while painting are released. You
1844 don't normally need to call this since it is called by the
1847 Returns true if the painter is no longer active; otherwise returns false.
1849 \sa begin(), isActive()
1852 bool QPainter::end()
1854 #ifdef QT_DEBUG_DRAW
1855 if (qt_show_painter_debug_output)
1856 printf("QPainter::end()\n");
1861 qWarning("QPainter::end: Painter not active, aborted");
1862 qt_cleanup_painter_state(d);
1866 if (d->refcount > 1) {
1867 d->detachPainterPrivate(this);
1873 if (d->engine->isActive()) {
1874 ended = d->engine->end();
1877 --d->device->painters;
1878 if (d->device->painters == 0) {
1879 d->engine->setPaintDevice(0);
1880 d->engine->setActive(false);
1884 if (d->states.size() > 1) {
1885 qWarning("QPainter::end: Painter ended with %d saved states",
1889 if (d->engine->autoDestruct()) {
1893 if (d->emulationEngine) {
1894 delete d->emulationEngine;
1895 d->emulationEngine = 0;
1902 qt_cleanup_painter_state(d);
1909 Returns the paint engine that the painter is currently operating
1910 on if the painter is active; otherwise 0.
1914 QPaintEngine *QPainter::paintEngine() const
1916 Q_D(const QPainter);
1923 Flushes the painting pipeline and prepares for the user issuing commands
1924 directly to the underlying graphics context. Must be followed by a call to
1925 endNativePainting().
1927 Note that only the states the underlying paint engine changes will be reset
1928 to their respective default states. The states we reset may change from
1929 release to release. The following states are currently reset in the OpenGL
1933 \li blending is disabled
1934 \li the depth, stencil and scissor tests are disabled
1935 \li the active texture unit is reset to 0
1936 \li the depth mask, depth function and the clear depth are reset to their
1938 \li the stencil mask, stencil operation and stencil function are reset to
1939 their default values
1940 \li the current color is reset to solid white
1943 If, for example, the OpenGL polygon mode is changed by the user inside a
1944 beginNativePaint()/endNativePainting() block, it will not be reset to the
1945 default state by endNativePainting(). Here is an example that shows
1946 intermixing of painter commands and raw OpenGL commands:
1948 \snippet code/src_gui_painting_qpainter.cpp 21
1950 \sa endNativePainting()
1952 void QPainter::beginNativePainting()
1956 qWarning("QPainter::beginNativePainting: Painter not active");
1961 d->extended->beginNativePainting();
1967 Restores the painter after manually issuing native painting commands. Lets
1968 the painter restore any native state that it relies on before calling any
1969 other painter commands.
1971 \sa beginNativePainting()
1973 void QPainter::endNativePainting()
1975 Q_D(const QPainter);
1977 qWarning("QPainter::beginNativePainting: Painter not active");
1982 d->extended->endNativePainting();
1984 d->engine->syncState();
1988 Returns the font metrics for the painter if the painter is
1989 active. Otherwise, the return value is undefined.
1991 \sa font(), isActive(), {QPainter#Settings}{Settings}
1994 QFontMetrics QPainter::fontMetrics() const
1996 Q_D(const QPainter);
1998 qWarning("QPainter::fontMetrics: Painter not active");
1999 return QFontMetrics(QFont());
2001 return QFontMetrics(d->state->font);
2006 Returns the font info for the painter if the painter is
2007 active. Otherwise, the return value is undefined.
2009 \sa font(), isActive(), {QPainter#Settings}{Settings}
2012 QFontInfo QPainter::fontInfo() const
2014 Q_D(const QPainter);
2016 qWarning("QPainter::fontInfo: Painter not active");
2017 return QFontInfo(QFont());
2019 return QFontInfo(d->state->font);
2025 Returns the opacity of the painter. The default value is
2029 qreal QPainter::opacity() const
2031 Q_D(const QPainter);
2033 qWarning("QPainter::opacity: Painter not active");
2036 return d->state->opacity;
2042 Sets the opacity of the painter to \a opacity. The value should
2043 be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2044 1.0 is fully opaque.
2046 Opacity set on the painter will apply to all drawing operations
2050 void QPainter::setOpacity(qreal opacity)
2055 qWarning("QPainter::setOpacity: Painter not active");
2059 opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2061 if (opacity == d->state->opacity)
2064 d->state->opacity = opacity;
2067 d->extended->opacityChanged();
2069 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2074 Returns the currently set brush origin.
2076 \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2079 QPoint QPainter::brushOrigin() const
2081 Q_D(const QPainter);
2083 qWarning("QPainter::brushOrigin: Painter not active");
2086 return QPointF(d->state->brushOrigin).toPoint();
2090 \fn void QPainter::setBrushOrigin(const QPointF &position)
2092 Sets the brush origin to \a position.
2094 The brush origin specifies the (0, 0) coordinate of the painter's
2097 Note that while the brushOrigin() was necessary to adopt the
2098 parent's background for a widget in Qt 3, this is no longer the
2099 case since the Qt 4 painter doesn't paint the background unless
2100 you explicitly tell it to do so by setting the widget's \l
2101 {QWidget::autoFillBackground}{autoFillBackground} property to
2104 \sa brushOrigin(), {QPainter#Settings}{Settings}
2107 void QPainter::setBrushOrigin(const QPointF &p)
2110 #ifdef QT_DEBUG_DRAW
2111 if (qt_show_painter_debug_output)
2112 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2116 qWarning("QPainter::setBrushOrigin: Painter not active");
2120 d->state->brushOrigin = p;
2123 d->extended->brushOriginChanged();
2127 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2131 \fn void QPainter::setBrushOrigin(const QPoint &position)
2134 Sets the brush's origin to the given \a position.
2138 \fn void QPainter::setBrushOrigin(int x, int y)
2142 Sets the brush's origin to point (\a x, \a y).
2146 \enum QPainter::CompositionMode
2148 Defines the modes supported for digital image compositing.
2149 Composition modes are used to specify how the pixels in one image,
2150 the source, are merged with the pixel in another image, the
2153 Please note that the bitwise raster operation modes, denoted with
2154 a RasterOp prefix, are only natively supported in the X11 and
2155 raster paint engines. This means that the only way to utilize
2156 these modes on the Mac is via a QImage. The RasterOp denoted blend
2157 modes are \e not supported for pens and brushes with alpha
2158 components. Also, turning on the QPainter::Antialiasing render
2159 hint will effectively disable the RasterOp modes.
2162 \image qpainter-compositionmode1.png
2163 \image qpainter-compositionmode2.png
2165 The most common type is SourceOver (often referred to as just
2166 alpha blending) where the source pixel is blended on top of the
2167 destination pixel in such a way that the alpha component of the
2168 source defines the translucency of the pixel.
2170 When the paint device is a QImage, the image format must be set to
2171 \l {QImage::Format}{Format_ARGB32_Premultiplied} or
2172 \l {QImage::Format}{Format_ARGB32} for the composition modes to have
2173 any effect. For performance the premultiplied version is the preferred
2176 When a composition mode is set it applies to all painting
2177 operator, pens, brushes, gradients and pixmap/image drawing.
2179 \value CompositionMode_SourceOver This is the default mode. The
2180 alpha of the source is used to blend the pixel on top of the
2183 \value CompositionMode_DestinationOver The alpha of the
2184 destination is used to blend it on top of the source pixels. This
2185 mode is the inverse of CompositionMode_SourceOver.
2187 \value CompositionMode_Clear The pixels in the destination are
2188 cleared (set to fully transparent) independent of the source.
2190 \value CompositionMode_Source The output is the source
2191 pixel. (This means a basic copy operation and is identical to
2192 SourceOver when the source pixel is opaque).
2194 \value CompositionMode_Destination The output is the destination
2195 pixel. This means that the blending has no effect. This mode is
2196 the inverse of CompositionMode_Source.
2198 \value CompositionMode_SourceIn The output is the source, where
2199 the alpha is reduced by that of the destination.
2201 \value CompositionMode_DestinationIn The output is the
2202 destination, where the alpha is reduced by that of the
2203 source. This mode is the inverse of CompositionMode_SourceIn.
2205 \value CompositionMode_SourceOut The output is the source, where
2206 the alpha is reduced by the inverse of destination.
2208 \value CompositionMode_DestinationOut The output is the
2209 destination, where the alpha is reduced by the inverse of the
2210 source. This mode is the inverse of CompositionMode_SourceOut.
2212 \value CompositionMode_SourceAtop The source pixel is blended on
2213 top of the destination, with the alpha of the source pixel reduced
2214 by the alpha of the destination pixel.
2216 \value CompositionMode_DestinationAtop The destination pixel is
2217 blended on top of the source, with the alpha of the destination
2218 pixel is reduced by the alpha of the destination pixel. This mode
2219 is the inverse of CompositionMode_SourceAtop.
2221 \value CompositionMode_Xor The source, whose alpha is reduced with
2222 the inverse of the destination alpha, is merged with the
2223 destination, whose alpha is reduced by the inverse of the source
2224 alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2226 \value CompositionMode_Plus Both the alpha and color of the source
2227 and destination pixels are added together.
2229 \value CompositionMode_Multiply The output is the source color
2230 multiplied by the destination. Multiplying a color with white
2231 leaves the color unchanged, while multiplying a color
2232 with black produces black.
2234 \value CompositionMode_Screen The source and destination colors
2235 are inverted and then multiplied. Screening a color with white
2236 produces white, whereas screening a color with black leaves the
2239 \value CompositionMode_Overlay Multiplies or screens the colors
2240 depending on the destination color. The destination color is mixed
2241 with the source color to reflect the lightness or darkness of the
2244 \value CompositionMode_Darken The darker of the source and
2245 destination colors is selected.
2247 \value CompositionMode_Lighten The lighter of the source and
2248 destination colors is selected.
2250 \value CompositionMode_ColorDodge The destination color is
2251 brightened to reflect the source color. A black source color
2252 leaves the destination color unchanged.
2254 \value CompositionMode_ColorBurn The destination color is darkened
2255 to reflect the source color. A white source color leaves the
2256 destination color unchanged.
2258 \value CompositionMode_HardLight Multiplies or screens the colors
2259 depending on the source color. A light source color will lighten
2260 the destination color, whereas a dark source color will darken the
2263 \value CompositionMode_SoftLight Darkens or lightens the colors
2264 depending on the source color. Similar to
2265 CompositionMode_HardLight.
2267 \value CompositionMode_Difference Subtracts the darker of the
2268 colors from the lighter. Painting with white inverts the
2269 destination color, whereas painting with black leaves the
2270 destination color unchanged.
2272 \value CompositionMode_Exclusion Similar to
2273 CompositionMode_Difference, but with a lower contrast. Painting
2274 with white inverts the destination color, whereas painting with
2275 black leaves the destination color unchanged.
2277 \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2278 the source and destination pixels (src OR dst).
2280 \value RasterOp_SourceAndDestination Does a bitwise AND operation
2281 on the source and destination pixels (src AND dst).
2283 \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2284 on the source and destination pixels (src XOR dst).
2286 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2287 operation on the source and destination pixels ((NOT src) AND (NOT
2290 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2291 operation on the source and destination pixels ((NOT src) OR (NOT
2294 \value RasterOp_NotSourceXorDestination Does a bitwise operation
2295 where the source pixels are inverted and then XOR'ed with the
2296 destination ((NOT src) XOR dst).
2298 \value RasterOp_NotSource Does a bitwise operation where the
2299 source pixels are inverted (NOT src).
2301 \value RasterOp_NotSourceAndDestination Does a bitwise operation
2302 where the source is inverted and then AND'ed with the destination
2303 ((NOT src) AND dst).
2305 \value RasterOp_SourceAndNotDestination Does a bitwise operation
2306 where the source is AND'ed with the inverted destination pixels
2307 (src AND (NOT dst)).
2309 \value RasterOp_NotSourceOrDestination Does a bitwise operation
2310 where the source is inverted and then OR'ed with the destination
2313 \value RasterOp_ClearDestination The pixels in the destination are
2314 cleared (set to 0) independent of the source.
2316 \value RasterOp_SetDestination The pixels in the destination are
2317 set (set to 1) independent of the source.
2319 \value RasterOp_NotDestination Does a bitwise operation
2320 where the destination pixels are inverted (NOT dst).
2322 \value RasterOp_SourceOrNotDestination Does a bitwise operation
2323 where the source is OR'ed with the inverted destination pixels
2326 \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2327 Modes}{Composition Modes}, {Image Composition Example}
2331 Sets the composition mode to the given \a mode.
2333 \warning Only a QPainter operating on a QImage fully supports all
2334 composition modes. The RasterOp modes are supported for X11 as
2335 described in compositionMode().
2337 \sa compositionMode()
2339 void QPainter::setCompositionMode(CompositionMode mode)
2343 qWarning("QPainter::setCompositionMode: Painter not active");
2346 if (d->state->composition_mode == mode)
2349 d->state->composition_mode = mode;
2350 d->extended->compositionModeChanged();
2354 if (mode >= QPainter::RasterOp_SourceOrDestination) {
2355 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2356 qWarning("QPainter::setCompositionMode: "
2357 "Raster operation modes not supported on device");
2360 } else if (mode >= QPainter::CompositionMode_Plus) {
2361 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2362 qWarning("QPainter::setCompositionMode: "
2363 "Blend modes not supported on device");
2366 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2367 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2368 qWarning("QPainter::setCompositionMode: "
2369 "PorterDuff modes not supported on device");
2374 d->state->composition_mode = mode;
2375 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2379 Returns the current composition mode.
2381 \sa CompositionMode, setCompositionMode()
2383 QPainter::CompositionMode QPainter::compositionMode() const
2385 Q_D(const QPainter);
2387 qWarning("QPainter::compositionMode: Painter not active");
2388 return QPainter::CompositionMode_SourceOver;
2390 return d->state->composition_mode;
2394 Returns the current background brush.
2396 \sa setBackground(), {QPainter#Settings}{Settings}
2399 const QBrush &QPainter::background() const
2401 Q_D(const QPainter);
2403 qWarning("QPainter::background: Painter not active");
2404 return d->fakeState()->brush;
2406 return d->state->bgBrush;
2411 Returns true if clipping has been set; otherwise returns false.
2413 \sa setClipping(), {QPainter#Clipping}{Clipping}
2416 bool QPainter::hasClipping() const
2418 Q_D(const QPainter);
2420 qWarning("QPainter::hasClipping: Painter not active");
2423 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2428 Enables clipping if \a enable is true, or disables clipping if \a
2431 \sa hasClipping(), {QPainter#Clipping}{Clipping}
2434 void QPainter::setClipping(bool enable)
2437 #ifdef QT_DEBUG_DRAW
2438 if (qt_show_painter_debug_output)
2439 printf("QPainter::setClipping(), enable=%s, was=%s\n",
2440 enable ? "on" : "off",
2441 hasClipping() ? "on" : "off");
2444 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2448 if (hasClipping() == enable)
2451 // we can't enable clipping if we don't have a clip
2453 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2455 d->state->clipEnabled = enable;
2458 d->extended->clipEnabledChanged();
2462 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2463 d->updateState(d->state);
2468 Returns the currently set clip region. Note that the clip region
2469 is given in logical coordinates.
2471 \warning QPainter does not store the combined clip explicitly as
2472 this is handled by the underlying QPaintEngine, so the path is
2473 recreated on demand and transformed to the current logical
2474 coordinate system. This is potentially an expensive operation.
2476 \sa setClipRegion(), clipPath(), setClipping()
2479 QRegion QPainter::clipRegion() const
2481 Q_D(const QPainter);
2483 qWarning("QPainter::clipRegion: Painter not active");
2488 bool lastWasNothing = true;
2491 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2493 // ### Falcon: Use QPainterPath
2494 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2495 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2496 switch (info.clipType) {
2498 case QPainterClipInfo::RegionClip: {
2499 QTransform matrix = (info.matrix * d->invMatrix);
2500 if (lastWasNothing) {
2501 region = info.region * matrix;
2502 lastWasNothing = false;
2505 if (info.operation == Qt::IntersectClip)
2506 region &= info.region * matrix;
2507 else if (info.operation == Qt::NoClip) {
2508 lastWasNothing = true;
2511 region = info.region * matrix;
2515 case QPainterClipInfo::PathClip: {
2516 QTransform matrix = (info.matrix * d->invMatrix);
2517 if (lastWasNothing) {
2518 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2519 info.path.fillRule());
2520 lastWasNothing = false;
2523 if (info.operation == Qt::IntersectClip) {
2524 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2525 info.path.fillRule());
2526 } else if (info.operation == Qt::NoClip) {
2527 lastWasNothing = true;
2530 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2531 info.path.fillRule());
2536 case QPainterClipInfo::RectClip: {
2537 QTransform matrix = (info.matrix * d->invMatrix);
2538 if (lastWasNothing) {
2539 region = QRegion(info.rect) * matrix;
2540 lastWasNothing = false;
2543 if (info.operation == Qt::IntersectClip) {
2544 // Use rect intersection if possible.
2545 if (matrix.type() <= QTransform::TxScale)
2546 region &= matrix.mapRect(info.rect);
2548 region &= matrix.map(QRegion(info.rect));
2549 } else if (info.operation == Qt::NoClip) {
2550 lastWasNothing = true;
2553 region = QRegion(info.rect) * matrix;
2558 case QPainterClipInfo::RectFClip: {
2559 QTransform matrix = (info.matrix * d->invMatrix);
2560 if (lastWasNothing) {
2561 region = QRegion(info.rectf.toRect()) * matrix;
2562 lastWasNothing = false;
2565 if (info.operation == Qt::IntersectClip) {
2566 // Use rect intersection if possible.
2567 if (matrix.type() <= QTransform::TxScale)
2568 region &= matrix.mapRect(info.rectf.toRect());
2570 region &= matrix.map(QRegion(info.rectf.toRect()));
2571 } else if (info.operation == Qt::NoClip) {
2572 lastWasNothing = true;
2575 region = QRegion(info.rectf.toRect()) * matrix;
2585 extern QPainterPath qt_regionToPath(const QRegion ®ion);
2588 Returns the currently clip as a path. Note that the clip path is
2589 given in logical coordinates.
2591 \warning QPainter does not store the combined clip explicitly as
2592 this is handled by the underlying QPaintEngine, so the path is
2593 recreated on demand and transformed to the current logical
2594 coordinate system. This is potentially an expensive operation.
2596 \sa setClipPath(), clipRegion(), setClipping()
2598 QPainterPath QPainter::clipPath() const
2600 Q_D(const QPainter);
2602 // ### Since we do not support path intersections and path unions yet,
2603 // we just use clipRegion() here...
2605 qWarning("QPainter::clipPath: Painter not active");
2606 return QPainterPath();
2609 // No clip, return empty
2610 if (d->state->clipInfo.size() == 0) {
2611 return QPainterPath();
2614 // Update inverse matrix, used below.
2616 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2618 // For the simple case avoid conversion.
2619 if (d->state->clipInfo.size() == 1
2620 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2621 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2622 return d->state->clipInfo.at(0).path * matrix;
2624 } else if (d->state->clipInfo.size() == 1
2625 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2626 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2628 path.addRect(d->state->clipInfo.at(0).rect);
2629 return path * matrix;
2631 // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2632 return qt_regionToPath(clipRegion());
2638 Returns the bounding rectangle of the current clip if there is a clip;
2639 otherwise returns an empty rectangle. Note that the clip region is
2640 given in logical coordinates.
2642 The bounding rectangle is not guaranteed to be tight.
2644 \sa setClipRect(), setClipPath(), setClipRegion()
2649 QRectF QPainter::clipBoundingRect() const
2651 Q_D(const QPainter);
2654 qWarning("QPainter::clipBoundingRect: Painter not active");
2658 // Accumulate the bounding box in device space. This is not 100%
2659 // precise, but it fits within the guarantee and it is reasonably
2662 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2664 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2666 if (info.clipType == QPainterClipInfo::RectClip)
2668 else if (info.clipType == QPainterClipInfo::RectFClip)
2670 else if (info.clipType == QPainterClipInfo::RegionClip)
2671 r = info.region.boundingRect();
2673 r = info.path.boundingRect();
2675 r = info.matrix.mapRect(r);
2679 else if (info.operation == Qt::IntersectClip)
2684 // Map the rectangle back into logical space using the inverse
2687 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2689 return d->invMatrix.mapRect(bounds);
2693 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2695 Enables clipping, and sets the clip region to the given \a
2696 rectangle using the given clip \a operation. The default operation
2697 is to replace the current clip rectangle.
2699 Note that the clip rectangle is specified in logical (painter)
2702 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2704 void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2709 if ((!d->state->clipEnabled && op != Qt::NoClip))
2710 op = Qt::ReplaceClip;
2713 qWarning("QPainter::setClipRect: Painter not active");
2716 qreal right = rect.x() + rect.width();
2717 qreal bottom = rect.y() + rect.height();
2718 qreal pts[] = { rect.x(), rect.y(),
2722 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2723 d->state->clipEnabled = true;
2724 d->extended->clip(vp, op);
2725 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2726 d->state->clipInfo.clear();
2727 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2728 d->state->clipOperation = op;
2732 if (qreal(int(rect.top())) == rect.top()
2733 && qreal(int(rect.bottom())) == rect.bottom()
2734 && qreal(int(rect.left())) == rect.left()
2735 && qreal(int(rect.right())) == rect.right())
2737 setClipRect(rect.toRect(), op);
2741 if (rect.isEmpty()) {
2742 setClipRegion(QRegion(), op);
2748 setClipPath(path, op);
2752 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2755 Enables clipping, and sets the clip region to the given \a rectangle using the given
2758 void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2763 qWarning("QPainter::setClipRect: Painter not active");
2767 if ((!d->state->clipEnabled && op != Qt::NoClip))
2768 op = Qt::ReplaceClip;
2771 d->state->clipEnabled = true;
2772 d->extended->clip(rect, op);
2773 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2774 d->state->clipInfo.clear();
2775 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2776 d->state->clipOperation = op;
2780 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2781 op = Qt::ReplaceClip;
2783 d->state->clipRegion = rect;
2784 d->state->clipOperation = op;
2785 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2786 d->state->clipInfo.clear();
2787 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2788 d->state->clipEnabled = true;
2789 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2790 d->updateState(d->state);
2794 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2796 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2797 with the given \a width and \a height.
2801 \fn void QPainter::setClipRegion(const QRegion ®ion, Qt::ClipOperation operation)
2803 Sets the clip region to the given \a region using the specified clip
2804 \a operation. The default clip operation is to replace the current
2807 Note that the clip region is given in logical coordinates.
2809 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2811 void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2814 #ifdef QT_DEBUG_DRAW
2815 QRect rect = r.boundingRect();
2816 if (qt_show_painter_debug_output)
2817 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2818 r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2821 qWarning("QPainter::setClipRegion: Painter not active");
2825 if ((!d->state->clipEnabled && op != Qt::NoClip))
2826 op = Qt::ReplaceClip;
2829 d->state->clipEnabled = true;
2830 d->extended->clip(r, op);
2831 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2832 d->state->clipInfo.clear();
2833 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2834 d->state->clipOperation = op;
2838 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2839 op = Qt::ReplaceClip;
2841 d->state->clipRegion = r;
2842 d->state->clipOperation = op;
2843 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2844 d->state->clipInfo.clear();
2845 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2846 d->state->clipEnabled = true;
2847 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2848 d->updateState(d->state);
2855 Sets the transformation matrix to \a matrix and enables transformations.
2857 \note It is advisable to use setWorldTransform() instead of this function to
2858 preserve the properties of perspective transformations.
2860 If \a combine is true, then \a matrix is combined with the current
2861 transformation matrix; otherwise \a matrix replaces the current
2862 transformation matrix.
2864 If \a matrix is the identity matrix and \a combine is false, this
2865 function calls setWorldMatrixEnabled(false). (The identity matrix is the
2866 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2869 The following functions can transform the coordinate system without using
2878 They operate on the painter's worldMatrix() and are implemented like this:
2880 \snippet code/src_gui_painting_qpainter.cpp 4
2882 Note that when using setWorldMatrix() function you should always have
2883 \a combine be true when you are drawing into a QPicture. Otherwise
2884 it may not be possible to replay the picture with additional
2885 transformations; using the translate(), scale(), etc. convenience
2888 For more information about the coordinate system, transformations
2889 and window-viewport conversion, see \l {Coordinate System}.
2891 \sa setWorldTransform(), QTransform
2894 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2896 setWorldTransform(QTransform(matrix), combine);
2903 Returns the world transformation matrix.
2905 It is advisable to use worldTransform() because worldMatrix() does not
2906 preserve the properties of perspective transformations.
2908 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2912 const QMatrix &QPainter::worldMatrix() const
2914 Q_D(const QPainter);
2916 qWarning("QPainter::worldMatrix: Painter not active");
2917 return d->fakeState()->transform.toAffine();
2919 return d->state->worldMatrix.toAffine();
2925 Use setWorldTransform() instead.
2927 \sa setWorldTransform()
2930 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
2932 setWorldTransform(QTransform(matrix), combine);
2938 Use worldTransform() instead.
2940 \sa worldTransform()
2943 const QMatrix &QPainter::matrix() const
2945 return worldMatrix();
2953 Returns the transformation matrix combining the current
2954 window/viewport and world transformation.
2956 It is advisable to use combinedTransform() instead of this
2957 function to preserve the properties of perspective transformations.
2959 \sa setWorldTransform(), setWindow(), setViewport()
2961 QMatrix QPainter::combinedMatrix() const
2963 return combinedTransform().toAffine();
2970 Returns the matrix that transforms from logical coordinates to
2971 device coordinates of the platform dependent paint device.
2973 \note It is advisable to use deviceTransform() instead of this
2974 function to preserve the properties of perspective transformations.
2976 This function is \e only needed when using platform painting
2977 commands on the platform dependent handle (Qt::HANDLE), and the
2978 platform does not do transformations nativly.
2980 The QPaintEngine::PaintEngineFeature enum can be queried to
2981 determine whether the platform performs the transformations or
2984 \sa worldMatrix(), QPaintEngine::hasFeature(),
2986 const QMatrix &QPainter::deviceMatrix() const
2988 Q_D(const QPainter);
2990 qWarning("QPainter::deviceMatrix: Painter not active");
2991 return d->fakeState()->transform.toAffine();
2993 return d->state->matrix.toAffine();
2999 Resets any transformations that were made using translate(), scale(),
3000 shear(), rotate(), setWorldMatrix(), setViewport() and
3003 It is advisable to use resetTransform() instead of this function
3004 to preserve the properties of perspective transformations.
3006 \sa {QPainter#Coordinate Transformations}{Coordinate
3010 void QPainter::resetMatrix()
3019 Enables transformations if \a enable is true, or disables
3020 transformations if \a enable is false. The world transformation
3021 matrix is not changed.
3023 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3024 Transformations}{Coordinate Transformations}
3027 void QPainter::setWorldMatrixEnabled(bool enable)
3030 #ifdef QT_DEBUG_DRAW
3031 if (qt_show_painter_debug_output)
3032 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3036 qWarning("QPainter::setMatrixEnabled: Painter not active");
3039 if (enable == d->state->WxF)
3042 d->state->WxF = enable;
3049 Returns true if world transformation is enabled; otherwise returns
3052 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3055 bool QPainter::worldMatrixEnabled() const
3057 Q_D(const QPainter);
3059 qWarning("QPainter::worldMatrixEnabled: Painter not active");
3062 return d->state->WxF;
3068 Use setWorldMatrixEnabled() instead.
3070 \sa setWorldMatrixEnabled()
3073 void QPainter::setMatrixEnabled(bool enable)
3075 setWorldMatrixEnabled(enable);
3081 Use worldMatrixEnabled() instead
3083 \sa worldMatrixEnabled()
3086 bool QPainter::matrixEnabled() const
3088 return worldMatrixEnabled();
3092 Scales the coordinate system by (\a{sx}, \a{sy}).
3094 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3097 void QPainter::scale(qreal sx, qreal sy)
3099 #ifdef QT_DEBUG_DRAW
3100 if (qt_show_painter_debug_output)
3101 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3105 qWarning("QPainter::scale: Painter not active");
3109 d->state->worldMatrix.scale(sx,sy);
3110 d->state->WxF = true;
3115 Shears the coordinate system by (\a{sh}, \a{sv}).
3117 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3120 void QPainter::shear(qreal sh, qreal sv)
3122 #ifdef QT_DEBUG_DRAW
3123 if (qt_show_painter_debug_output)
3124 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3128 qWarning("QPainter::shear: Painter not active");
3132 d->state->worldMatrix.shear(sh, sv);
3133 d->state->WxF = true;
3138 \fn void QPainter::rotate(qreal angle)
3140 Rotates the coordinate system clockwise. The given \a angle parameter uses degree unit.
3142 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3145 void QPainter::rotate(qreal a)
3147 #ifdef QT_DEBUG_DRAW
3148 if (qt_show_painter_debug_output)
3149 printf("QPainter::rotate(), angle=%f\n", a);
3153 qWarning("QPainter::rotate: Painter not active");
3157 d->state->worldMatrix.rotate(a);
3158 d->state->WxF = true;
3163 Translates the coordinate system by the given \a offset; i.e. the
3164 given \a offset is added to points.
3166 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3168 void QPainter::translate(const QPointF &offset)
3170 qreal dx = offset.x();
3171 qreal dy = offset.y();
3172 #ifdef QT_DEBUG_DRAW
3173 if (qt_show_painter_debug_output)
3174 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3178 qWarning("QPainter::translate: Painter not active");
3182 d->state->worldMatrix.translate(dx, dy);
3183 d->state->WxF = true;
3188 \fn void QPainter::translate(const QPoint &offset)
3191 Translates the coordinate system by the given \a offset.
3195 \fn void QPainter::translate(qreal dx, qreal dy)
3198 Translates the coordinate system by the vector (\a dx, \a dy).
3202 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3204 Enables clipping, and sets the clip path for the painter to the
3205 given \a path, with the clip \a operation.
3207 Note that the clip path is specified in logical (painter)
3210 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3213 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3215 #ifdef QT_DEBUG_DRAW
3216 if (qt_show_painter_debug_output) {
3217 QRectF b = path.boundingRect();
3218 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3219 path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3225 qWarning("QPainter::setClipPath: Painter not active");
3229 if ((!d->state->clipEnabled && op != Qt::NoClip))
3230 op = Qt::ReplaceClip;
3233 d->state->clipEnabled = true;
3234 d->extended->clip(path, op);
3235 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3236 d->state->clipInfo.clear();
3237 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3238 d->state->clipOperation = op;
3242 if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
3243 op = Qt::ReplaceClip;
3245 d->state->clipPath = path;
3246 d->state->clipOperation = op;
3247 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3248 d->state->clipInfo.clear();
3249 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3250 d->state->clipEnabled = true;
3251 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3252 d->updateState(d->state);
3256 Draws the outline (strokes) the path \a path with the pen specified
3259 \sa fillPath(), {QPainter#Drawing}{Drawing}
3261 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3266 qWarning("QPainter::strokePath: Painter not active");
3274 const QGradient *g = qpen_brush(pen).gradient();
3275 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3276 d->extended->stroke(qtVectorPathForPath(path), pen);
3281 QBrush oldBrush = d->state->brush;
3282 QPen oldPen = d->state->pen;
3285 setBrush(Qt::NoBrush);
3295 Fills the given \a path using the given \a brush. The outline is
3298 Alternatively, you can specify a QColor instead of a QBrush; the
3299 QBrush constructor (taking a QColor argument) will automatically
3300 create a solid pattern brush.
3304 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3309 qWarning("QPainter::fillPath: Painter not active");
3317 const QGradient *g = brush.gradient();
3318 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3319 d->extended->fill(qtVectorPathForPath(path), brush);
3324 QBrush oldBrush = d->state->brush;
3325 QPen oldPen = d->state->pen;
3338 Draws the given painter \a path using the current pen for outline
3339 and the current brush for filling.
3343 \li \inlineimage qpainter-path.png
3345 \snippet code/src_gui_painting_qpainter.cpp 5
3348 \sa {painting/painterpaths}{the Painter Paths
3349 example},{painting/deform}{the Vector Deformation example}
3351 void QPainter::drawPath(const QPainterPath &path)
3353 #ifdef QT_DEBUG_DRAW
3354 QRectF pathBounds = path.boundingRect();
3355 if (qt_show_painter_debug_output)
3356 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3357 path.elementCount(),
3358 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3364 qWarning("QPainter::drawPath: Painter not active");
3369 d->extended->drawPath(path);
3372 d->updateState(d->state);
3374 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3375 d->engine->drawPath(path);
3377 d->draw_helper(path);
3382 \fn void QPainter::drawLine(const QLineF &line)
3384 Draws a line defined by \a line.
3388 \li \inlineimage qpainter-line.png
3390 \snippet code/src_gui_painting_qpainter.cpp 6
3393 \sa drawLines(), drawPolyline(), {Coordinate System}
3397 \fn void QPainter::drawLine(const QLine &line)
3400 Draws a line defined by \a line.
3404 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3407 Draws a line from \a p1 to \a p2.
3411 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3414 Draws a line from \a p1 to \a p2.
3418 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3421 Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3422 current pen position to (\a x2, \a y2).
3426 \fn void QPainter::drawRect(const QRectF &rectangle)
3428 Draws the current \a rectangle with the current pen and brush.
3430 A filled rectangle has a size of \a{rectangle}.size(). A stroked
3431 rectangle has a size of \a{rectangle}.size() plus the pen width.
3435 \li \inlineimage qpainter-rectangle.png
3437 \snippet code/src_gui_painting_qpainter.cpp 7
3440 \sa drawRects(), drawPolygon(), {Coordinate System}
3444 \fn void QPainter::drawRect(const QRect &rectangle)
3448 Draws the current \a rectangle with the current pen and brush.
3452 \fn void QPainter::drawRect(int x, int y, int width, int height)
3456 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3457 with the given \a width and \a height.
3461 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3463 Draws the first \a rectCount of the given \a rectangles using the
3464 current pen and brush.
3468 void QPainter::drawRects(const QRectF *rects, int rectCount)
3470 #ifdef QT_DEBUG_DRAW
3471 if (qt_show_painter_debug_output)
3472 printf("QPainter::drawRects(), count=%d\n", rectCount);
3477 qWarning("QPainter::drawRects: Painter not active");
3485 d->extended->drawRects(rects, rectCount);
3489 d->updateState(d->state);
3491 if (!d->state->emulationSpecifier) {
3492 d->engine->drawRects(rects, rectCount);
3496 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3497 && d->state->matrix.type() == QTransform::TxTranslate) {
3498 for (int i=0; i<rectCount; ++i) {
3499 QRectF r(rects[i].x() + d->state->matrix.dx(),
3500 rects[i].y() + d->state->matrix.dy(),
3503 d->engine->drawRects(&r, 1);
3506 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3507 for (int i=0; i<rectCount; ++i) {
3508 QPainterPath rectPath;
3509 rectPath.addRect(rects[i]);
3510 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3513 QPainterPath rectPath;
3514 for (int i=0; i<rectCount; ++i)
3515 rectPath.addRect(rects[i]);
3516 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3522 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3525 Draws the first \a rectCount of the given \a rectangles using the
3526 current pen and brush.
3528 void QPainter::drawRects(const QRect *rects, int rectCount)
3530 #ifdef QT_DEBUG_DRAW
3531 if (qt_show_painter_debug_output)
3532 printf("QPainter::drawRects(), count=%d\n", rectCount);
3537 qWarning("QPainter::drawRects: Painter not active");
3545 d->extended->drawRects(rects, rectCount);
3549 d->updateState(d->state);
3551 if (!d->state->emulationSpecifier) {
3552 d->engine->drawRects(rects, rectCount);
3556 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3557 && d->state->matrix.type() == QTransform::TxTranslate) {
3558 for (int i=0; i<rectCount; ++i) {
3559 QRectF r(rects[i].x() + d->state->matrix.dx(),
3560 rects[i].y() + d->state->matrix.dy(),
3564 d->engine->drawRects(&r, 1);
3567 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3568 for (int i=0; i<rectCount; ++i) {
3569 QPainterPath rectPath;
3570 rectPath.addRect(rects[i]);
3571 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3574 QPainterPath rectPath;
3575 for (int i=0; i<rectCount; ++i)
3576 rectPath.addRect(rects[i]);
3578 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3584 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3587 Draws the given \a rectangles using the current pen and brush.
3591 \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3595 Draws the given \a rectangles using the current pen and brush.
3599 \fn void QPainter::drawPoint(const QPointF &position)
3601 Draws a single point at the given \a position using the current
3604 \sa {Coordinate System}
3608 \fn void QPainter::drawPoint(const QPoint &position)
3611 Draws a single point at the given \a position using the current
3615 /*! \fn void QPainter::drawPoint(int x, int y)
3619 Draws a single point at position (\a x, \a y).
3623 Draws the first \a pointCount points in the array \a points using
3624 the current pen's color.
3626 \sa {Coordinate System}
3628 void QPainter::drawPoints(const QPointF *points, int pointCount)
3630 #ifdef QT_DEBUG_DRAW
3631 if (qt_show_painter_debug_output)
3632 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3637 qWarning("QPainter::drawPoints: Painter not active");
3641 if (pointCount <= 0)
3645 d->extended->drawPoints(points, pointCount);
3649 d->updateState(d->state);
3651 if (!d->state->emulationSpecifier) {
3652 d->engine->drawPoints(points, pointCount);
3656 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3657 && d->state->matrix.type() == QTransform::TxTranslate) {
3658 // ### use drawPoints function
3659 for (int i=0; i<pointCount; ++i) {
3660 QPointF pt(points[i].x() + d->state->matrix.dx(),
3661 points[i].y() + d->state->matrix.dy());
3662 d->engine->drawPoints(&pt, 1);
3665 QPen pen = d->state->pen;
3666 bool flat_pen = pen.capStyle() == Qt::FlatCap;
3669 pen.setCapStyle(Qt::SquareCap);
3673 for (int i=0; i<pointCount; ++i) {
3674 path.moveTo(points[i].x(), points[i].y());
3675 path.lineTo(points[i].x() + 0.0001, points[i].y());
3677 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3686 Draws the first \a pointCount points in the array \a points using
3687 the current pen's color.
3690 void QPainter::drawPoints(const QPoint *points, int pointCount)
3692 #ifdef QT_DEBUG_DRAW
3693 if (qt_show_painter_debug_output)
3694 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3699 qWarning("QPainter::drawPoints: Painter not active");
3703 if (pointCount <= 0)
3707 d->extended->drawPoints(points, pointCount);
3711 d->updateState(d->state);
3713 if (!d->state->emulationSpecifier) {
3714 d->engine->drawPoints(points, pointCount);
3718 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3719 && d->state->matrix.type() == QTransform::TxTranslate) {
3720 // ### use drawPoints function
3721 for (int i=0; i<pointCount; ++i) {
3722 QPointF pt(points[i].x() + d->state->matrix.dx(),
3723 points[i].y() + d->state->matrix.dy());
3724 d->engine->drawPoints(&pt, 1);
3727 QPen pen = d->state->pen;
3728 bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3731 pen.setCapStyle(Qt::SquareCap);
3735 for (int i=0; i<pointCount; ++i) {
3736 path.moveTo(points[i].x(), points[i].y());
3737 path.lineTo(points[i].x() + 0.0001, points[i].y());
3739 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3746 \fn void QPainter::drawPoints(const QPolygonF &points)
3750 Draws the points in the vector \a points.
3754 \fn void QPainter::drawPoints(const QPolygon &points)
3758 Draws the points in the vector \a points.
3762 Sets the background mode of the painter to the given \a mode
3764 Qt::TransparentMode (the default) draws stippled lines and text
3765 without setting the background pixels. Qt::OpaqueMode fills these
3766 space with the current background color.
3768 Note that in order to draw a bitmap or pixmap transparently, you
3769 must use QPixmap::setMask().
3771 \sa backgroundMode(), setBackground(),
3772 {QPainter#Settings}{Settings}
3775 void QPainter::setBackgroundMode(Qt::BGMode mode)
3777 #ifdef QT_DEBUG_DRAW
3778 if (qt_show_painter_debug_output)
3779 printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3784 qWarning("QPainter::setBackgroundMode: Painter not active");
3787 if (d->state->bgMode == mode)
3790 d->state->bgMode = mode;
3792 d->checkEmulation();
3794 d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3799 Returns the current background mode.
3801 \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3803 Qt::BGMode QPainter::backgroundMode() const
3805 Q_D(const QPainter);
3807 qWarning("QPainter::backgroundMode: Painter not active");
3808 return Qt::TransparentMode;
3810 return d->state->bgMode;
3817 Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3821 void QPainter::setPen(const QColor &color)
3823 #ifdef QT_DEBUG_DRAW
3824 if (qt_show_painter_debug_output)
3825 printf("QPainter::setPen(), color=%04x\n", color.rgb());
3829 qWarning("QPainter::setPen: Painter not active");
3833 QPen pen(color.isValid() ? color : QColor(Qt::black));
3835 if (d->state->pen == pen)
3838 d->state->pen = pen;
3840 d->extended->penChanged();
3842 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3846 Sets the painter's pen to be the given \a pen.
3848 The \a pen defines how to draw lines and outlines, and it also
3849 defines the text color.
3851 \sa pen(), {QPainter#Settings}{Settings}
3854 void QPainter::setPen(const QPen &pen)
3857 #ifdef QT_DEBUG_DRAW
3858 if (qt_show_painter_debug_output)
3859 printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3860 pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3864 qWarning("QPainter::setPen: Painter not active");
3868 if (d->state->pen == pen)
3871 d->state->pen = pen;
3874 d->checkEmulation();
3875 d->extended->penChanged();
3879 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3885 Sets the painter's pen to have the given \a style, width 1 and
3889 void QPainter::setPen(Qt::PenStyle style)
3893 qWarning("QPainter::setPen: Painter not active");
3897 QPen pen = QPen(style);
3899 if (d->state->pen == pen)
3902 d->state->pen = pen;
3905 d->extended->penChanged();
3907 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3912 Returns the painter's current pen.
3914 \sa setPen(), {QPainter#Settings}{Settings}
3917 const QPen &QPainter::pen() const
3919 Q_D(const QPainter);
3921 qWarning("QPainter::pen: Painter not active");
3922 return d->fakeState()->pen;
3924 return d->state->pen;
3929 Sets the painter's brush to the given \a brush.
3931 The painter's brush defines how shapes are filled.
3933 \sa brush(), {QPainter#Settings}{Settings}
3936 void QPainter::setBrush(const QBrush &brush)
3938 #ifdef QT_DEBUG_DRAW
3939 if (qt_show_painter_debug_output)
3940 printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
3944 qWarning("QPainter::setBrush: Painter not active");
3948 if (d->state->brush.d == brush.d)
3952 d->state->brush = brush;
3953 d->checkEmulation();
3954 d->extended->brushChanged();
3958 d->state->brush = brush;
3959 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
3966 Sets the painter's brush to black color and the specified \a
3970 void QPainter::setBrush(Qt::BrushStyle style)
3974 qWarning("QPainter::setBrush: Painter not active");
3977 if (d->state->brush.style() == style &&
3978 (style == Qt::NoBrush
3979 || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
3981 d->state->brush = QBrush(Qt::black, style);
3983 d->extended->brushChanged();
3985 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
3989 Returns the painter's current brush.
3991 \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
3994 const QBrush &QPainter::brush() const
3996 Q_D(const QPainter);
3998 qWarning("QPainter::brush: Painter not active");
3999 return d->fakeState()->brush;
4001 return d->state->brush;
4005 \fn void QPainter::setBackground(const QBrush &brush)
4007 Sets the background brush of the painter to the given \a brush.
4009 The background brush is the brush that is filled in when drawing
4010 opaque text, stippled lines and bitmaps. The background brush has
4011 no effect in transparent background mode (which is the default).
4013 \sa background(), setBackgroundMode(),
4014 {QPainter#Settings}{Settings}
4017 void QPainter::setBackground(const QBrush &bg)
4019 #ifdef QT_DEBUG_DRAW
4020 if (qt_show_painter_debug_output)
4021 printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4026 qWarning("QPainter::setBackground: Painter not active");
4029 d->state->bgBrush = bg;
4031 d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4035 Sets the painter's font to the given \a font.
4037 This font is used by subsequent drawText() functions. The text
4038 color is the same as the pen color.
4040 If you set a font that isn't available, Qt finds a close match.
4041 font() will return what you set using setFont() and fontInfo() returns the
4042 font actually being used (which may be the same).
4044 \sa font(), drawText(), {QPainter#Settings}{Settings}
4047 void QPainter::setFont(const QFont &font)
4051 #ifdef QT_DEBUG_DRAW
4052 if (qt_show_painter_debug_output)
4053 printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4057 qWarning("QPainter::setFont: Painter not active");
4061 d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4063 d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4067 Returns the currently set font used for drawing text.
4069 \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4071 const QFont &QPainter::font() const
4073 Q_D(const QPainter);
4075 qWarning("QPainter::font: Painter not active");
4076 return d->fakeState()->font;
4078 return d->state->font;
4084 Draws the given rectangle \a rect with rounded corners.
4086 The \a xRadius and \a yRadius arguments specify the radii
4087 of the ellipses defining the corners of the rounded rectangle.
4088 When \a mode is Qt::RelativeSize, \a xRadius and
4089 \a yRadius are specified in percentage of half the rectangle's
4090 width and height respectively, and should be in the range
4093 A filled rectangle has a size of rect.size(). A stroked rectangle
4094 has a size of rect.size() plus the pen width.
4098 \li \inlineimage qpainter-roundrect.png
4100 \snippet code/src_gui_painting_qpainter.cpp 8
4103 \sa drawRect(), QPen
4105 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4107 #ifdef QT_DEBUG_DRAW
4108 if (qt_show_painter_debug_output)
4109 printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4116 if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
4122 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4127 path.addRoundedRect(rect, xRadius, yRadius, mode);
4132 \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4133 Qt::SizeMode mode = Qt::AbsoluteSize);
4137 Draws the given rectangle \a rect with rounded corners.
4141 \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4142 Qt::SizeMode mode = Qt::AbsoluteSize);
4146 Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4152 Draws a rectangle \a r with rounded corners.
4154 The \a xRnd and \a yRnd arguments specify how rounded the corners
4155 should be. 0 is angled corners, 99 is maximum roundedness.
4157 A filled rectangle has a size of r.size(). A stroked rectangle
4158 has a size of r.size() plus the pen width.
4160 \sa drawRoundedRect()
4162 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4164 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4169 \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4174 Draws the rectangle \a r with rounded corners.
4180 \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4184 Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4188 \fn void QPainter::drawEllipse(const QRectF &rectangle)
4190 Draws the ellipse defined by the given \a rectangle.
4192 A filled ellipse has a size of \a{rectangle}.\l
4193 {QRect::size()}{size()}. A stroked ellipse has a size of
4194 \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4198 \li \inlineimage qpainter-ellipse.png
4200 \snippet code/src_gui_painting_qpainter.cpp 9
4203 \sa drawPie(), {Coordinate System}
4205 void QPainter::drawEllipse(const QRectF &r)
4207 #ifdef QT_DEBUG_DRAW
4208 if (qt_show_painter_debug_output)
4209 printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4216 QRectF rect(r.normalized());
4219 d->extended->drawEllipse(rect);
4223 d->updateState(d->state);
4224 if (d->state->emulationSpecifier) {
4225 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4226 && d->state->matrix.type() == QTransform::TxTranslate) {
4227 rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4230 path.addEllipse(rect);
4231 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4236 d->engine->drawEllipse(rect);
4240 \fn QPainter::drawEllipse(const QRect &rectangle)
4244 Draws the ellipse defined by the given \a rectangle.
4246 void QPainter::drawEllipse(const QRect &r)
4248 #ifdef QT_DEBUG_DRAW
4249 if (qt_show_painter_debug_output)
4250 printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4257 QRect rect(r.normalized());
4260 d->extended->drawEllipse(rect);
4264 d->updateState(d->state);
4266 if (d->state->emulationSpecifier) {
4267 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4268 && d->state->matrix.type() == QTransform::TxTranslate) {
4269 rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4272 path.addEllipse(rect);
4273 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4278 d->engine->drawEllipse(rect);
4282 \fn QPainter::drawEllipse(int x, int y, int width, int height)
4286 Draws the ellipse defined by the rectangle beginning at (\a{x},
4287 \a{y}) with the given \a width and \a height.
4293 \fn QPainter::drawEllipse(const QPointF ¢er, qreal rx, qreal ry)
4297 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4303 \fn QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)
4307 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4311 \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4313 Draws the arc defined by the given \a rectangle, \a startAngle and
4316 The \a startAngle and \a spanAngle must be specified in 1/16th of
4317 a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4318 values for the angles mean counter-clockwise while negative values
4319 mean the clockwise direction. Zero degrees is at the 3 o'clock
4324 \li \inlineimage qpainter-arc.png
4326 \snippet code/src_gui_painting_qpainter.cpp 10
4329 \sa drawPie(), drawChord(), {Coordinate System}
4332 void QPainter::drawArc(const QRectF &r, int a, int alen)
4334 #ifdef QT_DEBUG_DRAW
4335 if (qt_show_painter_debug_output)
4336 printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4337 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4344 QRectF rect = r.normalized();
4347 path.arcMoveTo(rect, a/16.0);
4348 path.arcTo(rect, a/16.0, alen/16.0);
4349 strokePath(path, d->state->pen);
4352 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4357 Draws the arc defined by the given \a rectangle, \a startAngle and
4362 \fn void QPainter::drawArc(int x, int y, int width, int height,
4363 int startAngle, int spanAngle)
4367 Draws the arc defined by the rectangle beginning at (\a x, \a y)
4368 with the specified \a width and \a height, and the given \a
4369 startAngle and \a spanAngle.
4373 \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4375 Draws a pie defined by the given \a rectangle, \a startAngle and \a spanAngle.
4377 The pie is filled with the current brush().
4379 The startAngle and spanAngle must be specified in 1/16th of a
4380 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4381 for the angles mean counter-clockwise while negative values mean
4382 the clockwise direction. Zero degrees is at the 3 o'clock
4387 \li \inlineimage qpainter-pie.png
4389 \snippet code/src_gui_painting_qpainter.cpp 11
4392 \sa drawEllipse(), drawChord(), {Coordinate System}
4394 void QPainter::drawPie(const QRectF &r, int a, int alen)
4396 #ifdef QT_DEBUG_DRAW
4397 if (qt_show_painter_debug_output)
4398 printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4399 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4410 if (a < 0) a += (360*16);
4413 QRectF rect = r.normalized();
4416 path.moveTo(rect.center());
4417 path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4418 path.closeSubpath();
4424 \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4427 Draws a pie defined by the given \a rectangle, \a startAngle and
4432 \fn void QPainter::drawPie(int x, int y, int width, int height, int
4433 startAngle, int spanAngle)
4437 Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4438 the specified \a width and \a height, and the given \a startAngle and
4443 \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4445 Draws the chord defined by the given \a rectangle, \a startAngle and
4446 \a spanAngle. The chord is filled with the current brush().
4448 The startAngle and spanAngle must be specified in 1/16th of a
4449 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4450 for the angles mean counter-clockwise while negative values mean
4451 the clockwise direction. Zero degrees is at the 3 o'clock
4456 \li \inlineimage qpainter-chord.png
4458 \snippet code/src_gui_painting_qpainter.cpp 12
4461 \sa drawArc(), drawPie(), {Coordinate System}
4463 void QPainter::drawChord(const QRectF &r, int a, int alen)
4465 #ifdef QT_DEBUG_DRAW
4466 if (qt_show_painter_debug_output)
4467 printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4468 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4475 QRectF rect = r.normalized();
4478 path.arcMoveTo(rect, a/16.0);
4479 path.arcTo(rect, a/16.0, alen/16.0);
4480 path.closeSubpath();
4484 \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4488 Draws the chord defined by the given \a rectangle, \a startAngle and
4493 \fn void QPainter::drawChord(int x, int y, int width, int height, int
4494 startAngle, int spanAngle)
4498 Draws the chord defined by the rectangle beginning at (\a x, \a y)
4499 with the specified \a width and \a height, and the given \a
4500 startAngle and \a spanAngle.
4505 Draws the first \a lineCount lines in the array \a lines
4506 using the current pen.
4508 \sa drawLine(), drawPolyline()
4510 void QPainter::drawLines(const QLineF *lines, int lineCount)
4512 #ifdef QT_DEBUG_DRAW
4513 if (qt_show_painter_debug_output)
4514 printf("QPainter::drawLines(), line count=%d\n", lineCount);
4519 if (!d->engine || lineCount < 1)
4523 d->extended->drawLines(lines, lineCount);
4527 d->updateState(d->state);
4529 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4531 if (lineEmulation) {
4532 if (lineEmulation == QPaintEngine::PrimitiveTransform
4533 && d->state->matrix.type() == QTransform::TxTranslate) {
4534 for (int i = 0; i < lineCount; ++i) {
4535 QLineF line = lines[i];
4536 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4537 d->engine->drawLines(&line, 1);
4540 QPainterPath linePath;
4541 for (int i = 0; i < lineCount; ++i) {
4542 linePath.moveTo(lines[i].p1());
4543 linePath.lineTo(lines[i].p2());
4545 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4549 d->engine->drawLines(lines, lineCount);
4553 \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4556 Draws the first \a lineCount lines in the array \a lines
4557 using the current pen.
4559 void QPainter::drawLines(const QLine *lines, int lineCount)
4561 #ifdef QT_DEBUG_DRAW
4562 if (qt_show_painter_debug_output)
4563 printf("QPainter::drawLine(), line count=%d\n", lineCount);
4568 if (!d->engine || lineCount < 1)
4572 d->extended->drawLines(lines, lineCount);
4576 d->updateState(d->state);
4578 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4580 if (lineEmulation) {
4581 if (lineEmulation == QPaintEngine::PrimitiveTransform
4582 && d->state->matrix.type() == QTransform::TxTranslate) {
4583 for (int i = 0; i < lineCount; ++i) {
4584 QLineF line = lines[i];
4585 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4586 d->engine->drawLines(&line, 1);
4589 QPainterPath linePath;
4590 for (int i = 0; i < lineCount; ++i) {
4591 linePath.moveTo(lines[i].p1());
4592 linePath.lineTo(lines[i].p2());
4594 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4598 d->engine->drawLines(lines, lineCount);
4604 Draws the first \a lineCount lines in the array \a pointPairs
4605 using the current pen. The lines are specified as pairs of points
4606 so the number of entries in \a pointPairs must be at least \a
4609 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4611 Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4613 drawLines((QLineF*)pointPairs, lineCount);
4619 Draws the first \a lineCount lines in the array \a pointPairs
4620 using the current pen.
4622 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4624 Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4626 drawLines((QLine*)pointPairs, lineCount);
4631 \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4634 Draws a line for each pair of points in the vector \a pointPairs
4635 using the current pen. If there is an odd number of points in the
4636 array, the last point will be ignored.
4640 \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4643 Draws a line for each pair of points in the vector \a pointPairs
4644 using the current pen.
4648 \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4651 Draws the set of lines defined by the list \a lines using the
4652 current pen and brush.
4656 \fn void QPainter::drawLines(const QVector<QLine> &lines)
4659 Draws the set of lines defined by the list \a lines using the
4660 current pen and brush.
4664 Draws the polyline defined by the first \a pointCount points in \a
4665 points using the current pen.
4667 Note that unlike the drawPolygon() function the last point is \e
4668 not connected to the first, neither is the polyline filled.
4673 \snippet code/src_gui_painting_qpainter.cpp 13
4676 \sa drawLines(), drawPolygon(), {Coordinate System}
4678 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4680 #ifdef QT_DEBUG_DRAW
4681 if (qt_show_painter_debug_output)
4682 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4686 if (!d->engine || pointCount < 2)
4690 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4694 d->updateState(d->state);
4696 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4698 if (lineEmulation) {
4700 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4701 // && d->state->matrix.type() == QTransform::TxTranslate) {
4703 QPainterPath polylinePath(points[0]);
4704 for (int i=1; i<pointCount; ++i)
4705 polylinePath.lineTo(points[i]);
4706 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4709 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4716 Draws the polyline defined by the first \a pointCount points in \a
4717 points using the current pen.
4719 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4721 #ifdef QT_DEBUG_DRAW
4722 if (qt_show_painter_debug_output)
4723 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4727 if (!d->engine || pointCount < 2)
4731 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4735 d->updateState(d->state);
4737 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4739 if (lineEmulation) {
4741 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4742 // && d->state->matrix.type() == QTransform::TxTranslate) {
4744 QPainterPath polylinePath(points[0]);
4745 for (int i=1; i<pointCount; ++i)
4746 polylinePath.lineTo(points[i]);
4747 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4750 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4755 \fn void QPainter::drawPolyline(const QPolygonF &points)
4759 Draws the polyline defined by the given \a points using the
4764 \fn void QPainter::drawPolyline(const QPolygon &points)
4768 Draws the polyline defined by the given \a points using the
4773 Draws the polygon defined by the first \a pointCount points in the
4774 array \a points using the current pen and brush.
4778 \li \inlineimage qpainter-polygon.png
4780 \snippet code/src_gui_painting_qpainter.cpp 14
4783 The first point is implicitly connected to the last point, and the
4784 polygon is filled with the current brush().
4786 If \a fillRule is Qt::WindingFill, the polygon is filled using the
4787 winding fill algorithm. If \a fillRule is Qt::OddEvenFill, the
4788 polygon is filled using the odd-even fill algorithm. See
4789 \l{Qt::FillRule} for a more detailed description of these fill
4792 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
4794 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
4796 #ifdef QT_DEBUG_DRAW
4797 if (qt_show_painter_debug_output)
4798 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4803 if (!d->engine || pointCount < 2)
4807 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4811 d->updateState(d->state);
4813 uint emulationSpecifier = d->state->emulationSpecifier;
4815 if (emulationSpecifier) {
4816 QPainterPath polygonPath(points[0]);
4817 for (int i=1; i<pointCount; ++i)
4818 polygonPath.lineTo(points[i]);
4819 polygonPath.closeSubpath();
4820 polygonPath.setFillRule(fillRule);
4821 d->draw_helper(polygonPath);
4825 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4830 Draws the polygon defined by the first \a pointCount points in the
4833 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
4835 #ifdef QT_DEBUG_DRAW
4836 if (qt_show_painter_debug_output)
4837 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4842 if (!d->engine || pointCount < 2)
4846 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4850 d->updateState(d->state);
4852 uint emulationSpecifier = d->state->emulationSpecifier;
4854 if (emulationSpecifier) {
4855 QPainterPath polygonPath(points[0]);
4856 for (int i=1; i<pointCount; ++i)
4857 polygonPath.lineTo(points[i]);
4858 polygonPath.closeSubpath();
4859 polygonPath.setFillRule(fillRule);
4860 d->draw_helper(polygonPath);
4864 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4867 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
4871 Draws the polygon defined by the given \a points using the fill
4875 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
4879 Draws the polygon defined by the given \a points using the fill
4884 \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4886 Draws the convex polygon defined by the first \a pointCount points
4887 in the array \a points using the current pen.
4891 \li \inlineimage qpainter-polygon.png
4893 \snippet code/src_gui_painting_qpainter.cpp 15
4896 The first point is implicitly connected to the last point, and the
4897 polygon is filled with the current brush(). If the supplied
4898 polygon is not convex, i.e. it contains at least one angle larger
4899 than 180 degrees, the results are undefined.
4901 On some platforms (e.g. X11), the drawConvexPolygon() function can
4902 be faster than the drawPolygon() function.
4904 \sa drawPolygon(), drawPolyline(), {Coordinate System}
4908 \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4911 Draws the convex polygon defined by the first \a pointCount points
4912 in the array \a points using the current pen.
4916 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
4920 Draws the convex polygon defined by \a polygon using the current
4925 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
4928 Draws the convex polygon defined by \a polygon using the current
4932 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4934 #ifdef QT_DEBUG_DRAW
4935 if (qt_show_painter_debug_output)
4936 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4941 if (!d->engine || pointCount < 2)
4945 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4949 d->updateState(d->state);
4951 uint emulationSpecifier = d->state->emulationSpecifier;
4953 if (emulationSpecifier) {
4954 QPainterPath polygonPath(points[0]);
4955 for (int i=1; i<pointCount; ++i)
4956 polygonPath.lineTo(points[i]);
4957 polygonPath.closeSubpath();
4958 polygonPath.setFillRule(Qt::WindingFill);
4959 d->draw_helper(polygonPath);
4963 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4966 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4968 #ifdef QT_DEBUG_DRAW
4969 if (qt_show_painter_debug_output)
4970 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4975 if (!d->engine || pointCount < 2)
4979 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4983 d->updateState(d->state);
4985 uint emulationSpecifier = d->state->emulationSpecifier;
4987 if (emulationSpecifier) {
4988 QPainterPath polygonPath(points[0]);
4989 for (int i=1; i<pointCount; ++i)
4990 polygonPath.lineTo(points[i]);
4991 polygonPath.closeSubpath();
4992 polygonPath.setFillRule(Qt::WindingFill);
4993 d->draw_helper(polygonPath);
4997 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5000 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5002 return m.inverted().map(QPointF(m.map(p).toPoint()));
5006 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5008 Draws the rectangular portion \a source of the given \a pixmap
5009 into the given \a target in the paint device.
5011 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5016 \snippet code/src_gui_painting_qpainter.cpp 16
5019 If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5020 using the pens color. If backgroundMode is Qt::OpaqueMode, the
5021 "unset" bits are drawn using the color of the background brush; if
5022 backgroundMode is Qt::TransparentMode, the "unset" bits are
5023 transparent. Drawing bitmaps with gradient or texture colors is
5028 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5030 #if defined QT_DEBUG_DRAW
5031 if (qt_show_painter_debug_output)
5032 printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5034 pm.width(), pm.height());
5039 if (!d->engine || pm.isNull())
5043 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5047 d->extended->drawPixmap(p, pm);
5055 int h = pm.height();
5060 // Emulate opaque background for bitmaps
5061 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5062 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5065 d->updateState(d->state);
5067 if ((d->state->matrix.type() > QTransform::TxTranslate
5068 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5069 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5070 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5073 // If there is no rotation involved we have to make sure we use the
5074 // antialiased and not the aliased coordinate system by rounding the coordinates.
5075 if (d->state->matrix.type() <= QTransform::TxScale) {
5076 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5081 setBackgroundMode(Qt::TransparentMode);
5082 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5083 QBrush brush(d->state->pen.color(), pm);
5086 setBrushOrigin(QPointF(0, 0));
5088 drawRect(pm.rect());
5091 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5092 x += d->state->matrix.dx();
5093 y += d->state->matrix.dy();
5095 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5099 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5101 #if defined QT_DEBUG_DRAW
5102 if (qt_show_painter_debug_output)
5103 printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5104 r.x(), r.y(), r.width(), r.height(),
5105 pm.width(), pm.height(),
5106 sr.x(), sr.y(), sr.width(), sr.height());
5110 if (!d->engine || pm.isNull())
5113 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5118 qreal w = r.width();
5119 qreal h = r.height();
5122 qreal sw = sr.width();
5123 qreal sh = sr.height();
5125 // Sanity-check clipping
5127 sw = pm.width() - sx;
5130 sh = pm.height() - sy;
5138 qreal w_ratio = sx * w/sw;
5146 qreal h_ratio = sy * h/sh;
5153 if (sw + sx > pm.width()) {
5154 qreal delta = sw - (pm.width() - sx);
5155 qreal w_ratio = delta * w/sw;
5160 if (sh + sy > pm.height()) {
5161 qreal delta = sh - (pm.height() - sy);
5162 qreal h_ratio = delta * h/sh;
5167 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5171 d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5175 // Emulate opaque background for bitmaps
5176 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5177 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5179 d->updateState(d->state);
5181 if ((d->state->matrix.type() > QTransform::TxTranslate
5182 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5183 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5184 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5185 || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5188 // If there is no rotation involved we have to make sure we use the
5189 // antialiased and not the aliased coordinate system by rounding the coordinates.
5190 if (d->state->matrix.type() <= QTransform::TxScale) {
5191 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5196 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5204 scale(w / sw, h / sh);
5205 setBackgroundMode(Qt::TransparentMode);
5206 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5209 if (sw == pm.width() && sh == pm.height())
5210 brush = QBrush(d->state->pen.color(), pm);
5212 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5217 drawRect(QRectF(0, 0, sw, sh));
5220 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5221 x += d->state->matrix.dx();
5222 y += d->state->matrix.dy();
5224 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5230 \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5231 const QRect &source)
5234 Draws the rectangular portion \a source of the given \a pixmap
5235 into the given \a target in the paint device.
5237 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5241 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5242 const QRectF &source)
5245 Draws the rectangular portion \a source of the given \a pixmap
5246 with its origin at the given \a point.
5250 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5251 const QRect &source)
5255 Draws the rectangular portion \a source of the given \a pixmap
5256 with its origin at the given \a point.
5260 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5263 Draws the given \a pixmap with its origin at the given \a point.
5267 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5270 Draws the given \a pixmap with its origin at the given \a point.
5274 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5278 Draws the given \a pixmap at position (\a{x}, \a{y}).
5282 \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5285 Draws the given \a pixmap into the given \a rectangle.
5287 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5291 \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5292 const QPixmap &pixmap)
5296 Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5297 with the given \a width and \a height.
5301 \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5302 int sx, int sy, int sw, int sh)
5306 Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5307 width \a sw and height \a sh, of the given \a pixmap , at the
5308 point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5309 If sw or sh are equal to zero the width/height of the pixmap
5310 is used and adjusted by the offset sx/sy;
5314 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5315 int sx, int sy, int sw, int sh)
5319 Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5320 pixmap into the paint device.
5322 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5323 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5324 pixmap that is to be drawn. The default is (0, 0).
5326 (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5327 The default, (0, 0) (and negative) means all the way to the
5328 bottom-right of the pixmap.
5331 void QPainter::drawImage(const QPointF &p, const QImage &image)
5335 if (!d->engine || image.isNull())
5339 d->extended->drawImage(p, image);
5346 int w = image.width();
5347 int h = image.height();
5349 d->updateState(d->state);
5351 if (((d->state->matrix.type() > QTransform::TxTranslate)
5352 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5353 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5354 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5357 // If there is no rotation involved we have to make sure we use the
5358 // antialiased and not the aliased coordinate system by rounding the coordinates.
5359 if (d->state->matrix.type() <= QTransform::TxScale) {
5360 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5365 setBackgroundMode(Qt::TransparentMode);
5366 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5367 QBrush brush(image);
5370 setBrushOrigin(QPointF(0, 0));
5372 drawRect(image.rect());
5377 if (d->state->matrix.type() == QTransform::TxTranslate
5378 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5379 x += d->state->matrix.dx();
5380 y += d->state->matrix.dy();
5383 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5386 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5387 Qt::ImageConversionFlags flags)
5391 if (!d->engine || image.isNull())
5394 qreal x = targetRect.x();
5395 qreal y = targetRect.y();
5396 qreal w = targetRect.width();
5397 qreal h = targetRect.height();
5398 qreal sx = sourceRect.x();
5399 qreal sy = sourceRect.y();
5400 qreal sw = sourceRect.width();
5401 qreal sh = sourceRect.height();
5403 // Sanity-check clipping
5405 sw = image.width() - sx;
5408 sh = image.height() - sy;
5416 qreal w_ratio = sx * w/sw;
5424 qreal h_ratio = sy * h/sh;
5431 if (sw + sx > image.width()) {
5432 qreal delta = sw - (image.width() - sx);
5433 qreal w_ratio = delta * w/sw;
5438 if (sh + sy > image.height()) {
5439 qreal delta = sh - (image.height() - sy);
5440 qreal h_ratio = delta * h/sh;
5445 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5449 d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5453 d->updateState(d->state);
5455 if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5456 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5457 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5458 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5461 // If there is no rotation involved we have to make sure we use the
5462 // antialiased and not the aliased coordinate system by rounding the coordinates.
5463 if (d->state->matrix.type() <= QTransform::TxScale) {
5464 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5469 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5476 scale(w / sw, h / sh);
5477 setBackgroundMode(Qt::TransparentMode);
5478 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5479 QBrush brush(image);
5482 setBrushOrigin(QPointF(-sx, -sy));
5484 drawRect(QRectF(0, 0, sw, sh));
5489 if (d->state->matrix.type() == QTransform::TxTranslate
5490 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5491 x += d->state->matrix.dx();
5492 y += d->state->matrix.dy();
5495 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5499 \fn void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphs)
5501 Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5502 edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5503 selected on \a glyphs and at offsets given by the positions in \a glyphs.
5507 \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes()
5509 #if !defined(QT_NO_RAWFONT)
5510 void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
5514 QRawFont font = glyphRun.rawFont();
5515 if (!font.isValid())
5518 QGlyphRunPrivate *glyphRun_d = QGlyphRunPrivate::get(glyphRun);
5520 const quint32 *glyphIndexes = glyphRun_d->glyphIndexData;
5521 const QPointF *glyphPositions = glyphRun_d->glyphPositionData;
5523 int count = qMin(glyphRun_d->glyphIndexDataSize, glyphRun_d->glyphPositionDataSize);
5524 QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5526 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5527 bool supportsTransformations = d->extended
5528 ? d->extended->supportsTransformations(fontD->fontEngine, d->state->matrix)
5529 : d->engine->type() == QPaintEngine::CoreGraphics || d->state->matrix.isAffine();
5531 for (int i=0; i<count; ++i) {
5532 QPointF processedPosition = position + glyphPositions[i];
5533 if (!supportsTransformations)
5534 processedPosition = d->state->transform().map(processedPosition);
5535 fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5538 d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, font, glyphRun.overline(),
5539 glyphRun.underline(), glyphRun.strikeOut());
5542 void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions,
5544 const QRawFont &font, bool overline, bool underline,
5551 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5552 QFontEngine *fontEngine = fontD->fontEngine;
5557 for (int i=0; i<glyphCount; ++i) {
5558 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5559 if (i == 0 || leftMost > positions[i].x)
5560 leftMost = positions[i].x;
5562 // We don't support glyphs that do not share a common baseline. If this turns out to
5563 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5564 // and do a drawTextItemDecorations call per cluster.
5565 if (i == 0 || baseLine < positions[i].y)
5566 baseLine = positions[i].y;
5568 // We use the advance rather than the actual bounds to match the algorithm in drawText()
5569 if (i == 0 || rightMost < positions[i].x + gm.xoff)
5570 rightMost = positions[i].x + gm.xoff;
5573 QFixed width = rightMost - leftMost;
5575 if (extended != 0 && state->matrix.isAffine()) {
5576 QStaticTextItem staticTextItem;
5577 staticTextItem.color = state->pen.color();
5578 staticTextItem.font = state->font;
5579 staticTextItem.setFontEngine(fontEngine);
5580 staticTextItem.numGlyphs = glyphCount;
5581 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5582 staticTextItem.glyphPositions = positions;
5584 extended->drawStaticTextItem(&staticTextItem);
5586 QTextItemInt textItem;
5587 textItem.fontEngine = fontEngine;
5589 QVarLengthArray<QFixed, 128> advances(glyphCount);
5590 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5591 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5592 memset(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5593 memset(advances.data(), 0, advances.size() * sizeof(QFixed));
5594 memset(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5596 textItem.glyphs.numGlyphs = glyphCount;
5597 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5598 textItem.glyphs.offsets = positions;
5599 textItem.glyphs.advances_x = advances.data();
5600 textItem.glyphs.advances_y = advances.data();
5601 textItem.glyphs.justifications = glyphJustifications.data();
5602 textItem.glyphs.attributes = glyphAttributes.data();
5604 engine->drawTextItem(QPointF(0, 0), textItem);
5607 QTextItemInt::RenderFlags flags;
5609 flags |= QTextItemInt::Underline;
5611 flags |= QTextItemInt::Overline;
5613 flags |= QTextItemInt::StrikeOut;
5615 drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5619 ? QTextCharFormat::SingleUnderline
5620 : QTextCharFormat::NoUnderline),
5621 flags, width.toReal(), QTextCharFormat());
5623 #endif // QT_NO_RAWFONT
5627 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5631 Draws the \a staticText at the \a topLeftPosition.
5633 \note The y-position is used as the top of the font.
5638 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5642 Draws the \a staticText at coordinates \a left and \a top.
5644 \note The y-position is used as the top of the font.
5648 \fn void QPainter::drawText(const QPointF &position, const QString &text)
5650 Draws the given \a text with the currently defined text direction,
5651 beginning at the given \a position.
5653 This function does not handle the newline character (\\n), as it cannot
5654 break text into multiple lines, and it cannot display the newline character.
5655 Use the QPainter::drawText() overload that takes a rectangle instead
5656 if you want to draw multiple lines of text with the newline character, or
5657 if you want the text to be wrapped.
5659 By default, QPainter draws text anti-aliased.
5661 \note The y-position is used as the baseline of the font.
5663 \sa setFont(), setPen()
5666 void QPainter::drawText(const QPointF &p, const QString &str)
5668 drawText(p, str, 0, 0);
5674 Draws the given \a staticText at the given \a topLeftPosition.
5676 The text will be drawn using the font and the transformation set on the painter. If the
5677 font and/or transformation set on the painter are different from the ones used to initialize
5678 the layout of the QStaticText, then the layout will have to be recalculated. Use
5679 QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5680 it will later be drawn.
5682 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5683 last drawn, then there will be a slight overhead when translating the text to its new position.
5685 \note If the painter's transformation is not affine, then \a staticText will be drawn using
5686 regular calls to drawText(), losing any potential for performance improvement.
5688 \note The y-position is used as the top of the font.
5692 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5695 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5698 QStaticTextPrivate *staticText_d =
5699 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5701 if (font() != staticText_d->font) {
5702 staticText_d->font = font();
5703 staticText_d->needsRelayout = true;
5706 // If we don't have an extended paint engine, or if the painter is projected,
5707 // we go through standard code path
5708 if (d->extended == 0 || !d->state->matrix.isAffine()) {
5709 staticText_d->paintText(topLeftPosition, this);
5713 QFontEngine *fe = staticText_d->font.d->engineForScript(QUnicodeTables::Common);
5714 if (fe->type() == QFontEngine::Multi)
5715 fe = static_cast<QFontEngineMulti *>(fe)->engine(0);
5716 bool supportsTransformations = d->extended->supportsTransformations(fe,
5718 if (supportsTransformations && !staticText_d->untransformedCoordinates) {
5719 staticText_d->untransformedCoordinates = true;
5720 staticText_d->needsRelayout = true;
5721 } else if (!supportsTransformations && staticText_d->untransformedCoordinates) {
5722 staticText_d->untransformedCoordinates = false;
5723 staticText_d->needsRelayout = true;
5726 // Don't recalculate entire layout because of translation, rather add the dx and dy
5727 // into the position to move each text item the correct distance.
5728 QPointF transformedPosition = topLeftPosition;
5729 if (!staticText_d->untransformedCoordinates)
5730 transformedPosition = transformedPosition * d->state->matrix;
5731 QTransform oldMatrix;
5733 // The translation has been applied to transformedPosition. Remove translation
5734 // component from matrix.
5735 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
5736 qreal m11 = d->state->matrix.m11();
5737 qreal m12 = d->state->matrix.m12();
5738 qreal m13 = d->state->matrix.m13();
5739 qreal m21 = d->state->matrix.m21();
5740 qreal m22 = d->state->matrix.m22();
5741 qreal m23 = d->state->matrix.m23();
5742 qreal m33 = d->state->matrix.m33();
5744 oldMatrix = d->state->matrix;
5745 d->state->matrix.setMatrix(m11, m12, m13,
5750 // If the transform is not identical to the text transform,
5751 // we have to relayout the text (for other transformations than plain translation)
5752 bool staticTextNeedsReinit = staticText_d->needsRelayout;
5753 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
5754 staticText_d->matrix = d->state->matrix;
5755 staticTextNeedsReinit = true;
5758 // Recreate the layout of the static text because the matrix or font has changed
5759 if (staticTextNeedsReinit)
5760 staticText_d->init();
5762 if (transformedPosition != staticText_d->position) { // Translate to actual position
5763 QFixed fx = QFixed::fromReal(transformedPosition.x());
5764 QFixed fy = QFixed::fromReal(transformedPosition.y());
5765 QFixed oldX = QFixed::fromReal(staticText_d->position.x());
5766 QFixed oldY = QFixed::fromReal(staticText_d->position.y());
5767 for (int item=0; item<staticText_d->itemCount;++item) {
5768 QStaticTextItem *textItem = staticText_d->items + item;
5769 for (int i=0; i<textItem->numGlyphs; ++i) {
5770 textItem->glyphPositions[i].x += fx - oldX;
5771 textItem->glyphPositions[i].y += fy - oldY;
5773 textItem->userDataNeedsUpdate = true;
5776 staticText_d->position = transformedPosition;
5779 QPen oldPen = d->state->pen;
5780 QColor currentColor = oldPen.color();
5781 for (int i=0; i<staticText_d->itemCount; ++i) {
5782 QStaticTextItem *item = staticText_d->items + i;
5783 if (item->color.isValid() && currentColor != item->color) {
5784 setPen(item->color);
5785 currentColor = item->color;
5787 d->extended->drawStaticTextItem(item);
5789 qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
5790 item->numGlyphs, item->fontEngine(), staticText_d->font,
5793 if (currentColor != oldPen.color())
5796 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
5797 d->state->matrix = oldMatrix;
5803 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
5805 #ifdef QT_DEBUG_DRAW
5806 if (qt_show_painter_debug_output)
5807 printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
5812 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
5815 if (tf & Qt::TextBypassShaping) {
5816 // Skip harfbuzz complex shaping, shape using glyph advances only
5817 int len = str.length();
5818 int numGlyphs = len;
5819 QVarLengthGlyphLayoutArray glyphs(len);
5820 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
5821 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
5822 glyphs.resize(numGlyphs);
5823 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
5824 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
5827 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
5828 drawTextItem(p, gf);
5832 QStackTextEngine engine(str, d->state->font);
5833 engine.option.setTextDirection(d->state->layoutDirection);
5834 if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
5835 engine.ignoreBidi = true;
5836 engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
5840 line.length = str.length();
5841 engine.shapeLine(line);
5843 int nItems = engine.layoutData->items.size();
5844 QVarLengthArray<int> visualOrder(nItems);
5845 QVarLengthArray<uchar> levels(nItems);
5846 for (int i = 0; i < nItems; ++i)
5847 levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
5848 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
5850 if (justificationPadding > 0) {
5851 engine.option.setAlignment(Qt::AlignJustify);
5852 engine.forceJustification = true;
5853 // this works because justify() is only interested in the difference between width and textWidth
5854 line.width = justificationPadding;
5855 engine.justify(line);
5857 QFixed x = QFixed::fromReal(p.x());
5859 for (int i = 0; i < nItems; ++i) {
5860 int item = visualOrder[i];
5861 const QScriptItem &si = engine.layoutData->items.at(item);
5862 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
5866 QFont f = engine.font(si);
5867 QTextItemInt gf(si, &f);
5868 gf.glyphs = engine.shapedGlyphs(&si);
5869 gf.chars = engine.layoutData->string.unicode() + si.position;
5870 gf.num_chars = engine.length(item);
5871 if (engine.forceJustification) {
5872 for (int j=0; j<gf.glyphs.numGlyphs; ++j)
5873 gf.width += gf.glyphs.effectiveAdvance(j);
5875 gf.width = si.width;
5877 gf.logClusters = engine.logClusters(&si);
5879 drawTextItem(QPointF(x.toReal(), p.y()), gf);
5885 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
5887 #ifdef QT_DEBUG_DRAW
5888 if (qt_show_painter_debug_output)
5889 printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
5890 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5895 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5899 d->updateState(d->state);
5902 qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
5904 *br = bounds.toAlignedRect();
5908 \fn void QPainter::drawText(const QPoint &position, const QString &text)
5912 Draws the given \a text with the currently defined text direction,
5913 beginning at the given \a position.
5915 By default, QPainter draws text anti-aliased.
5917 \note The y-position is used as the baseline of the font.
5919 \sa setFont(), setPen()
5923 \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
5926 Draws the given \a text within the provided \a rectangle.
5927 The \a rectangle along with alignment \a flags defines the anchors for the \a text.
5931 \li \inlineimage qpainter-text.png
5933 \snippet code/src_gui_painting_qpainter.cpp 17
5936 The \a boundingRect (if not null) is set to the what the bounding rectangle
5937 should be in order to enclose the whole text. The \a flags argument is a bitwise
5938 OR of the following flags:
5943 \li Qt::AlignHCenter
5944 \li Qt::AlignJustify
5947 \li Qt::AlignVCenter
5949 \li Qt::TextDontClip
5950 \li Qt::TextSingleLine
5951 \li Qt::TextExpandTabs
5952 \li Qt::TextShowMnemonic
5953 \li Qt::TextWordWrap
5954 \li Qt::TextIncludeTrailingSpaces
5957 \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
5959 By default, QPainter draws text anti-aliased.
5961 \note The y-coordinate of \a rectangle is used as the top of the font.
5963 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
5965 #ifdef QT_DEBUG_DRAW
5966 if (qt_show_painter_debug_output)
5967 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
5968 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5973 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5977 d->updateState(d->state);
5979 qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
5983 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
5986 Draws the given \a text within the provided \a rectangle according
5987 to the specified \a flags. The \a boundingRect (if not null) is set to
5988 the what the bounding rectangle should be in order to enclose the whole text.
5990 By default, QPainter draws text anti-aliased.
5992 \note The y-coordinate of \a rectangle is used as the top of the font.
5994 \sa setFont(), setPen()
5998 \fn void QPainter::drawText(int x, int y, const QString &text)
6002 Draws the given \a text at position (\a{x}, \a{y}), using the painter's
6003 currently defined text direction.
6005 By default, QPainter draws text anti-aliased.
6007 \note The y-position is used as the baseline of the font.
6009 \sa setFont(), setPen()
6013 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6014 const QString &text, QRect *boundingRect)
6018 Draws the given \a text within the rectangle with origin (\a{x},
6019 \a{y}), \a width and \a height.
6021 The \a boundingRect (if not null) is set to the actual bounding
6022 rectangle of the output. The \a flags argument is a bitwise OR of
6023 the following flags:
6028 \li Qt::AlignHCenter
6029 \li Qt::AlignJustify
6032 \li Qt::AlignVCenter
6034 \li Qt::TextSingleLine
6035 \li Qt::TextExpandTabs
6036 \li Qt::TextShowMnemonic
6037 \li Qt::TextWordWrap
6040 By default, QPainter draws text anti-aliased.
6042 \note The y-position is used as the top of the font.
6044 \sa Qt::AlignmentFlag, Qt::TextFlag, setFont(), setPen()
6048 \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6049 const QTextOption &option)
6052 Draws the given \a text in the \a rectangle specified using the \a option
6053 to control its positioning and orientation.
6055 By default, QPainter draws text anti-aliased.
6057 \note The y-coordinate of \a rectangle is used as the top of the font.
6059 \sa setFont(), setPen()
6061 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6063 #ifdef QT_DEBUG_DRAW
6064 if (qt_show_painter_debug_output)
6065 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6066 r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6071 if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6075 d->updateState(d->state);
6077 qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6081 \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6088 \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6093 Draws the text item \a ti at position \a p.
6097 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6102 Draws the text item \a ti at position \a p.
6104 This method ignores the painters background mode and
6105 color. drawText and qt_format_text have to do it themselves, as
6106 only they know the extents of the complete string.
6108 It ignores the font set on the painter as the text item has one of its own.
6110 The underline and strikeout parameters of the text items font are
6111 ignored aswell. You'll need to pass in the correct flags to get
6112 underlining and strikeout.
6115 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6117 const qreal radiusBase = qMax(qreal(1), maxRadius);
6119 QString key = QLatin1String("WaveUnderline-")
6120 % pen.color().name()
6121 % HexString<qreal>(radiusBase);
6124 if (QPixmapCache::find(key, pixmap))
6127 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6128 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6129 const int radius = qFloor(radiusBase);
6136 while (xs < width) {
6139 path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6142 pixmap = QPixmap(width, radius * 2);
6143 pixmap.fill(Qt::transparent);
6146 wavePen.setCapStyle(Qt::SquareCap);
6148 // This is to protect against making the line too fat, as happens on Mac OS X
6149 // due to it having a rather thick width for the regular underline.
6150 const qreal maxPenWidth = .8 * radius;
6151 if (wavePen.widthF() > maxPenWidth)
6152 wavePen.setWidth(maxPenWidth);
6154 QPainter imgPainter(&pixmap);
6155 imgPainter.setPen(wavePen);
6156 imgPainter.setRenderHint(QPainter::Antialiasing);
6157 imgPainter.translate(0, radius);
6158 imgPainter.drawPath(path);
6161 QPixmapCache::insert(key, pixmap);
6166 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
6167 QTextCharFormat::UnderlineStyle underlineStyle,
6168 QTextItem::RenderFlags flags, qreal width,
6169 const QTextCharFormat &charFormat)
6171 if (underlineStyle == QTextCharFormat::NoUnderline
6172 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6175 const QPen oldPen = painter->pen();
6176 const QBrush oldBrush = painter->brush();
6177 painter->setBrush(Qt::NoBrush);
6179 pen.setStyle(Qt::SolidLine);
6180 pen.setWidthF(fe->lineThickness().toReal());
6181 pen.setCapStyle(Qt::FlatCap);
6183 QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6185 const qreal underlineOffset = fe->underlinePosition().toReal();
6186 // deliberately ceil the offset to avoid the underline coming too close to
6187 // the text above it.
6188 const qreal underlinePos = pos.y() + qCeil(underlineOffset);
6190 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6191 QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
6193 underlineStyle = QTextCharFormat::UnderlineStyle(theme->themeHint(QPlatformTheme::SpellCheckUnderlineStyle).toInt());
6196 if (underlineStyle == QTextCharFormat::WaveUnderline) {
6198 painter->translate(0, pos.y() + 1);
6200 QColor uc = charFormat.underlineColor();
6204 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6205 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6206 const int descent = (int) fe->descent().toReal();
6208 painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6209 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6211 } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6212 QColor uc = charFormat.underlineColor();
6216 pen.setStyle((Qt::PenStyle)(underlineStyle));
6217 painter->setPen(pen);
6218 QLineF underline(line.x1(), underlinePos, line.x2(), underlinePos);
6220 textEngine->addUnderline(painter, underline);
6222 painter->drawLine(underline);
6225 pen.setStyle(Qt::SolidLine);
6226 pen.setColor(oldPen.color());
6228 if (flags & QTextItem::StrikeOut) {
6229 QLineF strikeOutLine = line;
6230 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6231 painter->setPen(pen);
6233 textEngine->addStrikeOut(painter, strikeOutLine);
6235 painter->drawLine(strikeOutLine);
6238 if (flags & QTextItem::Overline) {
6239 QLineF overline = line;
6240 overline.translate(0., - fe->ascent().toReal());
6241 painter->setPen(pen);
6243 textEngine->addOverline(painter, overline);
6245 painter->drawLine(overline);
6248 painter->setPen(oldPen);
6249 painter->setBrush(oldBrush);
6252 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6253 const QFixedPoint *positions, int glyphCount,
6254 QFontEngine *fontEngine, const QFont &font,
6255 const QTextCharFormat &charFormat)
6257 if (!(font.underline() || font.strikeOut() || font.overline()))
6263 for (int i=0; i<glyphCount; ++i) {
6264 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6265 if (i == 0 || leftMost > positions[i].x)
6266 leftMost = positions[i].x;
6268 // We don't support glyphs that do not share a common baseline. If this turns out to
6269 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6270 // and do a drawTextItemDecoration call per cluster.
6271 if (i == 0 || baseLine < positions[i].y)
6272 baseLine = positions[i].y;
6274 // We use the advance rather than the actual bounds to match the algorithm in drawText()
6275 if (i == 0 || rightMost < positions[i].x + gm.xoff)
6276 rightMost = positions[i].x + gm.xoff;
6279 QFixed width = rightMost - leftMost;
6280 QTextItem::RenderFlags flags = 0;
6282 if (font.underline())
6283 flags |= QTextItem::Underline;
6284 if (font.overline())
6285 flags |= QTextItem::Overline;
6286 if (font.strikeOut())
6287 flags |= QTextItem::StrikeOut;
6289 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6292 font.underline() ? QTextCharFormat::SingleUnderline
6293 : QTextCharFormat::NoUnderline, flags,
6294 width.toReal(), charFormat);
6297 void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6301 d->drawTextItem(p, ti, static_cast<QTextEngine *>(0));
6304 void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine)
6306 #ifdef QT_DEBUG_DRAW
6307 if (qt_show_painter_debug_output)
6308 printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6309 p.x(), p.y(), qPrintable(_ti.text()));
6318 qt_painter_thread_test(device->devType(),
6320 QFontDatabase::supportsThreadedFontRendering());
6323 QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6325 if (!extended && state->bgMode == Qt::OpaqueMode) {
6326 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6327 q->fillRect(rect, state->bgBrush);
6330 if (q->pen().style() == Qt::NoPen)
6333 const QPainter::RenderHints oldRenderHints = state->renderHints;
6334 if (!state->renderHints & QPainter::Antialiasing && state->matrix.type() >= QTransform::TxScale) {
6335 // draw antialias decoration (underline/overline/strikeout) with
6339 const QTransform &m = state->matrix;
6340 if (state->matrix.type() < QTransform::TxShear) {
6341 bool isPlain90DegreeRotation =
6342 (qFuzzyIsNull(m.m11())
6343 && qFuzzyIsNull(m.m12() - qreal(1))
6344 && qFuzzyIsNull(m.m21() + qreal(1))
6345 && qFuzzyIsNull(m.m22())
6348 (qFuzzyIsNull(m.m11() + qreal(1))
6349 && qFuzzyIsNull(m.m12())
6350 && qFuzzyIsNull(m.m21())
6351 && qFuzzyIsNull(m.m22() + qreal(1))
6354 (qFuzzyIsNull(m.m11())
6355 && qFuzzyIsNull(m.m12() + qreal(1))
6356 && qFuzzyIsNull(m.m21() - qreal(1))
6357 && qFuzzyIsNull(m.m22())
6360 aa = !isPlain90DegreeRotation;
6363 q->setRenderHint(QPainter::Antialiasing, true);
6369 if (!ti.glyphs.numGlyphs) {
6371 } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6372 QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6374 const QGlyphLayout &glyphs = ti.glyphs;
6375 int which = glyphs.glyphs[0] >> 24;
6380 bool rtl = ti.flags & QTextItem::RightToLeft;
6382 x += ti.width.toReal();
6386 for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6387 const int e = glyphs.glyphs[end] >> 24;
6392 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6394 // set the high byte to zero and calc the width
6395 for (i = start; i < end; ++i) {
6396 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6397 ti2.width += ti.glyphs.effectiveAdvance(i);
6401 x -= ti2.width.toReal();
6403 engine->drawTextItem(QPointF(x, y), ti2);
6406 x += ti2.width.toReal();
6408 // reset the high byte for all glyphs and advance to the next sub-string
6409 const int hi = which << 24;
6410 for (i = start; i < end; ++i) {
6411 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6419 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6421 // set the high byte to zero and calc the width
6422 for (i = start; i < end; ++i) {
6423 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6424 ti2.width += ti.glyphs.effectiveAdvance(i);
6428 x -= ti2.width.toReal();
6431 extended->drawTextItem(QPointF(x, y), ti2);
6433 engine->drawTextItem(QPointF(x,y), ti2);
6435 // reset the high byte for all glyphs
6436 const int hi = which << 24;
6437 for (i = start; i < end; ++i)
6438 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6442 extended->drawTextItem(p, ti);
6444 engine->drawTextItem(p, ti);
6446 drawTextItemDecoration(q, p, ti.fontEngine, textEngine, ti.underlineStyle,
6447 ti.flags, ti.width.toReal(), ti.charFormat);
6449 if (state->renderHints != oldRenderHints) {
6450 state->renderHints = oldRenderHints;
6452 extended->renderHintsChanged();
6454 state->dirtyFlags |= QPaintEngine::DirtyHints;
6459 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6461 Returns the bounding rectangle of the \a text as it will appear
6462 when drawn inside the given \a rectangle with the specified \a
6463 flags using the currently set font(); i.e the function tells you
6464 where the drawText() function will draw when given the same
6467 If the \a text does not fit within the given \a rectangle using
6468 the specified \a flags, the function returns the required
6471 The \a flags argument is a bitwise OR of the following flags:
6475 \li Qt::AlignHCenter
6478 \li Qt::AlignVCenter
6480 \li Qt::TextSingleLine
6481 \li Qt::TextExpandTabs
6482 \li Qt::TextShowMnemonic
6483 \li Qt::TextWordWrap
6484 \li Qt::TextIncludeTrailingSpaces
6486 If several of the horizontal or several of the vertical alignment
6487 flags are set, the resulting alignment is undefined.
6489 \sa drawText(), Qt::Alignment, Qt::TextFlag
6493 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6494 const QString &text)
6498 Returns the bounding rectangle of the \a text as it will appear
6499 when drawn inside the given \a rectangle with the specified \a
6500 flags using the currently set font().
6504 \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6505 const QString &text);
6509 Returns the bounding rectangle of the given \a text as it will
6510 appear when drawn inside the rectangle beginning at the point
6511 (\a{x}, \a{y}) with width \a w and height \a h.
6513 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6516 return QRect(rect.x(),rect.y(), 0,0);
6518 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6524 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6527 return QRectF(rect.x(),rect.y(), 0,0);
6529 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6534 \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6535 const QString &text, const QTextOption &option)
6539 Instead of specifying flags as a bitwise OR of the
6540 Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6541 an \a option argument. The QTextOption class provides a
6542 description of general rich text properties.
6546 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6550 if (!d->engine || text.length() == 0)
6551 return QRectF(r.x(),r.y(), 0,0);
6554 qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6559 \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6561 Draws a tiled \a pixmap, inside the given \a rectangle with its
6562 origin at the given \a position.
6564 Calling drawTiledPixmap() is similar to calling drawPixmap()
6565 several times to fill (tile) an area with a pixmap, but is
6566 potentially much more efficient depending on the underlying window
6571 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6573 #ifdef QT_DEBUG_DRAW
6574 if (qt_show_painter_debug_output)
6575 printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6576 r.x(), r.y(), r.width(), r.height(),
6577 pixmap.width(), pixmap.height(),
6582 if (!d->engine || pixmap.isNull() || r.isEmpty())
6586 qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6589 qreal sw = pixmap.width();
6590 qreal sh = pixmap.height();
6594 sx = qRound(sw) - qRound(-sx) % qRound(sw);
6596 sx = qRound(sx) % qRound(sw);
6598 sy = qRound(sh) - -qRound(sy) % qRound(sh);
6600 sy = qRound(sy) % qRound(sh);
6604 d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6608 if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6609 fillRect(r, d->state->bgBrush);
6611 d->updateState(d->state);
6612 if ((d->state->matrix.type() > QTransform::TxTranslate
6613 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6614 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6617 setBackgroundMode(Qt::TransparentMode);
6618 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6619 setBrush(QBrush(d->state->pen.color(), pixmap));
6622 // If there is no rotation involved we have to make sure we use the
6623 // antialiased and not the aliased coordinate system by rounding the coordinates.
6624 if (d->state->matrix.type() <= QTransform::TxScale) {
6625 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6627 if (d->state->matrix.type() <= QTransform::TxTranslate) {
6632 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6633 drawRect(QRectF(p, r.size()));
6635 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6644 if (d->state->matrix.type() == QTransform::TxTranslate
6645 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6646 x += d->state->matrix.dx();
6647 y += d->state->matrix.dy();
6650 d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6654 \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6655 const QPoint &position = QPoint())
6658 Draws a tiled \a pixmap, inside the given \a rectangle with its
6659 origin at the given \a position.
6663 \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6664 QPixmap &pixmap, int sx, int sy);
6667 Draws a tiled \a pixmap in the specified rectangle.
6669 (\a{x}, \a{y}) specifies the top-left point in the paint device
6670 that is to be drawn onto; with the given \a width and \a
6671 height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6672 pixmap that is to be drawn; this defaults to (0, 0).
6675 #ifndef QT_NO_PICTURE
6678 \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6680 Replays the given \a picture at the given \a point.
6682 The QPicture class is a paint device that records and replays
6683 QPainter commands. A picture serializes the painter commands to an
6684 IO device in a platform-independent format. Everything that can be
6685 painted on a widget or pixmap can also be stored in a picture.
6687 This function does exactly the same as QPicture::play() when
6688 called with \a point = QPoint(0, 0).
6693 \snippet code/src_gui_painting_qpainter.cpp 18
6696 \sa QPicture::play()
6699 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6707 d->updateState(d->state);
6711 const_cast<QPicture *>(&picture)->play(this);
6716 \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6719 Replays the given \a picture at the given \a point.
6723 \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6726 Draws the given \a picture at point (\a x, \a y).
6729 #endif // QT_NO_PICTURE
6732 \fn void QPainter::eraseRect(const QRectF &rectangle)
6734 Erases the area inside the given \a rectangle. Equivalent to
6736 \snippet code/src_gui_painting_qpainter.cpp 19
6740 void QPainter::eraseRect(const QRectF &r)
6744 fillRect(r, d->state->bgBrush);
6747 static inline bool needsResolving(const QBrush &brush)
6749 Qt::BrushStyle s = brush.style();
6750 return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
6751 s == Qt::ConicalGradientPattern) &&
6752 brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
6756 \fn void QPainter::eraseRect(const QRect &rectangle)
6759 Erases the area inside the given \a rectangle.
6763 \fn void QPainter::eraseRect(int x, int y, int width, int height)
6766 Erases the area inside the rectangle beginning at (\a x, \a y)
6767 with the given \a width and \a height.
6772 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
6775 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6776 width and \a height, using the brush \a style specified.
6782 \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
6785 Fills the given \a rectangle with the brush \a style specified.
6791 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
6794 Fills the given \a rectangle with the brush \a style specified.
6800 \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
6802 Fills the given \a rectangle with the \a brush specified.
6804 Alternatively, you can specify a QColor instead of a QBrush; the
6805 QBrush constructor (taking a QColor argument) will automatically
6806 create a solid pattern brush.
6810 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
6818 const QGradient *g = brush.gradient();
6819 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6820 d->extended->fillRect(r, brush);
6825 QPen oldPen = pen();
6826 QBrush oldBrush = this->brush();
6828 if (brush.style() == Qt::SolidPattern) {
6829 d->colorBrush.setStyle(Qt::SolidPattern);
6830 d->colorBrush.setColor(brush.color());
6831 setBrush(d->colorBrush);
6842 \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
6845 Fills the given \a rectangle with the specified \a brush.
6848 void QPainter::fillRect(const QRect &r, const QBrush &brush)
6856 const QGradient *g = brush.gradient();
6857 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6858 d->extended->fillRect(r, brush);
6863 QPen oldPen = pen();
6864 QBrush oldBrush = this->brush();
6866 if (brush.style() == Qt::SolidPattern) {
6867 d->colorBrush.setStyle(Qt::SolidPattern);
6868 d->colorBrush.setColor(brush.color());
6869 setBrush(d->colorBrush);
6882 \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
6885 Fills the given \a rectangle with the \a color specified.
6889 void QPainter::fillRect(const QRect &r, const QColor &color)
6897 d->extended->fillRect(r, color);
6901 fillRect(r, QBrush(color));
6906 \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
6909 Fills the given \a rectangle with the \a color specified.
6913 void QPainter::fillRect(const QRectF &r, const QColor &color)
6921 d->extended->fillRect(r, color);
6925 fillRect(r, QBrush(color));
6929 \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
6933 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6934 width and \a height, using the given \a brush.
6938 \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
6942 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6943 width and \a height, using the given \a color.
6949 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
6953 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6954 width and \a height, using the given \a color.
6960 \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
6964 Fills the given \a rectangle with the specified \a color.
6970 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
6974 Fills the given \a rectangle with the specified \a color.
6980 Sets the given render \a hint on the painter if \a on is true;
6981 otherwise clears the render hint.
6983 \sa setRenderHints(), renderHints(), {QPainter#Rendering
6984 Quality}{Rendering Quality}
6986 void QPainter::setRenderHint(RenderHint hint, bool on)
6988 #ifdef QT_DEBUG_DRAW
6989 if (qt_show_painter_debug_output)
6990 printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
6994 static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
6995 if (hint == QPainter::Antialiasing && antialiasingDisabled)
6999 setRenderHints(hint, on);
7005 Sets the given render \a hints on the painter if \a on is true;
7006 otherwise clears the render hints.
7008 \sa setRenderHint(), renderHints(), {QPainter#Rendering
7009 Quality}{Rendering Quality}
7012 void QPainter::setRenderHints(RenderHints hints, bool on)
7017 qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7022 d->state->renderHints |= hints;
7024 d->state->renderHints &= ~hints;
7027 d->extended->renderHintsChanged();
7029 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7033 Returns a flag that specifies the rendering hints that are set for
7036 \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7038 QPainter::RenderHints QPainter::renderHints() const
7040 Q_D(const QPainter);
7045 return d->state->renderHints;
7049 \fn bool QPainter::testRenderHint(RenderHint hint) const
7052 Returns true if \a hint is set; otherwise returns false.
7054 \sa renderHints(), setRenderHint()
7058 Returns true if view transformation is enabled; otherwise returns
7061 \sa setViewTransformEnabled(), worldTransform()
7064 bool QPainter::viewTransformEnabled() const
7066 Q_D(const QPainter);
7068 qWarning("QPainter::viewTransformEnabled: Painter not active");
7071 return d->state->VxF;
7075 \fn void QPainter::setWindow(const QRect &rectangle)
7077 Sets the painter's window to the given \a rectangle, and enables
7078 view transformations.
7080 The window rectangle is part of the view transformation. The
7081 window specifies the logical coordinate system. Its sister, the
7082 viewport(), specifies the device coordinate system.
7084 The default window rectangle is the same as the device's
7087 \sa window(), viewTransformEnabled(), {Coordinate
7088 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7092 \fn void QPainter::setWindow(int x, int y, int width, int height)
7095 Sets the painter's window to the rectangle beginning at (\a x, \a
7096 y) and the given \a width and \a height.
7099 void QPainter::setWindow(const QRect &r)
7101 #ifdef QT_DEBUG_DRAW
7102 if (qt_show_painter_debug_output)
7103 printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7109 qWarning("QPainter::setWindow: Painter not active");
7113 d->state->wx = r.x();
7114 d->state->wy = r.y();
7115 d->state->ww = r.width();
7116 d->state->wh = r.height();
7118 d->state->VxF = true;
7123 Returns the window rectangle.
7125 \sa setWindow(), setViewTransformEnabled()
7128 QRect QPainter::window() const
7130 Q_D(const QPainter);
7132 qWarning("QPainter::window: Painter not active");
7135 return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7139 \fn void QPainter::setViewport(const QRect &rectangle)
7141 Sets the painter's viewport rectangle to the given \a rectangle,
7142 and enables view transformations.
7144 The viewport rectangle is part of the view transformation. The
7145 viewport specifies the device coordinate system. Its sister, the
7146 window(), specifies the logical coordinate system.
7148 The default viewport rectangle is the same as the device's
7151 \sa viewport(), viewTransformEnabled(), {Coordinate
7152 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7156 \fn void QPainter::setViewport(int x, int y, int width, int height)
7159 Sets the painter's viewport rectangle to be the rectangle
7160 beginning at (\a x, \a y) with the given \a width and \a height.
7163 void QPainter::setViewport(const QRect &r)
7165 #ifdef QT_DEBUG_DRAW
7166 if (qt_show_painter_debug_output)
7167 printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7173 qWarning("QPainter::setViewport: Painter not active");
7177 d->state->vx = r.x();
7178 d->state->vy = r.y();
7179 d->state->vw = r.width();
7180 d->state->vh = r.height();
7182 d->state->VxF = true;
7187 Returns the viewport rectangle.
7189 \sa setViewport(), setViewTransformEnabled()
7192 QRect QPainter::viewport() const
7194 Q_D(const QPainter);
7196 qWarning("QPainter::viewport: Painter not active");
7199 return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7203 Enables view transformations if \a enable is true, or disables
7204 view transformations if \a enable is false.
7206 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7207 Conversion}{Window-Viewport Conversion}
7210 void QPainter::setViewTransformEnabled(bool enable)
7212 #ifdef QT_DEBUG_DRAW
7213 if (qt_show_painter_debug_output)
7214 printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7220 qWarning("QPainter::setViewTransformEnabled: Painter not active");
7224 if (enable == d->state->VxF)
7227 d->state->VxF = enable;
7236 Please use QWidget::render() instead.
7238 Redirects all paint commands for the given paint \a device, to the
7239 \a replacement device. The optional point \a offset defines an
7240 offset within the source device.
7242 The redirection will not be effective until the begin() function
7243 has been called; make sure to call end() for the given \a
7244 device's painter (if any) before redirecting. Call
7245 restoreRedirected() to restore the previous redirection.
7247 \warning Making use of redirections in the QPainter API implies
7248 that QPainter::begin() and QPaintDevice destructors need to hold
7249 a mutex for a short period. This can impact performance. Use of
7250 QWidget::render is strongly encouraged.
7252 \sa redirected(), restoreRedirected()
7254 void QPainter::setRedirected(const QPaintDevice *device,
7255 QPaintDevice *replacement,
7256 const QPoint &offset)
7258 Q_ASSERT(device != 0);
7260 Q_UNUSED(replacement)
7262 qWarning("QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7270 Using QWidget::render() obsoletes the use of this function.
7272 Restores the previous redirection for the given \a device after a
7273 call to setRedirected().
7275 \warning Making use of redirections in the QPainter API implies
7276 that QPainter::begin() and QPaintDevice destructors need to hold
7277 a mutex for a short period. This can impact performance. Use of
7278 QWidget::render is strongly encouraged.
7282 void QPainter::restoreRedirected(const QPaintDevice *device)
7285 qWarning("QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7293 Using QWidget::render() obsoletes the use of this function.
7295 Returns the replacement for given \a device. The optional out
7296 parameter \a offset returns the offset within the replaced device.
7298 \warning Making use of redirections in the QPainter API implies
7299 that QPainter::begin() and QPaintDevice destructors need to hold
7300 a mutex for a short period. This can impact performance. Use of
7301 QWidget::render is strongly encouraged.
7303 \sa setRedirected(), restoreRedirected()
7305 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7312 void qt_format_text(const QFont &fnt, const QRectF &_r,
7313 int tf, const QString& str, QRectF *brect,
7314 int tabstops, int *ta, int tabarraylen,
7317 qt_format_text(fnt, _r,
7319 tabstops, ta, tabarraylen,
7322 void qt_format_text(const QFont &fnt, const QRectF &_r,
7323 int tf, const QTextOption *option, const QString& str, QRectF *brect,
7324 int tabstops, int *ta, int tabarraylen,
7328 Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
7331 tf |= option->alignment();
7332 if (option->wrapMode() != QTextOption::NoWrap)
7333 tf |= Qt::TextWordWrap;
7335 if (option->flags() & QTextOption::IncludeTrailingSpaces)
7336 tf |= Qt::TextIncludeTrailingSpaces;
7338 if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
7339 tf |= Qt::TextExpandTabs;
7342 // we need to copy r here to protect against the case (&r == brect).
7345 bool dontclip = (tf & Qt::TextDontClip);
7346 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
7347 bool singleline = (tf & Qt::TextSingleLine);
7348 bool showmnemonic = (tf & Qt::TextShowMnemonic);
7349 bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
7351 Qt::LayoutDirection layout_direction;
7352 if (tf & Qt::TextForceLeftToRight)
7353 layout_direction = Qt::LeftToRight;
7354 else if (tf & Qt::TextForceRightToLeft)
7355 layout_direction = Qt::RightToLeft;
7357 layout_direction = option->textDirection();
7359 layout_direction = painter->layoutDirection();
7361 layout_direction = Qt::LeftToRight;
7363 tf = QGuiApplicationPrivate::visualAlignment(layout_direction, QFlag(tf));
7365 bool isRightToLeft = layout_direction == Qt::RightToLeft;
7366 bool expandtabs = ((tf & Qt::TextExpandTabs) &&
7367 (((tf & Qt::AlignLeft) && !isRightToLeft) ||
7368 ((tf & Qt::AlignRight) && isRightToLeft)));
7371 tf |= Qt::TextDontPrint;
7373 uint maxUnderlines = 0;
7374 int numUnderlines = 0;
7375 QVarLengthArray<int, 32> underlinePositions(1);
7377 QFontMetricsF fm(fnt);
7380 start_lengthVariant:
7381 bool hasMoreLengthVariants = false;
7382 // compatible behaviour to the old implementation. Replace
7384 int old_offset = offset;
7385 for (; offset < text.length(); offset++) {
7386 QChar chr = text.at(offset);
7387 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
7388 text[offset] = QLatin1Char(' ');
7389 } else if (chr == QLatin1Char('\n')) {
7390 text[offset] = QChar::LineSeparator;
7391 } else if (chr == QLatin1Char('&')) {
7393 } else if (chr == QLatin1Char('\t')) {
7395 text[offset] = QLatin1Char(' ');
7396 } else if (!tabarraylen && !tabstops) {
7397 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
7399 } else if (chr == QChar(ushort(0x9c))) {
7400 // string with multiple length variants
7401 hasMoreLengthVariants = true;
7406 int length = offset - old_offset;
7407 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
7408 underlinePositions.resize(maxUnderlines + 1);
7410 QChar *cout = text.data() + old_offset;
7414 if (*cin == QLatin1Char('&')) {
7420 if (*cin != QLatin1Char('&') && !hidemnmemonic)
7421 underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
7430 // no need to do extra work for underlines if we don't paint
7431 if (tf & Qt::TextDontPrint)
7434 underlinePositions[numUnderlines] = -1;
7438 QString finalText = text.mid(old_offset, length);
7439 QStackTextEngine engine(finalText, fnt);
7441 engine.option = *option;
7444 if (engine.option.tabStop() < 0 && tabstops > 0)
7445 engine.option.setTabStop(tabstops);
7447 if (engine.option.tabs().isEmpty() && ta) {
7449 for (int i = 0; i < tabarraylen; i++)
7450 tabs.append(qreal(ta[i]));
7451 engine.option.setTabArray(tabs);
7454 engine.option.setTextDirection(layout_direction);
7455 if (tf & Qt::AlignJustify)
7456 engine.option.setAlignment(Qt::AlignJustify);
7458 engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
7460 if (!option && (tf & Qt::TextWrapAnywhere))
7461 engine.option.setWrapMode(QTextOption::WrapAnywhere);
7463 if (tf & Qt::TextJustificationForced)
7464 engine.forceJustification = true;
7465 QTextLayout textLayout(&engine);
7466 textLayout.setCacheEnabled(true);
7467 textLayout.engine()->underlinePositions = underlinePositions.data();
7469 if (finalText.isEmpty()) {
7470 height = fm.height();
7472 tf |= Qt::TextDontPrint;
7474 qreal lineWidth = 0x01000000;
7475 if (wordwrap || (tf & Qt::TextJustificationForced))
7476 lineWidth = qMax<qreal>(0, r.width());
7478 tf |= Qt::TextIncludeTrailingSpaces;
7479 textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
7480 textLayout.beginLayout();
7482 qreal leading = fm.leading();
7486 QTextLine l = textLayout.createLine();
7490 l.setLineWidth(lineWidth);
7492 l.setPosition(QPointF(0., height));
7493 height += l.height();
7494 width = qMax(width, l.naturalTextWidth());
7495 if (!dontclip && !brect && height >= r.height())
7498 textLayout.endLayout();
7503 if (tf & Qt::AlignBottom) {
7504 yoff = r.height() - height;
7505 } else if (tf & Qt::AlignVCenter) {
7506 yoff = (r.height() - height)/2;
7508 QTransform::TransformationType type = painter->transform().type();
7509 if (type <= QTransform::TxScale) {
7510 // do the rounding manually to work around inconsistencies
7511 // in the paint engines when drawing on floating point offsets
7512 const qreal scale = painter->transform().m22();
7514 yoff = -qRound(-yoff * scale) / scale;
7518 if (tf & Qt::AlignRight) {
7519 xoff = r.width() - width;
7520 } else if (tf & Qt::AlignHCenter) {
7521 xoff = (r.width() - width)/2;
7523 QTransform::TransformationType type = painter->transform().type();
7524 if (type <= QTransform::TxScale) {
7525 // do the rounding manually to work around inconsistencies
7526 // in the paint engines when drawing on floating point offsets
7527 const qreal scale = painter->transform().m11();
7529 xoff = qRound(xoff * scale) / scale;
7533 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
7535 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
7537 goto start_lengthVariant;
7542 if (!(tf & Qt::TextDontPrint)) {
7543 bool restore = false;
7544 if (!dontclip && !r.contains(bounds)) {
7547 painter->setClipRect(r, Qt::IntersectClip);
7550 for (int i = 0; i < textLayout.lineCount(); i++) {
7551 QTextLine line = textLayout.lineAt(i);
7552 QTextEngine *eng = textLayout.engine();
7553 eng->enableDelayDecorations();
7555 qreal advance = line.horizontalAdvance();
7557 if (tf & Qt::AlignRight) {
7558 xoff = r.width() - advance -
7559 eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
7561 else if (tf & Qt::AlignHCenter)
7562 xoff = (r.width() - advance) / 2;
7564 line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
7565 eng->drawDecorations(painter);
7575 Sets the layout direction used by the painter when drawing text,
7576 to the specified \a direction.
7578 The default is Qt::LayoutDirectionAuto, which will implicitly determine the
7579 direction from the text drawn.
7581 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
7583 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
7587 d->state->layoutDirection = direction;
7591 Returns the layout direction used by the painter when drawing text.
7593 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
7595 Qt::LayoutDirection QPainter::layoutDirection() const
7597 Q_D(const QPainter);
7598 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
7601 QPainterState::QPainterState(const QPainterState *s)
7602 : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
7603 pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
7604 clipRegion(s->clipRegion), clipPath(s->clipPath),
7605 clipOperation(s->clipOperation),
7606 renderHints(s->renderHints), clipInfo(s->clipInfo),
7607 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
7608 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
7609 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
7610 opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
7611 clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
7612 layoutDirection(s->layoutDirection),
7613 composition_mode(s->composition_mode),
7614 emulationSpecifier(s->emulationSpecifier), changeFlags(0)
7616 dirtyFlags = s->dirtyFlags;
7619 QPainterState::QPainterState()
7620 : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
7622 wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
7623 opacity(1), WxF(false), VxF(false), clipEnabled(true),
7624 bgMode(Qt::TransparentMode), painter(0),
7625 layoutDirection(QGuiApplication::layoutDirection()),
7626 composition_mode(QPainter::CompositionMode_SourceOver),
7627 emulationSpecifier(0), changeFlags(0)
7632 QPainterState::~QPainterState()
7636 void QPainterState::init(QPainter *p) {
7637 bgBrush = Qt::white;
7638 bgMode = Qt::TransparentMode;
7642 wx = wy = ww = wh = 0;
7643 vx = vy = vw = vh = 0;
7646 brushOrigin = QPointF(0, 0);
7648 font = deviceFont = QFont();
7649 clipRegion = QRegion();
7650 clipPath = QPainterPath();
7651 clipOperation = Qt::NoClip;
7653 worldMatrix.reset();
7655 layoutDirection = QGuiApplication::layoutDirection();
7656 composition_mode = QPainter::CompositionMode_SourceOver;
7657 emulationSpecifier = 0;
7665 \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
7666 Qt::ImageConversionFlags flags)
7668 Draws the rectangular portion \a source of the given \a image
7669 into the \a target rectangle in the paint device.
7671 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7673 If the image needs to be modified to fit in a lower-resolution
7674 result (e.g. converting from 32-bit to 8-bit), use the \a flags to
7675 specify how you would prefer this to happen.
7680 \snippet code/src_gui_painting_qpainter.cpp 20
7687 \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
7688 Qt::ImageConversionFlags flags)
7691 Draws the rectangular portion \a source of the given \a image
7692 into the \a target rectangle in the paint device.
7694 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7698 \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
7702 Draws the given \a image at the given \a point.
7706 \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
7710 Draws the given \a image at the given \a point.
7714 \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
7715 Qt::ImageConversionFlags flags = 0)
7719 Draws the rectangular portion \a source of the given \a image with
7720 its origin at the given \a point.
7724 \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
7725 Qt::ImageConversionFlags flags = 0)
7728 Draws the rectangular portion \a source of the given \a image with
7729 its origin at the given \a point.
7733 \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
7737 Draws the given \a image into the given \a rectangle.
7739 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7743 \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
7747 Draws the given \a image into the given \a rectangle.
7749 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7753 \fn void QPainter::drawImage(int x, int y, const QImage &image,
7754 int sx, int sy, int sw, int sh,
7755 Qt::ImageConversionFlags flags)
7758 Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
7761 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
7762 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
7763 image that is to be drawn. The default is (0, 0).
7765 (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
7766 The default, (0, 0) (and negative) means all the way to the
7767 bottom-right of the image.
7771 \class QPaintEngineState
7775 \brief The QPaintEngineState class provides information about the
7776 active paint engine's current state.
7779 QPaintEngineState records which properties that have changed since
7780 the last time the paint engine was updated, as well as their
7783 Which properties that have changed can at any time be retrieved
7784 using the state() function. This function returns an instance of
7785 the QPaintEngine::DirtyFlags type which stores an OR combination
7786 of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
7787 enum defines whether a property has changed since the last update
7790 If a property is marked with a dirty flag, its current value can
7791 be retrieved using the corresponding get function:
7796 \header \li Property Flag \li Current Property Value
7797 \row \li QPaintEngine::DirtyBackground \li backgroundBrush()
7798 \row \li QPaintEngine::DirtyBackgroundMode \li backgroundMode()
7799 \row \li QPaintEngine::DirtyBrush \li brush()
7800 \row \li QPaintEngine::DirtyBrushOrigin \li brushOrigin()
7801 \row \li QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
7803 \row \li QPaintEngine::DirtyClipPath \li clipPath()
7804 \row \li QPaintEngine::DirtyClipRegion \li clipRegion()
7805 \row \li QPaintEngine::DirtyCompositionMode \li compositionMode()
7806 \row \li QPaintEngine::DirtyFont \li font()
7807 \row \li QPaintEngine::DirtyTransform \li transform()
7808 \row \li QPaintEngine::DirtyClipEnabled \li isClipEnabled()
7809 \row \li QPaintEngine::DirtyPen \li pen()
7810 \row \li QPaintEngine::DirtyHints \li renderHints()
7813 The QPaintEngineState class also provide the painter() function
7814 which returns a pointer to the painter that is currently updating
7817 An instance of this class, representing the current state of the
7818 active paint engine, is passed as argument to the
7819 QPaintEngine::updateState() function. The only situation in which
7820 you will have to use this class directly is when implementing your
7828 \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
7830 Returns a combination of flags identifying the set of properties
7831 that need to be updated when updating the paint engine's state
7832 (i.e. during a call to the QPaintEngine::updateState() function).
7834 \sa QPaintEngine::updateState()
7839 Returns the pen in the current paint engine state.
7841 This variable should only be used when the state() returns a
7842 combination which includes the QPaintEngine::DirtyPen flag.
7844 \sa state(), QPaintEngine::updateState()
7847 QPen QPaintEngineState::pen() const
7849 return static_cast<const QPainterState *>(this)->pen;
7853 Returns the brush in the current paint engine state.
7855 This variable should only be used when the state() returns a
7856 combination which includes the QPaintEngine::DirtyBrush flag.
7858 \sa state(), QPaintEngine::updateState()
7861 QBrush QPaintEngineState::brush() const
7863 return static_cast<const QPainterState *>(this)->brush;
7867 Returns the brush origin in the current paint engine state.
7869 This variable should only be used when the state() returns a
7870 combination which includes the QPaintEngine::DirtyBrushOrigin flag.
7872 \sa state(), QPaintEngine::updateState()
7875 QPointF QPaintEngineState::brushOrigin() const
7877 return static_cast<const QPainterState *>(this)->brushOrigin;
7881 Returns the background brush in the current paint engine state.
7883 This variable should only be used when the state() returns a
7884 combination which includes the QPaintEngine::DirtyBackground flag.
7886 \sa state(), QPaintEngine::updateState()
7889 QBrush QPaintEngineState::backgroundBrush() const
7891 return static_cast<const QPainterState *>(this)->bgBrush;
7895 Returns the background mode in the current paint engine
7898 This variable should only be used when the state() returns a
7899 combination which includes the QPaintEngine::DirtyBackgroundMode flag.
7901 \sa state(), QPaintEngine::updateState()
7904 Qt::BGMode QPaintEngineState::backgroundMode() const
7906 return static_cast<const QPainterState *>(this)->bgMode;
7910 Returns the font in the current paint engine
7913 This variable should only be used when the state() returns a
7914 combination which includes the QPaintEngine::DirtyFont flag.
7916 \sa state(), QPaintEngine::updateState()
7919 QFont QPaintEngineState::font() const
7921 return static_cast<const QPainterState *>(this)->font;
7928 Returns the matrix in the current paint engine
7931 \note It is advisable to use transform() instead of this function to
7932 preserve the properties of perspective transformations.
7934 This variable should only be used when the state() returns a
7935 combination which includes the QPaintEngine::DirtyTransform flag.
7937 \sa state(), QPaintEngine::updateState()
7940 QMatrix QPaintEngineState::matrix() const
7942 const QPainterState *st = static_cast<const QPainterState *>(this);
7944 return st->matrix.toAffine();
7950 Returns the matrix in the current paint engine state.
7952 This variable should only be used when the state() returns a
7953 combination which includes the QPaintEngine::DirtyTransform flag.
7955 \sa state(), QPaintEngine::updateState()
7959 QTransform QPaintEngineState::transform() const
7961 const QPainterState *st = static_cast<const QPainterState *>(this);
7968 Returns the clip operation in the current paint engine
7971 This variable should only be used when the state() returns a
7972 combination which includes either the QPaintEngine::DirtyClipPath
7973 or the QPaintEngine::DirtyClipRegion flag.
7975 \sa state(), QPaintEngine::updateState()
7978 Qt::ClipOperation QPaintEngineState::clipOperation() const
7980 return static_cast<const QPainterState *>(this)->clipOperation;
7986 Returns whether the coordinate of the fill have been specified
7987 as bounded by the current rendering operation and have to be
7988 resolved (about the currently rendered primitive).
7990 bool QPaintEngineState::brushNeedsResolving() const
7992 const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
7993 return needsResolving(brush);
8000 Returns whether the coordinate of the stroke have been specified
8001 as bounded by the current rendering operation and have to be
8002 resolved (about the currently rendered primitive).
8004 bool QPaintEngineState::penNeedsResolving() const
8006 const QPen &pen = static_cast<const QPainterState *>(this)->pen;
8007 return needsResolving(pen.brush());
8011 Returns the clip region in the current paint engine state.
8013 This variable should only be used when the state() returns a
8014 combination which includes the QPaintEngine::DirtyClipRegion flag.
8016 \sa state(), QPaintEngine::updateState()
8019 QRegion QPaintEngineState::clipRegion() const
8021 return static_cast<const QPainterState *>(this)->clipRegion;
8025 Returns the clip path in the current paint engine state.
8027 This variable should only be used when the state() returns a
8028 combination which includes the QPaintEngine::DirtyClipPath flag.
8030 \sa state(), QPaintEngine::updateState()
8033 QPainterPath QPaintEngineState::clipPath() const
8035 return static_cast<const QPainterState *>(this)->clipPath;
8039 Returns whether clipping is enabled or not in the current paint
8042 This variable should only be used when the state() returns a
8043 combination which includes the QPaintEngine::DirtyClipEnabled
8046 \sa state(), QPaintEngine::updateState()
8049 bool QPaintEngineState::isClipEnabled() const
8051 return static_cast<const QPainterState *>(this)->clipEnabled;
8055 Returns the render hints in the current paint engine state.
8057 This variable should only be used when the state() returns a
8058 combination which includes the QPaintEngine::DirtyHints
8061 \sa state(), QPaintEngine::updateState()
8064 QPainter::RenderHints QPaintEngineState::renderHints() const
8066 return static_cast<const QPainterState *>(this)->renderHints;
8070 Returns the composition mode in the current paint engine state.
8072 This variable should only be used when the state() returns a
8073 combination which includes the QPaintEngine::DirtyCompositionMode
8076 \sa state(), QPaintEngine::updateState()
8079 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8081 return static_cast<const QPainterState *>(this)->composition_mode;
8086 Returns a pointer to the painter currently updating the paint
8090 QPainter *QPaintEngineState::painter() const
8092 return static_cast<const QPainterState *>(this)->painter;
8099 Returns the opacity in the current paint engine state.
8102 qreal QPaintEngineState::opacity() const
8104 return static_cast<const QPainterState *>(this)->opacity;
8110 Sets the world transformation matrix.
8111 If \a combine is true, the specified \a transform is combined with
8112 the current matrix; otherwise it replaces the current matrix.
8114 \sa transform(), setWorldTransform()
8117 void QPainter::setTransform(const QTransform &transform, bool combine )
8119 setWorldTransform(transform, combine);
8123 Returns the world transformation matrix.
8125 \sa worldTransform()
8128 const QTransform & QPainter::transform() const
8130 return worldTransform();
8135 Returns the matrix that transforms from logical coordinates to
8136 device coordinates of the platform dependent paint device.
8138 This function is \e only needed when using platform painting
8139 commands on the platform dependent handle (Qt::HANDLE), and the
8140 platform does not do transformations nativly.
8142 The QPaintEngine::PaintEngineFeature enum can be queried to
8143 determine whether the platform performs the transformations or
8146 \sa worldTransform(), QPaintEngine::hasFeature(),
8149 const QTransform & QPainter::deviceTransform() const
8151 Q_D(const QPainter);
8153 qWarning("QPainter::deviceTransform: Painter not active");
8154 return d->fakeState()->transform;
8156 return d->state->matrix;
8161 Resets any transformations that were made using translate(),
8162 scale(), shear(), rotate(), setWorldTransform(), setViewport()
8165 \sa {Coordinate Transformations}
8168 void QPainter::resetTransform()
8171 #ifdef QT_DEBUG_DRAW
8172 if (qt_show_painter_debug_output)
8173 printf("QPainter::resetMatrix()\n");
8176 qWarning("QPainter::resetMatrix: Painter not active");
8180 d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins
8181 d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
8182 d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
8183 d->state->worldMatrix = QTransform();
8184 setMatrixEnabled(false);
8185 setViewTransformEnabled(false);
8187 d->extended->transformChanged();
8189 d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
8193 Sets the world transformation matrix.
8194 If \a combine is true, the specified \a matrix is combined with the current matrix;
8195 otherwise it replaces the current matrix.
8197 \sa transform(), setTransform()
8200 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
8205 qWarning("QPainter::setWorldTransform: Painter not active");
8210 d->state->worldMatrix = matrix * d->state->worldMatrix; // combines
8212 d->state->worldMatrix = matrix; // set new matrix
8214 d->state->WxF = true;
8219 Returns the world transformation matrix.
8222 const QTransform & QPainter::worldTransform() const
8224 Q_D(const QPainter);
8226 qWarning("QPainter::worldTransform: Painter not active");
8227 return d->fakeState()->transform;
8229 return d->state->worldMatrix;
8233 Returns the transformation matrix combining the current
8234 window/viewport and world transformation.
8236 \sa setWorldTransform(), setWindow(), setViewport()
8239 QTransform QPainter::combinedTransform() const
8241 Q_D(const QPainter);
8243 qWarning("QPainter::combinedTransform: Painter not active");
8244 return QTransform();
8246 return d->state->worldMatrix * d->viewTransform();
8252 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
8253 at multiple positions with different scale, rotation and opacity. \a
8254 fragments is an array of \a fragmentCount elements specifying the
8255 parameters used to draw each pixmap fragment. The \a hints
8256 parameter can be used to pass in drawing hints.
8258 This function is potentially faster than multiple calls to drawPixmap(),
8259 since the backend can optimize state changes.
8261 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
8264 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
8265 const QPixmap &pixmap, PixmapFragmentHints hints)
8269 if (!d->engine || pixmap.isNull())
8273 for (int i = 0; i < fragmentCount; ++i) {
8274 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8275 fragments[i].width, fragments[i].height);
8276 if (!(QRectF(pixmap.rect()).contains(sourceRect)))
8277 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
8281 if (d->engine->isExtended()) {
8282 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
8284 qreal oldOpacity = opacity();
8285 QTransform oldTransform = transform();
8287 for (int i = 0; i < fragmentCount; ++i) {
8288 QTransform transform = oldTransform;
8291 if (fragments[i].rotation == 0) {
8292 xOffset = fragments[i].x;
8293 yOffset = fragments[i].y;
8295 transform.translate(fragments[i].x, fragments[i].y);
8296 transform.rotate(fragments[i].rotation);
8298 setOpacity(oldOpacity * fragments[i].opacity);
8299 setTransform(transform);
8301 qreal w = fragments[i].scaleX * fragments[i].width;
8302 qreal h = fragments[i].scaleY * fragments[i].height;
8303 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8304 fragments[i].width, fragments[i].height);
8305 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
8308 setOpacity(oldOpacity);
8309 setTransform(oldTransform);
8315 \class QPainter::PixmapFragment
8318 \brief This class is used in conjunction with the
8319 QPainter::drawPixmapFragments() function to specify how a pixmap, or
8320 sub-rect of a pixmap, is drawn.
8322 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
8323 as a source rectangle within the pixmap passed into the
8324 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
8325 width and \a height are used to calculate the target rectangle that is
8326 drawn. \a x and \a y denotes the center of the target rectangle. The \a
8327 width and \a height in the target rectangle is scaled by the \a scaleX and
8328 \a scaleY values. The resulting target rectangle is then rotated \a
8329 rotation degrees around the \a x, \a y center point.
8331 \sa QPainter::drawPixmapFragments()
8337 This is a convenience function that returns a QPainter::PixmapFragment that is
8338 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
8339 rotation, \a opacity parameters.
8342 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
8343 qreal scaleX, qreal scaleY, qreal rotation,
8346 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
8347 sourceRect.height(), scaleX, scaleY, rotation, opacity};
8352 \variable QPainter::PixmapFragment::x
8353 \brief the x coordinate of center point in the target rectangle.
8357 \variable QPainter::PixmapFragment::y
8358 \brief the y coordinate of the center point in the target rectangle.
8362 \variable QPainter::PixmapFragment::sourceLeft
8363 \brief the left coordinate of the source rectangle.
8367 \variable QPainter::PixmapFragment::sourceTop
8368 \brief the top coordinate of the source rectangle.
8372 \variable QPainter::PixmapFragment::width
8374 \brief the width of the source rectangle and is used to calculate the width
8375 of the target rectangle.
8379 \variable QPainter::PixmapFragment::height
8381 \brief the height of the source rectangle and is used to calculate the
8382 height of the target rectangle.
8386 \variable QPainter::PixmapFragment::scaleX
8387 \brief the horizontal scale of the target rectangle.
8391 \variable QPainter::PixmapFragment::scaleY
8392 \brief the vertical scale of the target rectangle.
8396 \variable QPainter::PixmapFragment::rotation
8398 \brief the rotation of the target rectangle in degrees. The target
8399 rectangle is rotated after it has been scaled.
8403 \variable QPainter::PixmapFragment::opacity
8405 \brief the opacity of the target rectangle, where 0.0 is fully transparent
8406 and 1.0 is fully opaque.
8412 \enum QPainter::PixmapFragmentHint
8414 \value OpaqueHint Indicates that the pixmap fragments to be drawn are
8415 opaque. Opaque fragments are potentially faster to draw.
8417 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
8420 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
8422 p->draw_helper(path, operation);