1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
50 #include "qpaintdevice.h"
51 #include "qpaintengine.h"
53 #include "qpainter_p.h"
54 #include "qpainterpath.h"
56 #include "qpixmapcache.h"
58 #include "qtextlayout.h"
60 #include "qapplication.h"
63 #include "qvarlengtharray.h"
64 #include "qstatictext.h"
67 #include <private/qfontengine_p.h>
68 #include <private/qpaintengine_p.h>
69 #include <private/qemulationpaintengine_p.h>
70 #include <private/qpainterpath_p.h>
71 #include <private/qtextengine_p.h>
72 #include <private/qwidget_p.h>
73 #include <private/qpaintengine_raster_p.h>
74 #include <private/qmath_p.h>
75 #include <private/qstatictext_p.h>
76 #include <private/qglyphs_p.h>
77 #include <private/qstylehelper_p.h>
78 #include <private/qrawfont_p.h>
82 #define QGradient_StretchToDevice 0x10000000
83 #define QPaintEngine_OpaqueBackground 0x40000000
85 // #define QT_DEBUG_DRAW
87 bool qt_show_painter_debug_output = true;
90 extern QPixmap qt_pixmapForBrush(int style, bool invert);
92 void qt_format_text(const QFont &font,
93 const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
94 int tabstops, int* tabarray, int tabarraylen,
96 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
97 QTextCharFormat::UnderlineStyle underlineStyle,
98 QTextItem::RenderFlags flags, qreal width,
99 const QTextCharFormat &charFormat);
100 // Helper function to calculate left most position, width and flags for decoration drawing
101 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
102 const QFixedPoint *positions, int glyphCount,
103 QFontEngine *fontEngine, const QFont &font,
104 const QTextCharFormat &charFormat);
106 static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush)
108 switch (brush.style()) {
109 case Qt::LinearGradientPattern:
110 case Qt::RadialGradientPattern:
111 case Qt::ConicalGradientPattern:
112 return brush.gradient()->coordinateMode();
116 return QGradient::LogicalMode;
119 /* Returns true if the gradient requires stretch to device...*/
120 static inline bool check_gradient(const QBrush &brush)
122 return coordinateMode(brush) == QGradient::StretchToDeviceMode;
125 extern bool qHasPixmapTexture(const QBrush &);
127 static inline bool is_brush_transparent(const QBrush &brush) {
128 Qt::BrushStyle s = brush.style();
129 bool brushBitmap = qHasPixmapTexture(brush)
130 ? brush.texture().isQBitmap()
131 : (brush.textureImage().depth() == 1);
132 return ((s >= Qt::Dense1Pattern && s <= Qt::DiagCrossPattern)
133 || (s == Qt::TexturePattern && brushBitmap));
136 static inline bool is_pen_transparent(const QPen &pen) {
137 return pen.style() > Qt::SolidLine || is_brush_transparent(pen.brush());
140 /* Discards the emulation flags that are not relevant for line drawing
141 and returns the result
143 static inline uint line_emulation(uint emulation)
145 return emulation & (QPaintEngine::PrimitiveTransform
146 | QPaintEngine::AlphaBlend
147 | QPaintEngine::Antialiasing
148 | QPaintEngine::BrushStroke
149 | QPaintEngine::ConstantOpacity
150 | QGradient_StretchToDevice
151 | QPaintEngine::ObjectBoundingModeGradients
152 | QPaintEngine_OpaqueBackground);
155 static bool qt_paintengine_supports_transformations(QPaintEngine::Type type)
157 return type == QPaintEngine::OpenGL2
158 || type == QPaintEngine::OpenVG
159 || type == QPaintEngine::OpenGL
160 || type == QPaintEngine::CoreGraphics;
164 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
167 case QInternal::Image:
168 case QInternal::Printer:
169 case QInternal::Picture:
170 // can be drawn onto these devices safely from any thread
177 if (QApplication::testAttribute(Qt::AA_X11InitThreads))
180 if (!extraCondition && QThread::currentThread() != qApp->thread()) {
181 qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
190 void QPainterPrivate::checkEmulation()
193 if (extended->flags() & QPaintEngineEx::DoNotEmulate)
196 bool doEmulation = false;
197 if (state->bgMode == Qt::OpaqueMode)
200 const QGradient *bg = state->brush.gradient();
201 if (bg && bg->coordinateMode() > QGradient::LogicalMode)
204 const QGradient *pg = qpen_brush(state->pen).gradient();
205 if (pg && pg->coordinateMode() > QGradient::LogicalMode)
209 if (extended != emulationEngine) {
210 if (!emulationEngine)
211 emulationEngine = new QEmulationPaintEngine(extended);
212 extended = emulationEngine;
213 extended->setState(state);
215 } else if (emulationEngine == extended) {
216 extended = emulationEngine->real_engine;
221 QPainterPrivate::~QPainterPrivate()
223 delete emulationEngine;
224 for (int i=0; i<states.size(); ++i)
232 QTransform QPainterPrivate::viewTransform() const
235 qreal scaleW = qreal(state->vw)/qreal(state->ww);
236 qreal scaleH = qreal(state->vh)/qreal(state->wh);
237 return QTransform(scaleW, 0, 0, scaleH,
238 state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
246 Returns true if using a shared painter; otherwise false.
248 bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
253 if (pdev->devType() != QInternal::Widget)
256 QWidget *widget = static_cast<QWidget *>(pdev);
259 // Someone either called QPainter::setRedirected in the widget's paint event
260 // right before this painter was created (or begin was called) or
261 // sent a paint event directly to the widget.
262 if (!widget->d_func()->redirectDev)
265 QPainter *sp = widget->d_func()->sharedPainter();
266 if (!sp || !sp->isActive())
269 if (sp->paintEngine()->paintDevice() != widget->d_func()->redirectDev)
272 // Check if we're attempting to paint outside a paint event.
273 if (!sp->d_ptr->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent)
274 && !widget->testAttribute(Qt::WA_PaintOutsidePaintEvent)
275 && !widget->testAttribute(Qt::WA_WState_InPaintEvent)) {
277 qWarning("QPainter::begin: Widget painting can only begin as a result of a paintEvent");
281 // Save the current state of the shared painter and assign
282 // the current d_ptr to the shared painter's d_ptr.
284 if (!sp->d_ptr->d_ptrs) {
285 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
286 // redirections within the same paintEvent(), which should be enough
287 // in 99% of all cases). E.g: A renders B which renders C which renders D.
288 sp->d_ptr->d_ptrs_size = 4;
289 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
290 Q_CHECK_PTR(sp->d_ptr->d_ptrs);
291 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
292 // However, to support corner cases we grow the array dynamically if needed.
293 sp->d_ptr->d_ptrs_size <<= 1;
294 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
295 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
297 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
299 q->d_ptr.reset(sp->d_ptr.data());
301 Q_ASSERT(q->d_ptr->state);
303 // Now initialize the painter with correct widget properties.
306 widget->d_func()->redirected(&offset);
307 offset += q->d_ptr->engine->coordinateOffset();
309 // Update system rect.
310 q->d_ptr->state->ww = q->d_ptr->state->vw = widget->width();
311 q->d_ptr->state->wh = q->d_ptr->state->vh = widget->height();
314 if (q->d_ptr->state->WxF) {
315 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix;
316 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
317 q->d_ptr->state->worldMatrix = QTransform();
318 q->d_ptr->state->WxF = false;
320 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
322 q->d_ptr->updateMatrix();
324 QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
325 if (enginePrivate->currentClipWidget == widget) {
326 enginePrivate->systemStateChanged();
330 // Update system transform and clip.
331 enginePrivate->currentClipWidget = widget;
332 enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
336 void QPainterPrivate::detachPainterPrivate(QPainter *q)
338 Q_ASSERT(refcount > 1);
341 QPainterPrivate *original = d_ptrs[--refcount - 1];
343 inDestructor = false;
345 original->inDestructor = true;
346 } else if (!original) {
347 original = new QPainterPrivate(q);
350 d_ptrs[refcount - 1] = 0;
353 q->d_ptr.reset(original);
355 if (emulationEngine) {
356 extended = emulationEngine->real_engine;
357 delete emulationEngine;
363 void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op)
366 if (qt_show_painter_debug_output) {
367 printf("QPainter::drawHelper\n");
371 if (originalPath.isEmpty())
374 QPaintEngine::PaintEngineFeatures gradientStretch =
375 QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
376 | QPaintEngine::ObjectBoundingModeGradients);
378 const bool mustEmulateObjectBoundingModeGradients = extended
379 || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients)
380 && !engine->hasFeature(QPaintEngine::PatternTransform));
382 if (!(state->emulationSpecifier & ~gradientStretch)
383 && !mustEmulateObjectBoundingModeGradients) {
384 drawStretchedGradient(originalPath, op);
386 } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {
387 drawOpaqueBackground(originalPath, op);
393 qreal strokeOffsetX = 0, strokeOffsetY = 0;
395 QPainterPath path = originalPath * state->matrix;
396 QRectF pathBounds = path.boundingRect();
398 bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
400 qreal penWidth = state->pen.widthF();
405 // In case of complex xform
406 if (state->matrix.type() > QTransform::TxScale) {
407 QPainterPathStroker stroker;
408 stroker.setWidth(penWidth);
409 stroker.setJoinStyle(state->pen.joinStyle());
410 stroker.setCapStyle(state->pen.capStyle());
411 QPainterPath stroke = stroker.createStroke(originalPath);
412 strokeBounds = (stroke * state->matrix).boundingRect();
414 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);
415 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);
421 if (!strokeBounds.isEmpty()) {
422 absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
424 absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
425 .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
428 if (q->hasClipping()) {
429 bool hasPerspectiveTransform = false;
430 for (int i = 0; i < state->clipInfo.size(); ++i) {
431 const QPainterClipInfo &info = state->clipInfo.at(i);
432 if (info.matrix.type() == QTransform::TxProject) {
433 hasPerspectiveTransform = true;
437 // avoid mapping QRegions with perspective transforms
438 if (!hasPerspectiveTransform) {
439 // The trick with txinv and invMatrix is done in order to
440 // avoid transforming the clip to logical coordinates, and
441 // then back to device coordinates. This is a problem with
442 // QRegion/QRect based clips, since they use integer
443 // coordinates and converting to/from logical coordinates will
445 bool old_txinv = txinv;
446 QTransform old_invMatrix = invMatrix;
448 invMatrix = QTransform();
449 QPainterPath clipPath = q->clipPath();
450 QRectF r = clipPath.boundingRect().intersected(absPathRect);
451 absPathRect = r.toAlignedRect();
453 invMatrix = old_invMatrix;
457 // qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
458 // devMinX, devMinY, device->width(), device->height());
459 // qDebug() << " - matrix" << state->matrix;
460 // qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
461 // qDebug() << " - path.bounds" << path.boundingRect();
463 if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
466 QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
471 p.d_ptr->helper_device = helper_device;
473 p.setOpacity(state->opacity);
474 p.translate(-absPathRect.x(), -absPathRect.y());
475 p.setTransform(state->matrix, true);
476 p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
477 p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
478 p.setBackground(state->bgBrush);
479 p.setBackgroundMode(state->bgMode);
480 p.setBrushOrigin(state->brushOrigin);
482 p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);
483 p.setRenderHint(QPainter::SmoothPixmapTransform,
484 state->renderHints & QPainter::SmoothPixmapTransform);
486 p.drawPath(originalPath);
489 static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0;
490 if (do_fallback_overlay) {
491 QImage block(8, 8, QImage::Format_ARGB32_Premultiplied);
493 pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
494 pt.drawLine(0, 0, 8, 8);
497 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
499 p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
506 state->matrix = QTransform();
507 state->dirtyFlags |= QPaintEngine::DirtyTransform;
509 engine->drawImage(absPathRect,
511 QRectF(0, 0, absPathRect.width(), absPathRect.height()),
512 Qt::OrderedDither | Qt::OrderedAlphaDither);
516 void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op)
520 q->setBackgroundMode(Qt::TransparentMode);
522 if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
523 q->fillPath(path, state->bgBrush.color());
524 q->fillPath(path, state->brush);
527 if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
528 q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
529 q->strokePath(path, state->pen);
532 q->setBackgroundMode(Qt::OpaqueMode);
535 static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
537 Q_ASSERT(brush.style() >= Qt::LinearGradientPattern
538 && brush.style() <= Qt::ConicalGradientPattern);
540 QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
541 boundingRect.x(), boundingRect.y());
543 QGradient g = *brush.gradient();
544 g.setCoordinateMode(QGradient::LogicalMode);
547 b.setTransform(gradientToUser * b.transform());
551 void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op)
555 const qreal sw = helper_device->width();
556 const qreal sh = helper_device->height();
558 bool changedPen = false;
559 bool changedBrush = false;
560 bool needsFill = false;
562 const QPen pen = state->pen;
563 const QBrush brush = state->brush;
565 const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
566 const QGradient::CoordinateMode brushMode = coordinateMode(brush);
570 // Draw the xformed fill if the brush is a stretch gradient.
571 if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
572 if (brushMode == QGradient::StretchToDeviceMode) {
573 q->setPen(Qt::NoPen);
574 changedPen = pen.style() != Qt::NoPen;
578 const qreal isw = 1.0 / sw;
579 const qreal ish = 1.0 / sh;
580 QTransform inv(isw, 0, 0, ish, 0, 0);
581 engine->drawPath(path * inv);
586 if (brushMode == QGradient::ObjectBoundingMode) {
587 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
588 boundingRect = path.boundingRect();
589 q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
595 if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
596 // Draw the xformed outline if the pen is a stretch gradient.
597 if (penMode == QGradient::StretchToDeviceMode) {
598 q->setPen(Qt::NoPen);
603 engine->drawPath(path);
607 q->setBrush(pen.brush());
611 QPainterPathStroker stroker;
612 stroker.setDashPattern(pen.style());
613 stroker.setWidth(pen.widthF());
614 stroker.setJoinStyle(pen.joinStyle());
615 stroker.setCapStyle(pen.capStyle());
616 stroker.setMiterLimit(pen.miterLimit());
617 QPainterPath stroke = stroker.createStroke(path);
619 const qreal isw = 1.0 / sw;
620 const qreal ish = 1.0 / sh;
621 QTransform inv(isw, 0, 0, ish, 0, 0);
622 engine->drawPath(stroke * inv);
625 if (!needsFill && brush.style() != Qt::NoBrush) {
626 q->setBrush(Qt::NoBrush);
630 if (penMode == QGradient::ObjectBoundingMode) {
631 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
633 // avoid computing the bounding rect twice
634 if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
635 boundingRect = path.boundingRect();
638 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect));
641 } else if (changedPen) {
647 engine->drawPath(path);
649 } else if (needsFill) {
650 if (pen.style() != Qt::NoPen) {
651 q->setPen(Qt::NoPen);
656 engine->drawPath(path);
666 void QPainterPrivate::updateMatrix()
668 state->matrix = state->WxF ? state->worldMatrix : QTransform();
670 state->matrix *= viewTransform();
672 txinv = false; // no inverted matrix
673 state->matrix *= state->redirectionMatrix;
675 extended->transformChanged();
677 state->dirtyFlags |= QPaintEngine::DirtyTransform;
679 // printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
680 // qDebug() << " --- using matrix" << state->matrix << redirection_offset;
684 void QPainterPrivate::updateInvMatrix()
686 Q_ASSERT(txinv == false);
687 txinv = true; // creating inverted matrix
688 invMatrix = state->matrix.inverted();
691 void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
694 bool linearGradient = false;
695 bool radialGradient = false;
696 bool conicalGradient = false;
697 bool patternBrush = false;
699 bool complexXform = false;
703 // Pen and brush properties (we have to check both if one changes because the
704 // one that's unchanged can still be in a state which requires emulation)
705 if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) {
706 // Check Brush stroke emulation
707 if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke))
708 s->emulationSpecifier |= QPaintEngine::BrushStroke;
710 s->emulationSpecifier &= ~QPaintEngine::BrushStroke;
714 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
715 Qt::BrushStyle brushStyle = qbrush_style(s->brush);
716 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
717 alpha = (penBrushStyle != Qt::NoBrush
718 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
719 && !penBrush.isOpaque())
720 || (brushStyle != Qt::NoBrush
721 && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
722 && !s->brush.isOpaque());
723 linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
724 (brushStyle == Qt::LinearGradientPattern));
725 radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
726 (brushStyle == Qt::RadialGradientPattern));
727 conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
728 (brushStyle == Qt::ConicalGradientPattern));
729 patternBrush = (((penBrushStyle > Qt::SolidPattern
730 && penBrushStyle < Qt::LinearGradientPattern)
731 || penBrushStyle == Qt::TexturePattern) ||
732 ((brushStyle > Qt::SolidPattern
733 && brushStyle < Qt::LinearGradientPattern)
734 || brushStyle == Qt::TexturePattern));
736 bool penTextureAlpha = false;
737 if (penBrush.style() == Qt::TexturePattern)
738 penTextureAlpha = qHasPixmapTexture(penBrush)
739 ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
740 : penBrush.textureImage().hasAlphaChannel();
741 bool brushTextureAlpha = false;
742 if (s->brush.style() == Qt::TexturePattern) {
743 brushTextureAlpha = qHasPixmapTexture(s->brush)
744 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
745 : s->brush.textureImage().hasAlphaChannel();
747 if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
748 || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
749 && !engine->hasFeature(QPaintEngine::MaskedBrush))
750 s->emulationSpecifier |= QPaintEngine::MaskedBrush;
752 s->emulationSpecifier &= ~QPaintEngine::MaskedBrush;
755 if (s->state() & (QPaintEngine::DirtyHints
756 | QPaintEngine::DirtyOpacity
757 | QPaintEngine::DirtyBackgroundMode)) {
765 qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
767 " - linearGradient: %d\n"
768 " - radialGradient: %d\n"
769 " - conicalGradient: %d\n"
770 " - patternBrush: %d\n"
779 uint(s->renderHints),
784 if (s->state() & QPaintEngine::DirtyTransform) {
785 xform = !s->matrix.isIdentity();
786 complexXform = !s->matrix.isAffine();
787 } else if (s->matrix.type() >= QTransform::TxTranslate) {
789 complexXform = !s->matrix.isAffine();
792 const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone);
793 const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone);
795 const bool patternXform = patternBrush && (xform || brushXform || penXform);
797 // Check alphablending
798 if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend))
799 s->emulationSpecifier |= QPaintEngine::AlphaBlend;
801 s->emulationSpecifier &= ~QPaintEngine::AlphaBlend;
803 // Linear gradient emulation
804 if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill))
805 s->emulationSpecifier |= QPaintEngine::LinearGradientFill;
807 s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
809 // Radial gradient emulation
810 if (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill))
811 s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
813 s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
815 // Conical gradient emulation
816 if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
817 s->emulationSpecifier |= QPaintEngine::ConicalGradientFill;
819 s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill;
822 if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
823 s->emulationSpecifier |= QPaintEngine::PatternBrush;
825 s->emulationSpecifier &= ~QPaintEngine::PatternBrush;
828 if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform))
829 s->emulationSpecifier |= QPaintEngine::PatternTransform;
831 s->emulationSpecifier &= ~QPaintEngine::PatternTransform;
834 if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform))
835 s->emulationSpecifier |= QPaintEngine::PrimitiveTransform;
837 s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform;
839 // Perspective XForms
840 if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform))
841 s->emulationSpecifier |= QPaintEngine::PerspectiveTransform;
843 s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform;
846 if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity))
847 s->emulationSpecifier |= QPaintEngine::ConstantOpacity;
849 s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity;
851 bool gradientStretch = false;
852 bool objectBoundingMode = false;
853 if (linearGradient || conicalGradient || radialGradient) {
854 QGradient::CoordinateMode brushMode = coordinateMode(s->brush);
855 QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush());
857 gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
858 gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
860 objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
861 objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
864 s->emulationSpecifier |= QGradient_StretchToDevice;
866 s->emulationSpecifier &= ~QGradient_StretchToDevice;
868 if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
869 s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients;
871 s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients;
873 // Opaque backgrounds...
874 if (s->bgMode == Qt::OpaqueMode &&
875 (is_pen_transparent(s->pen) || is_brush_transparent(s->brush)))
876 s->emulationSpecifier |= QPaintEngine_OpaqueBackground;
878 s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground;
881 //won't be correct either way because the device can already have
882 // something rendered to it in which case subsequent emulation
883 // on a fully transparent qimage and then blitting the results
884 // won't produce correct results
886 if (state->composition_mode > QPainter::CompositionMode_Xor &&
887 !engine->hasFeature(QPaintEngine::BlendModes))
888 s->emulationSpecifier |= QPaintEngine::BlendModes;
890 s->emulationSpecifier &= ~QPaintEngine::BlendModes;
894 void QPainterPrivate::updateStateImpl(QPainterState *newState)
896 // ### we might have to call QPainter::begin() here...
897 if (!engine->state) {
898 engine->state = newState;
899 engine->setDirty(QPaintEngine::AllDirty);
902 if (engine->state->painter() != newState->painter)
903 // ### this could break with clip regions vs paths.
904 engine->setDirty(QPaintEngine::AllDirty);
906 // Upon restore, revert all changes since last save
907 else if (engine->state != newState)
908 newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
910 // We need to store all changes made so that restore can deal with them
912 newState->changeFlags |= newState->dirtyFlags;
914 updateEmulationSpecifier(newState);
916 // Unset potential dirty background mode
917 newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode
918 | QPaintEngine::DirtyBackground);
920 engine->state = newState;
921 engine->updateState(*newState);
922 engine->clearDirty(QPaintEngine::AllDirty);
926 void QPainterPrivate::updateState(QPainterState *newState)
930 engine->state = newState;
932 } else if (newState->state() || engine->state!=newState) {
933 bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
934 && newState->pen.widthF() == 0;
935 if (setNonCosmeticPen) {
936 // Override the default pen's cosmetic state if the
937 // NonCosmeticDefaultPen render hint is used.
938 QPen oldPen = newState->pen;
939 newState->pen.setWidth(1);
940 newState->pen.setCosmetic(false);
941 newState->dirtyFlags |= QPaintEngine::DirtyPen;
943 updateStateImpl(newState);
945 // Restore the state pen back to its default to preserve visible
947 newState->pen = oldPen;
949 updateStateImpl(newState);
957 \brief The QPainter class performs low-level painting on widgets and
964 QPainter provides highly optimized functions to do most of the
965 drawing GUI programs require. It can draw everything from simple
966 lines to complex shapes like pies and chords. It can also draw
967 aligned text and pixmaps. Normally, it draws in a "natural"
968 coordinate system, but it can also do view and world
969 transformation. QPainter can operate on any object that inherits
970 the QPaintDevice class.
972 The common use of QPainter is inside a widget's paint event:
973 Construct and customize (e.g. set the pen or the brush) the
974 painter. Then draw. Remember to destroy the QPainter object after
975 drawing. For example:
977 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 0
979 The core functionality of QPainter is drawing, but the class also
980 provide several functions that allows you to customize QPainter's
981 settings and its rendering quality, and others that enable
982 clipping. In addition you can control how different shapes are
983 merged together by specifying the painter's composition mode.
985 The isActive() function indicates whether the painter is active. A
986 painter is activated by the begin() function and the constructor
987 that takes a QPaintDevice argument. The end() function, and the
988 destructor, deactivates it.
990 Together with the QPaintDevice and QPaintEngine classes, QPainter
991 form the basis for Qt's paint system. QPainter is the class used
992 to perform drawing operations. QPaintDevice represents a device
993 that can be painted on using a QPainter. QPaintEngine provides the
994 interface that the painter uses to draw onto different types of
995 devices. If the painter is active, device() returns the paint
996 device on which the painter paints, and paintEngine() returns the
997 paint engine that the painter is currently operating on. For more
998 information, see the \l {Paint System}.
1000 Sometimes it is desirable to make someone else paint on an unusual
1001 QPaintDevice. QPainter supports a static function to do this,
1004 \warning When the paintdevice is a widget, QPainter can only be
1005 used inside a paintEvent() function or in a function called by
1006 paintEvent(); that is unless the Qt::WA_PaintOutsidePaintEvent
1007 widget attribute is set. On Mac OS X and Windows, you can only
1008 paint in a paintEvent() function regardless of this attribute's
1015 There are several settings that you can customize to make QPainter
1016 draw according to your preferences:
1020 \o font() is the font used for drawing text. If the painter
1021 isActive(), you can retrieve information about the currently set
1022 font, and its metrics, using the fontInfo() and fontMetrics()
1023 functions respectively.
1025 \o brush() defines the color or pattern that is used for filling
1028 \o pen() defines the color or stipple that is used for drawing
1029 lines or boundaries.
1031 \o backgroundMode() defines whether there is a background() or
1032 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
1034 \o background() only applies when backgroundMode() is \l
1035 Qt::OpaqueMode and pen() is a stipple. In that case, it
1036 describes the color of the background pixels in the stipple.
1038 \o brushOrigin() defines the origin of the tiled brushes, normally
1039 the origin of widget's background.
1041 \o viewport(), window(), worldTransform() make up the painter's coordinate
1042 transformation system. For more information, see the \l
1043 {Coordinate Transformations} section and the \l {Coordinate
1044 System} documentation.
1046 \o hasClipping() tells whether the painter clips at all. (The paint
1047 device clips, too.) If the painter clips, it clips to clipRegion().
1049 \o layoutDirection() defines the layout direction used by the
1050 painter when drawing text.
1052 \o worldMatrixEnabled() tells whether world transformation is enabled.
1054 \o viewTransformEnabled() tells whether view transformation is
1059 Note that some of these settings mirror settings in some paint
1060 devices, e.g. QWidget::font(). The QPainter::begin() function (or
1061 equivalently the QPainter constructor) copies these attributes
1062 from the paint device.
1064 You can at any time save the QPainter's state by calling the
1065 save() function which saves all the available settings on an
1066 internal stack. The restore() function pops them back.
1070 QPainter provides functions to draw most primitives: drawPoint(),
1071 drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1072 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1073 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
1074 convenience functions, drawRects() and drawLines(), draw the given
1075 number of rectangles or lines in the given array of \l
1076 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1079 The QPainter class also provides the fillRect() function which
1080 fills the given QRect, with the given QBrush, and the eraseRect()
1081 function that erases the area inside the given rectangle.
1083 All of these functions have both integer and floating point
1088 \o \inlineimage qpainter-basicdrawing.png
1090 \bold {Basic Drawing Example}
1092 The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1093 display basic graphics primitives in a variety of styles using the
1098 If you need to draw a complex shape, especially if you need to do
1099 so repeatedly, consider creating a QPainterPath and drawing it
1105 \bold {Painter Paths example}
1107 The QPainterPath class provides a container for painting
1108 operations, enabling graphical shapes to be constructed and
1111 The \l {painting/painterpaths}{Painter Paths} example shows how
1112 painter paths can be used to build complex shapes for rendering.
1114 \o \inlineimage qpainter-painterpaths.png
1117 QPainter also provides the fillPath() function which fills the
1118 given QPainterPath with the given QBrush, and the strokePath()
1119 function that draws the outline of the given path (i.e. strokes
1122 See also the \l {demos/deform}{Vector Deformation} demo which
1123 shows how to use advanced vector techniques to draw text using a
1124 QPainterPath, the \l {demos/gradients}{Gradients} demo which shows
1125 the different types of gradients that are available in Qt, and the \l
1126 {demos/pathstroke}{Path Stroking} demo which shows Qt's built-in
1127 dash patterns and shows how custom patterns can be used to extend
1128 the range of available patterns.
1132 \o \l {demos/deform}{Vector Deformation}
1133 \o \l {demos/gradients}{Gradients}
1134 \o \l {demos/pathstroke}{Path Stroking}
1136 \o \inlineimage qpainter-vectordeformation.png
1137 \o \inlineimage qpainter-gradients.png
1138 \o \inlineimage qpainter-pathstroking.png
1142 There are functions to draw pixmaps/images, namely drawPixmap(),
1143 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1144 produce the same result, except that drawPixmap() is faster
1145 on-screen while drawImage() may be faster on a QPrinter or other
1148 Text drawing is done using drawText(). When you need
1149 fine-grained positioning, boundingRect() tells you where a given
1150 drawText() command will draw.
1152 There is a drawPicture() function that draws the contents of an
1153 entire QPicture. The drawPicture() function is the only function
1154 that disregards all the painter's settings as QPicture has its own
1157 \section1 Rendering Quality
1159 To get the optimal rendering result using QPainter, you should use
1160 the platform independent QImage as paint device; i.e. using QImage
1161 will ensure that the result has an identical pixel representation
1164 The QPainter class also provides a means of controlling the
1165 rendering quality through its RenderHint enum and the support for
1166 floating point precision: All the functions for drawing primitives
1167 has a floating point version. These are often used in combination
1168 with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1172 \o \inlineimage qpainter-concentriccircles.png
1174 \bold {Concentric Circles Example}
1176 The \l {painting/concentriccircles}{Concentric Circles} example
1177 shows the improved rendering quality that can be obtained using
1178 floating point precision and anti-aliasing when drawing custom
1181 The application's main window displays several widgets which are
1182 drawn using the various combinations of precision and
1187 The RenderHint enum specifies flags to QPainter that may or may
1188 not be respected by any given engine. \l
1189 {RenderHint}{QPainter::Antialiasing} indicates that the engine
1190 should antialias edges of primitives if possible, \l
1191 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1192 should antialias text if possible, and the \l
1193 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1194 engine should use a smooth pixmap transformation algorithm.
1195 \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
1196 indicating that the engine should use fragment programs and offscreen
1197 rendering for antialiasing.
1199 The renderHints() function returns a flag that specifies the
1200 rendering hints that are set for this painter. Use the
1201 setRenderHint() function to set or clear the currently set
1204 \section1 Coordinate Transformations
1206 Normally, the QPainter operates on the device's own coordinate
1207 system (usually pixels), but QPainter has good support for
1208 coordinate transformations.
1212 \o nop \o rotate() \o scale() \o translate()
1214 \o \inlineimage qpainter-clock.png
1215 \o \inlineimage qpainter-rotation.png
1216 \o \inlineimage qpainter-scale.png
1217 \o \inlineimage qpainter-translation.png
1220 The most commonly used transformations are scaling, rotation,
1221 translation and shearing. Use the scale() function to scale the
1222 coordinate system by a given offset, the rotate() function to
1223 rotate it clockwise and translate() to translate it (i.e. adding a
1224 given offset to the points). You can also twist the coordinate
1225 system around the origin using the shear() function. See the \l
1226 {demos/affine}{Affine Transformations} demo for a visualization of
1227 a sheared coordinate system.
1229 See also the \l {painting/transformations}{Transformations}
1230 example which shows how transformations influence the way that
1231 QPainter renders graphics primitives. In particular it shows how
1232 the order of transformations affects the result.
1237 \bold {Affine Transformations Demo}
1239 The \l {demos/affine}{Affine Transformations} demo show Qt's
1240 ability to perform affine transformations on painting
1241 operations. The demo also allows the user to experiment with the
1242 transformation operations and see the results immediately.
1244 \o \inlineimage qpainter-affinetransformations.png
1247 All the tranformation operations operate on the transformation
1248 worldTransform(). A matrix transforms a point in the plane to another
1249 point. For more information about the transformation matrix, see
1250 the \l {Coordinate System} and QTransform documentation.
1252 The setWorldTransform() function can replace or add to the currently
1253 set worldTransform(). The resetTransform() function resets any
1254 transformations that were made using translate(), scale(),
1255 shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1256 functions. The deviceTransform() returns the matrix that transforms
1257 from logical coordinates to device coordinates of the platform
1258 dependent paint device. The latter function is only needed when
1259 using platform painting commands on the platform dependent handle,
1260 and the platform does not do transformations nativly.
1262 When drawing with QPainter, we specify points using logical
1263 coordinates which then are converted into the physical coordinates
1264 of the paint device. The mapping of the logical coordinates to the
1265 physical coordinates are handled by QPainter's combinedTransform(), a
1266 combination of viewport() and window() and worldTransform(). The
1267 viewport() represents the physical coordinates specifying an
1268 arbitrary rectangle, the window() describes the same rectangle in
1269 logical coordinates, and the worldTransform() is identical with the
1270 transformation matrix.
1272 See also \l {Coordinate System}
1276 QPainter can clip any drawing operation to a rectangle, a region,
1277 or a vector path. The current clip is available using the
1278 functions clipRegion() and clipPath(). Whether paths or regions are
1279 preferred (faster) depends on the underlying paintEngine(). For
1280 example, the QImage paint engine prefers paths while the X11 paint
1281 engine prefers regions. Setting a clip is done in the painters
1282 logical coordinates.
1284 After QPainter's clipping, the paint device may also clip. For
1285 example, most widgets clip away the pixels used by child widgets,
1286 and most printers clip away an area near the edges of the paper.
1287 This additional clipping is not reflected by the return value of
1288 clipRegion() or hasClipping().
1290 \section1 Composition Modes
1291 \target Composition Modes
1293 QPainter provides the CompositionMode enum which defines the
1294 Porter-Duff rules for digital image compositing; it describes a
1295 model for combining the pixels in one image, the source, with the
1296 pixels in another image, the destination.
1298 The two most common forms of composition are \l
1299 {QPainter::CompositionMode}{Source} and \l
1300 {QPainter::CompositionMode}{SourceOver}. \l
1301 {QPainter::CompositionMode}{Source} is used to draw opaque objects
1302 onto a paint device. In this mode, each pixel in the source
1303 replaces the corresponding pixel in the destination. In \l
1304 {QPainter::CompositionMode}{SourceOver} composition mode, the
1305 source object is transparent and is drawn on top of the
1308 Note that composition transformation operates pixelwise. For that
1309 reason, there is a difference between using the graphic primitive
1310 itself and its bounding rectangle: The bounding rect contains
1311 pixels with alpha == 0 (i.e the pixels surrounding the
1312 primitive). These pixels will overwrite the other image's pixels,
1313 affectively clearing those, while the primitive only overwrites
1318 \o \inlineimage qpainter-compositiondemo.png
1321 \bold {Composition Modes Demo}
1323 The \l {demos/composition}{Composition Modes} demo, available in
1324 Qt's demo directory, allows you to experiment with the various
1325 composition modes and see the results immediately.
1329 \section1 Limitations
1332 If you are using coordinates with Qt's raster-based paint engine, it is
1333 important to note that, while coordinates greater than +/- 2\sup 15 can
1334 be used, any painting performed with coordinates outside this range is not
1335 guaranteed to be shown; the drawing may be clipped. This is due to the
1336 use of \c{short int} in the implementation.
1338 The outlines generated by Qt's stroker are only an approximation when dealing
1339 with curved shapes. It is in most cases impossible to represent the outline of
1340 a bezier curve segment using another bezier curve segment, and so Qt approximates
1341 the curve outlines by using several smaller curves. For performance reasons there
1342 is a limit to how many curves Qt uses for these outlines, and thus when using
1343 large pen widths or scales the outline error increases. To generate outlines with
1344 smaller errors it is possible to use the QPainterPathStroker class, which has the
1345 setCurveThreshold member function which let's the user specify the error tolerance.
1346 Another workaround is to convert the paths to polygons first and then draw the
1349 \section1 Performance
1351 QPainter is a rich framework that allows developers to do a great
1352 variety of graphical operations, such as gradients, composition
1353 modes and vector graphics. And QPainter can do this across a
1354 variety of different hardware and software stacks. Naturally the
1355 underlying combination of hardware and software has some
1356 implications for performance, and ensuring that every single
1357 operation is fast in combination with all the various combinations
1358 of composition modes, brushes, clipping, transformation, etc, is
1359 close to an impossible task because of the number of
1360 permutations. As a compromise we have selected a subset of the
1361 QPainter API and backends, where performance is guaranteed to be as
1362 good as we can sensibly get it for the given combination of
1363 hardware and software.
1365 The backends we focus on as high-performance engines are:
1369 \o Raster - This backend implements all rendering in pure software
1370 and is always used to render into QImages. For optimal performance
1371 only use the format types QImage::Format_ARGB32_Premultiplied,
1372 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1373 including QImage::Format_ARGB32, has significantly worse
1374 performance. This engine is also used by default on Windows and on
1375 QWS. It can be used as default graphics system on any
1376 OS/hardware/software combination by passing \c {-graphicssystem
1377 raster} on the command line
1379 \o OpenGL 2.0 (ES) - This backend is the primary backend for
1380 hardware accelerated graphics. It can be run on desktop machines
1381 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1382 specification. This includes most graphics chips produced in the
1383 last couple of years. The engine can be enabled by using QPainter
1384 onto a QGLWidget or by passing \c {-graphicssystem opengl} on the
1385 command line when the underlying system supports it.
1387 \o OpenVG - This backend implements the Khronos standard for 2D
1388 and Vector Graphics. It is primarily for embedded devices with
1389 hardware support for OpenVG. The engine can be enabled by
1390 passing \c {-graphicssystem openvg} on the command line when
1391 the underlying system supports it.
1395 These operations are:
1399 \o Simple transformations, meaning translation and scaling, pluss
1400 0, 90, 180, 270 degree rotations.
1402 \o \c drawPixmap() in combination with simple transformations and
1403 opacity with non-smooth transformation mode
1404 (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1406 \o Rectangle fills with solid color, two-color linear gradients
1407 and simple transforms.
1409 \o Rectangular clipping with simple transformations and intersect
1412 \o Composition Modes \c QPainter::CompositionMode_Source and
1413 QPainter::CompositionMode_SourceOver
1415 \o Rounded rectangle filling using solid color and two-color
1416 linear gradients fills.
1418 \o 3x3 patched pixmaps, via qDrawBorderPixmap.
1422 This list gives an indication of which features to safely use in
1423 an application where performance is critical. For certain setups,
1424 other operations may be fast too, but before making extensive use
1425 of them, it is recommended to benchmark and verify them on the
1426 system where the software will run in the end. There are also
1427 cases where expensive operations are ok to use, for instance when
1428 the result is cached in a QPixmap.
1430 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
1431 {Drawing Utility Functions}
1435 \enum QPainter::RenderHint
1437 Renderhints are used to specify flags to QPainter that may or
1438 may not be respected by any given engine.
1440 \value Antialiasing Indicates that the engine should antialias
1441 edges of primitives if possible.
1443 \value TextAntialiasing Indicates that the engine should antialias
1444 text if possible. To forcibly disable antialiasing for text, do not
1445 use this hint. Instead, set QFont::NoAntialias on your font's style
1448 \value SmoothPixmapTransform Indicates that the engine should use
1449 a smooth pixmap transformation algorithm (such as bilinear) rather
1450 than nearest neighbor.
1452 \value HighQualityAntialiasing An OpenGL-specific rendering hint
1453 indicating that the engine should use fragment programs and offscreen
1454 rendering for antialiasing.
1456 \value NonCosmeticDefaultPen The engine should interpret pens with a width
1457 of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
1458 pen with a width of 1.
1460 \sa renderHints(), setRenderHint(), {QPainter#Rendering
1461 Quality}{Rendering Quality}, {Concentric Circles Example}
1466 Constructs a painter.
1471 QPainter::QPainter()
1472 : d_ptr(new QPainterPrivate(this))
1477 \fn QPainter::QPainter(QPaintDevice *device)
1479 Constructs a painter that begins painting the paint \a device
1482 This constructor is convenient for short-lived painters, e.g. in a
1483 QWidget::paintEvent() and should be used only once. The
1484 constructor calls begin() for you and the QPainter destructor
1485 automatically calls end().
1487 Here's an example using begin() and end():
1488 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 1
1490 The same example using this constructor:
1491 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 2
1493 Since the constructor cannot provide feedback when the initialization
1494 of the painter failed you should rather use begin() and end() to paint
1495 on external devices, e.g. printers.
1500 QPainter::QPainter(QPaintDevice *pd)
1504 if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1505 d_ptr.reset(new QPainterPrivate(this));
1512 Destroys the painter.
1514 QPainter::~QPainter()
1516 d_ptr->inDestructor = true;
1520 else if (d_ptr->refcount > 1)
1521 d_ptr->detachPainterPrivate(this);
1523 // don't throw anything in the destructor.
1526 // Make sure we haven't messed things up.
1527 Q_ASSERT(d_ptr->inDestructor);
1528 d_ptr->inDestructor = false;
1529 Q_ASSERT(d_ptr->refcount == 1);
1531 free(d_ptr->d_ptrs);
1536 Returns the paint device on which this painter is currently
1537 painting, or 0 if the painter is not active.
1542 QPaintDevice *QPainter::device() const
1544 Q_D(const QPainter);
1545 if (isActive() && d->engine->d_func()->currentClipWidget)
1546 return d->engine->d_func()->currentClipWidget;
1547 return d->original_device;
1551 Returns true if begin() has been called and end() has not yet been
1552 called; otherwise returns false.
1554 \sa begin(), QPaintDevice::paintingActive()
1557 bool QPainter::isActive() const
1559 Q_D(const QPainter);
1564 Initializes the painters pen, background and font to the same as
1565 the given \a widget. This function is called automatically when the
1566 painter is opened on a QWidget.
1568 \sa begin(), {QPainter#Settings}{Settings}
1570 void QPainter::initFrom(const QWidget *widget)
1572 Q_ASSERT_X(widget, "QPainter::initFrom(const QWidget *widget)", "Widget cannot be 0");
1575 qWarning("QPainter::initFrom: Painter not active, aborted");
1579 const QPalette &pal = widget->palette();
1580 d->state->pen = QPen(pal.brush(widget->foregroundRole()), 0);
1581 d->state->bgBrush = pal.brush(widget->backgroundRole());
1582 d->state->deviceFont = QFont(widget->font(), const_cast<QWidget*> (widget));
1583 d->state->font = d->state->deviceFont;
1585 d->extended->penChanged();
1586 } else if (d->engine) {
1587 d->engine->setDirty(QPaintEngine::DirtyPen);
1588 d->engine->setDirty(QPaintEngine::DirtyBrush);
1589 d->engine->setDirty(QPaintEngine::DirtyFont);
1595 Saves the current painter state (pushes the state onto a stack). A
1596 save() must be followed by a corresponding restore(); the end()
1597 function unwinds the stack.
1602 void QPainter::save()
1604 #ifdef QT_DEBUG_DRAW
1605 if (qt_show_painter_debug_output)
1606 printf("QPainter::save()\n");
1610 qWarning("QPainter::save: Painter not active");
1615 d->state = d->extended->createState(d->states.back());
1616 d->extended->setState(d->state);
1618 d->updateState(d->state);
1619 d->state = new QPainterState(d->states.back());
1620 d->engine->state = d->state;
1622 d->states.push_back(d->state);
1626 Restores the current painter state (pops a saved state off the
1632 void QPainter::restore()
1634 #ifdef QT_DEBUG_DRAW
1635 if (qt_show_painter_debug_output)
1636 printf("QPainter::restore()\n");
1639 if (d->states.size()<=1) {
1640 qWarning("QPainter::restore: Unbalanced save/restore");
1642 } else if (!d->engine) {
1643 qWarning("QPainter::restore: Painter not active");
1647 QPainterState *tmp = d->state;
1648 d->states.pop_back();
1649 d->state = d->states.back();
1653 d->checkEmulation();
1654 d->extended->setState(d->state);
1659 // trigger clip update if the clip path/region has changed since
1661 if (!d->state->clipInfo.isEmpty()
1662 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1663 // reuse the tmp state to avoid any extra allocs...
1664 tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1665 tmp->clipOperation = Qt::NoClip;
1666 tmp->clipPath = QPainterPath();
1667 d->engine->updateState(*tmp);
1668 // replay the list of clip states,
1669 for (int i=0; i<d->state->clipInfo.size(); ++i) {
1670 const QPainterClipInfo &info = d->state->clipInfo.at(i);
1671 tmp->matrix = info.matrix;
1672 tmp->matrix *= d->state->redirectionMatrix;
1673 tmp->clipOperation = info.operation;
1674 if (info.clipType == QPainterClipInfo::RectClip) {
1675 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1676 tmp->clipRegion = info.rect;
1677 } else if (info.clipType == QPainterClipInfo::RegionClip) {
1678 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1679 tmp->clipRegion = info.region;
1680 } else { // clipType == QPainterClipInfo::PathClip
1681 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1682 tmp->clipPath = info.path;
1684 d->engine->updateState(*tmp);
1688 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1689 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1690 tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1691 tmp->changeFlags |= QPaintEngine::DirtyTransform;
1694 d->updateState(d->state);
1701 \fn bool QPainter::begin(QPaintDevice *device)
1703 Begins painting the paint \a device and returns true if
1704 successful; otherwise returns false.
1706 Notice that all painter settings (setPen(), setBrush() etc.) are reset
1707 to default values when begin() is called.
1709 The errors that can occur are serious problems, such as these:
1711 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 3
1713 Note that most of the time, you can use one of the constructors
1714 instead of begin(), and that end() is automatically done at
1717 \warning A paint device can only be painted by one painter at a
1720 \warning Painting on a QImage with the format
1721 QImage::Format_Indexed8 is not supported.
1723 \sa end(), QPainter()
1726 static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1735 bool QPainter::begin(QPaintDevice *pd)
1739 if (pd->painters > 0) {
1740 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1744 if (d_ptr->engine) {
1745 qWarning("QPainter::begin: Painter already active");
1749 if (QPainterPrivate::attachPainterPrivate(this, pd))
1754 d->helper_device = pd;
1755 d->original_device = pd;
1756 QPaintDevice *rpd = 0;
1758 QPoint redirectionOffset;
1759 // We know for sure that redirection is broken when the widget is inside
1760 // its paint event, so it's safe to use our hard-coded redirection. However,
1761 // there IS one particular case we still need to support, and that's
1762 // when people call QPainter::setRedirected in the widget's paint event right
1763 // before any painter is created (or QPainter::begin is called). In that
1764 // particular case our hard-coded redirection is restored and the redirection
1765 // is retrieved from QPainter::redirected (as before).
1766 if (pd->devType() == QInternal::Widget)
1767 rpd = static_cast<QWidget *>(pd)->d_func()->redirected(&redirectionOffset);
1770 rpd = redirected(pd, &redirectionOffset);
1775 #ifdef QT_DEBUG_DRAW
1776 if (qt_show_painter_debug_output)
1777 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1780 if (pd->devType() == QInternal::Pixmap)
1781 static_cast<QPixmap *>(pd)->detach();
1782 else if (pd->devType() == QInternal::Image)
1783 static_cast<QImage *>(pd)->detach();
1785 d->engine = pd->paintEngine();
1788 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1794 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1795 if (d->emulationEngine)
1796 d->emulationEngine->real_engine = d->extended;
1798 // Setup new state...
1799 Q_ASSERT(!d->state);
1800 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1801 d->state->painter = this;
1802 d->states.push_back(d->state);
1804 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1805 d->state->brushOrigin = QPointF();
1807 // Slip a painter state into the engine before we do any other operations
1809 d->extended->setState(d->state);
1811 d->engine->state = d->state;
1813 switch (pd->devType()) {
1814 case QInternal::Widget:
1816 const QWidget *widget = static_cast<const QWidget *>(pd);
1819 const bool paintOutsidePaintEvent = widget->testAttribute(Qt::WA_PaintOutsidePaintEvent);
1820 const bool inPaintEvent = widget->testAttribute(Qt::WA_WState_InPaintEvent);
1821 if(!d->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent)
1822 && !paintOutsidePaintEvent && !inPaintEvent) {
1823 qWarning("QPainter::begin: Widget painting can only begin as a "
1824 "result of a paintEvent");
1825 qt_cleanup_painter_state(d);
1829 // Adjust offset for alien widgets painting outside the paint event.
1830 if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
1831 && widget->testAttribute(Qt::WA_WState_Created)) {
1832 const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
1833 d->state->redirectionMatrix.translate(offset.x(), offset.y());
1837 case QInternal::Pixmap:
1839 QPixmap *pm = static_cast<QPixmap *>(pd);
1842 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1843 qt_cleanup_painter_state(d);
1847 if (pm->depth() == 1) {
1848 d->state->pen = QPen(Qt::color1);
1849 d->state->brush = QBrush(Qt::color0);
1853 case QInternal::Image:
1855 QImage *img = static_cast<QImage *>(pd);
1857 if (img->isNull()) {
1858 qWarning("QPainter::begin: Cannot paint on a null image");
1859 qt_cleanup_painter_state(d);
1861 } else if (img->format() == QImage::Format_Indexed8) {
1862 // Painting on indexed8 images is not supported.
1863 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1864 qt_cleanup_painter_state(d);
1867 if (img->depth() == 1) {
1868 d->state->pen = QPen(Qt::color1);
1869 d->state->brush = QBrush(Qt::color0);
1876 if (d->state->ww == 0) // For compat with 3.x painter defaults
1877 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1879 d->engine->setPaintDevice(pd);
1881 bool begun = d->engine->begin(pd);
1883 qWarning("QPainter::begin(): Returned false");
1884 if (d->engine->isActive()) {
1887 qt_cleanup_painter_state(d);
1891 d->engine->setActive(begun);
1894 // Copy painter properties from original paint device,
1895 // required for QPixmap::grabWidget()
1896 if (d->original_device->devType() == QInternal::Widget) {
1897 QWidget *widget = static_cast<QWidget *>(d->original_device);
1900 d->state->layoutDirection = Qt::LayoutDirectionAuto;
1901 // make sure we have a font compatible with the paintdevice
1902 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1905 QRect systemRect = d->engine->systemRect();
1906 if (!systemRect.isEmpty()) {
1907 d->state->ww = d->state->vw = systemRect.width();
1908 d->state->wh = d->state->vh = systemRect.height();
1910 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1911 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1914 const QPoint coordinateOffset = d->engine->coordinateOffset();
1915 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1917 Q_ASSERT(d->engine->isActive());
1919 if (!d->state->redirectionMatrix.isIdentity())
1922 Q_ASSERT(d->engine->isActive());
1923 d->state->renderHints = QPainter::TextAntialiasing;
1924 ++d->device->painters;
1926 d->state->emulationSpecifier = 0;
1932 Ends painting. Any resources used while painting are released. You
1933 don't normally need to call this since it is called by the
1936 Returns true if the painter is no longer active; otherwise returns false.
1938 \sa begin(), isActive()
1941 bool QPainter::end()
1943 #ifdef QT_DEBUG_DRAW
1944 if (qt_show_painter_debug_output)
1945 printf("QPainter::end()\n");
1950 qWarning("QPainter::end: Painter not active, aborted");
1951 qt_cleanup_painter_state(d);
1955 if (d->refcount > 1) {
1956 d->detachPainterPrivate(this);
1962 if (d->engine->isActive()) {
1963 ended = d->engine->end();
1966 --d->device->painters;
1967 if (d->device->painters == 0) {
1968 d->engine->setPaintDevice(0);
1969 d->engine->setActive(false);
1973 if (d->states.size() > 1) {
1974 qWarning("QPainter::end: Painter ended with %d saved states",
1978 if (d->engine->autoDestruct()) {
1982 if (d->emulationEngine) {
1983 delete d->emulationEngine;
1984 d->emulationEngine = 0;
1991 qt_cleanup_painter_state(d);
1998 Returns the paint engine that the painter is currently operating
1999 on if the painter is active; otherwise 0.
2003 QPaintEngine *QPainter::paintEngine() const
2005 Q_D(const QPainter);
2012 Flushes the painting pipeline and prepares for the user issuing commands
2013 directly to the underlying graphics context. Must be followed by a call to
2014 endNativePainting().
2016 Note that only the states the underlying paint engine changes will be reset
2017 to their respective default states. The states we reset may change from
2018 release to release. The following states are currently reset in the OpenGL
2022 \i blending is disabled
2023 \i the depth, stencil and scissor tests are disabled
2024 \i the active texture unit is reset to 0
2025 \i the depth mask, depth function and the clear depth are reset to their
2027 \i the stencil mask, stencil operation and stencil function are reset to
2028 their default values
2029 \i the current color is reset to solid white
2032 If, for example, the OpenGL polygon mode is changed by the user inside a
2033 beginNativePaint()/endNativePainting() block, it will not be reset to the
2034 default state by endNativePainting(). Here is an example that shows
2035 intermixing of painter commands and raw OpenGL commands:
2037 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
2039 \sa endNativePainting()
2041 void QPainter::beginNativePainting()
2045 qWarning("QPainter::beginNativePainting: Painter not active");
2050 d->extended->beginNativePainting();
2056 Restores the painter after manually issuing native painting commands. Lets
2057 the painter restore any native state that it relies on before calling any
2058 other painter commands.
2060 \sa beginNativePainting()
2062 void QPainter::endNativePainting()
2064 Q_D(const QPainter);
2066 qWarning("QPainter::beginNativePainting: Painter not active");
2071 d->extended->endNativePainting();
2073 d->engine->syncState();
2077 Returns the font metrics for the painter if the painter is
2078 active. Otherwise, the return value is undefined.
2080 \sa font(), isActive(), {QPainter#Settings}{Settings}
2083 QFontMetrics QPainter::fontMetrics() const
2085 Q_D(const QPainter);
2087 qWarning("QPainter::fontMetrics: Painter not active");
2088 return QFontMetrics(QFont());
2090 return QFontMetrics(d->state->font);
2095 Returns the font info for the painter if the painter is
2096 active. Otherwise, the return value is undefined.
2098 \sa font(), isActive(), {QPainter#Settings}{Settings}
2101 QFontInfo QPainter::fontInfo() const
2103 Q_D(const QPainter);
2105 qWarning("QPainter::fontInfo: Painter not active");
2106 return QFontInfo(QFont());
2108 return QFontInfo(d->state->font);
2114 Returns the opacity of the painter. The default value is
2118 qreal QPainter::opacity() const
2120 Q_D(const QPainter);
2122 qWarning("QPainter::opacity: Painter not active");
2125 return d->state->opacity;
2131 Sets the opacity of the painter to \a opacity. The value should
2132 be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2133 1.0 is fully opaque.
2135 Opacity set on the painter will apply to all drawing operations
2139 void QPainter::setOpacity(qreal opacity)
2144 qWarning("QPainter::setOpacity: Painter not active");
2148 opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2150 if (opacity == d->state->opacity)
2153 d->state->opacity = opacity;
2156 d->extended->opacityChanged();
2158 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2163 Returns the currently set brush origin.
2165 \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2168 QPoint QPainter::brushOrigin() const
2170 Q_D(const QPainter);
2172 qWarning("QPainter::brushOrigin: Painter not active");
2175 return QPointF(d->state->brushOrigin).toPoint();
2179 \fn void QPainter::setBrushOrigin(const QPointF &position)
2181 Sets the brush origin to \a position.
2183 The brush origin specifies the (0, 0) coordinate of the painter's
2186 Note that while the brushOrigin() was necessary to adopt the
2187 parent's background for a widget in Qt 3, this is no longer the
2188 case since the Qt 4 painter doesn't paint the background unless
2189 you explicitly tell it to do so by setting the widget's \l
2190 {QWidget::autoFillBackground}{autoFillBackground} property to
2193 \sa brushOrigin(), {QPainter#Settings}{Settings}
2196 void QPainter::setBrushOrigin(const QPointF &p)
2199 #ifdef QT_DEBUG_DRAW
2200 if (qt_show_painter_debug_output)
2201 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2205 qWarning("QPainter::setBrushOrigin: Painter not active");
2209 d->state->brushOrigin = p;
2212 d->extended->brushOriginChanged();
2216 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2220 \fn void QPainter::setBrushOrigin(const QPoint &position)
2223 Sets the brush's origin to the given \a position.
2227 \fn void QPainter::setBrushOrigin(int x, int y)
2231 Sets the brush's origin to point (\a x, \a y).
2235 \enum QPainter::CompositionMode
2237 Defines the modes supported for digital image compositing.
2238 Composition modes are used to specify how the pixels in one image,
2239 the source, are merged with the pixel in another image, the
2242 Please note that the bitwise raster operation modes, denoted with
2243 a RasterOp prefix, are only natively supported in the X11 and
2244 raster paint engines. This means that the only way to utilize
2245 these modes on the Mac is via a QImage. The RasterOp denoted blend
2246 modes are \e not supported for pens and brushes with alpha
2247 components. Also, turning on the QPainter::Antialiasing render
2248 hint will effectively disable the RasterOp modes.
2251 \image qpainter-compositionmode1.png
2252 \image qpainter-compositionmode2.png
2254 The most common type is SourceOver (often referred to as just
2255 alpha blending) where the source pixel is blended on top of the
2256 destination pixel in such a way that the alpha component of the
2257 source defines the translucency of the pixel.
2259 When the paint device is a QImage, the image format must be set to
2260 \l {QImage::Format}{Format_ARGB32Premultiplied} or
2261 \l {QImage::Format}{Format_ARGB32} for the composition modes to have
2262 any effect. For performance the premultiplied version is the preferred
2265 When a composition mode is set it applies to all painting
2266 operator, pens, brushes, gradients and pixmap/image drawing.
2268 \value CompositionMode_SourceOver This is the default mode. The
2269 alpha of the source is used to blend the pixel on top of the
2272 \value CompositionMode_DestinationOver The alpha of the
2273 destination is used to blend it on top of the source pixels. This
2274 mode is the inverse of CompositionMode_SourceOver.
2276 \value CompositionMode_Clear The pixels in the destination are
2277 cleared (set to fully transparent) independent of the source.
2279 \value CompositionMode_Source The output is the source
2280 pixel. (This means a basic copy operation and is identical to
2281 SourceOver when the source pixel is opaque).
2283 \value CompositionMode_Destination The output is the destination
2284 pixel. This means that the blending has no effect. This mode is
2285 the inverse of CompositionMode_Source.
2287 \value CompositionMode_SourceIn The output is the source, where
2288 the alpha is reduced by that of the destination.
2290 \value CompositionMode_DestinationIn The output is the
2291 destination, where the alpha is reduced by that of the
2292 source. This mode is the inverse of CompositionMode_SourceIn.
2294 \value CompositionMode_SourceOut The output is the source, where
2295 the alpha is reduced by the inverse of destination.
2297 \value CompositionMode_DestinationOut The output is the
2298 destination, where the alpha is reduced by the inverse of the
2299 source. This mode is the inverse of CompositionMode_SourceOut.
2301 \value CompositionMode_SourceAtop The source pixel is blended on
2302 top of the destination, with the alpha of the source pixel reduced
2303 by the alpha of the destination pixel.
2305 \value CompositionMode_DestinationAtop The destination pixel is
2306 blended on top of the source, with the alpha of the destination
2307 pixel is reduced by the alpha of the destination pixel. This mode
2308 is the inverse of CompositionMode_SourceAtop.
2310 \value CompositionMode_Xor The source, whose alpha is reduced with
2311 the inverse of the destination alpha, is merged with the
2312 destination, whose alpha is reduced by the inverse of the source
2313 alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2315 \value CompositionMode_Plus Both the alpha and color of the source
2316 and destination pixels are added together.
2318 \value CompositionMode_Multiply The output is the source color
2319 multiplied by the destination. Multiplying a color with white
2320 leaves the color unchanged, while multiplying a color
2321 with black produces black.
2323 \value CompositionMode_Screen The source and destination colors
2324 are inverted and then multiplied. Screening a color with white
2325 produces white, whereas screening a color with black leaves the
2328 \value CompositionMode_Overlay Multiplies or screens the colors
2329 depending on the destination color. The destination color is mixed
2330 with the source color to reflect the lightness or darkness of the
2333 \value CompositionMode_Darken The darker of the source and
2334 destination colors is selected.
2336 \value CompositionMode_Lighten The lighter of the source and
2337 destination colors is selected.
2339 \value CompositionMode_ColorDodge The destination color is
2340 brightened to reflect the source color. A black source color
2341 leaves the destination color unchanged.
2343 \value CompositionMode_ColorBurn The destination color is darkened
2344 to reflect the source color. A white source color leaves the
2345 destination color unchanged.
2347 \value CompositionMode_HardLight Multiplies or screens the colors
2348 depending on the source color. A light source color will lighten
2349 the destination color, whereas a dark source color will darken the
2352 \value CompositionMode_SoftLight Darkens or lightens the colors
2353 depending on the source color. Similar to
2354 CompositionMode_HardLight.
2356 \value CompositionMode_Difference Subtracts the darker of the
2357 colors from the lighter. Painting with white inverts the
2358 destination color, whereas painting with black leaves the
2359 destination color unchanged.
2361 \value CompositionMode_Exclusion Similar to
2362 CompositionMode_Difference, but with a lower contrast. Painting
2363 with white inverts the destination color, whereas painting with
2364 black leaves the destination color unchanged.
2366 \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2367 the source and destination pixels (src OR dst).
2369 \value RasterOp_SourceAndDestination Does a bitwise AND operation
2370 on the source and destination pixels (src AND dst).
2372 \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2373 on the source and destination pixels (src XOR dst).
2375 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2376 operation on the source and destination pixels ((NOT src) AND (NOT
2379 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2380 operation on the source and destination pixels ((NOT src) OR (NOT
2383 \value RasterOp_NotSourceXorDestination Does a bitwise operation
2384 where the source pixels are inverted and then XOR'ed with the
2385 destination ((NOT src) XOR dst).
2387 \value RasterOp_NotSource Does a bitwise operation where the
2388 source pixels are inverted (NOT src).
2390 \value RasterOp_NotSourceAndDestination Does a bitwise operation
2391 where the source is inverted and then AND'ed with the destination
2392 ((NOT src) AND dst).
2394 \value RasterOp_SourceAndNotDestination Does a bitwise operation
2395 where the source is AND'ed with the inverted destination pixels
2396 (src AND (NOT dst)).
2398 \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2399 Modes}{Composition Modes}, {Image Composition Example}
2403 Sets the composition mode to the given \a mode.
2405 \warning Only a QPainter operating on a QImage fully supports all
2406 composition modes. The RasterOp modes are supported for X11 as
2407 described in compositionMode().
2409 \sa compositionMode()
2411 void QPainter::setCompositionMode(CompositionMode mode)
2415 qWarning("QPainter::setCompositionMode: Painter not active");
2418 if (d->state->composition_mode == mode)
2421 d->state->composition_mode = mode;
2422 d->extended->compositionModeChanged();
2426 if (mode >= QPainter::RasterOp_SourceOrDestination) {
2427 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2428 qWarning("QPainter::setCompositionMode: "
2429 "Raster operation modes not supported on device");
2432 } else if (mode >= QPainter::CompositionMode_Plus) {
2433 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2434 qWarning("QPainter::setCompositionMode: "
2435 "Blend modes not supported on device");
2438 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2439 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2440 qWarning("QPainter::setCompositionMode: "
2441 "PorterDuff modes not supported on device");
2446 d->state->composition_mode = mode;
2447 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2451 Returns the current composition mode.
2453 \sa CompositionMode, setCompositionMode()
2455 QPainter::CompositionMode QPainter::compositionMode() const
2457 Q_D(const QPainter);
2459 qWarning("QPainter::compositionMode: Painter not active");
2460 return QPainter::CompositionMode_SourceOver;
2462 return d->state->composition_mode;
2466 Returns the current background brush.
2468 \sa setBackground(), {QPainter#Settings}{Settings}
2471 const QBrush &QPainter::background() const
2473 Q_D(const QPainter);
2475 qWarning("QPainter::background: Painter not active");
2476 return d->fakeState()->brush;
2478 return d->state->bgBrush;
2483 Returns true if clipping has been set; otherwise returns false.
2485 \sa setClipping(), {QPainter#Clipping}{Clipping}
2488 bool QPainter::hasClipping() const
2490 Q_D(const QPainter);
2492 qWarning("QPainter::hasClipping: Painter not active");
2495 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2500 Enables clipping if \a enable is true, or disables clipping if \a
2503 \sa hasClipping(), {QPainter#Clipping}{Clipping}
2506 void QPainter::setClipping(bool enable)
2509 #ifdef QT_DEBUG_DRAW
2510 if (qt_show_painter_debug_output)
2511 printf("QPainter::setClipping(), enable=%s, was=%s\n",
2512 enable ? "on" : "off",
2513 hasClipping() ? "on" : "off");
2516 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2520 if (hasClipping() == enable)
2523 // we can't enable clipping if we don't have a clip
2525 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2527 d->state->clipEnabled = enable;
2530 d->extended->clipEnabledChanged();
2534 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2535 d->updateState(d->state);
2540 Returns the currently set clip region. Note that the clip region
2541 is given in logical coordinates.
2543 \warning QPainter does not store the combined clip explicitly as
2544 this is handled by the underlying QPaintEngine, so the path is
2545 recreated on demand and transformed to the current logical
2546 coordinate system. This is potentially an expensive operation.
2548 \sa setClipRegion(), clipPath(), setClipping()
2551 QRegion QPainter::clipRegion() const
2553 Q_D(const QPainter);
2555 qWarning("QPainter::clipRegion: Painter not active");
2560 bool lastWasNothing = true;
2563 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2565 // ### Falcon: Use QPainterPath
2566 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2567 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2568 switch (info.clipType) {
2570 case QPainterClipInfo::RegionClip: {
2571 QTransform matrix = (info.matrix * d->invMatrix);
2572 if (lastWasNothing) {
2573 region = info.region * matrix;
2574 lastWasNothing = false;
2577 if (info.operation == Qt::IntersectClip)
2578 region &= info.region * matrix;
2579 else if (info.operation == Qt::UniteClip)
2580 region |= info.region * matrix;
2581 else if (info.operation == Qt::NoClip) {
2582 lastWasNothing = true;
2585 region = info.region * matrix;
2589 case QPainterClipInfo::PathClip: {
2590 QTransform matrix = (info.matrix * d->invMatrix);
2591 if (lastWasNothing) {
2592 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2593 info.path.fillRule());
2594 lastWasNothing = false;
2597 if (info.operation == Qt::IntersectClip) {
2598 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2599 info.path.fillRule());
2600 } else if (info.operation == Qt::UniteClip) {
2601 region |= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2602 info.path.fillRule());
2603 } else if (info.operation == Qt::NoClip) {
2604 lastWasNothing = true;
2607 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2608 info.path.fillRule());
2613 case QPainterClipInfo::RectClip: {
2614 QTransform matrix = (info.matrix * d->invMatrix);
2615 if (lastWasNothing) {
2616 region = QRegion(info.rect) * matrix;
2617 lastWasNothing = false;
2620 if (info.operation == Qt::IntersectClip) {
2621 // Use rect intersection if possible.
2622 if (matrix.type() <= QTransform::TxScale)
2623 region &= matrix.mapRect(info.rect);
2625 region &= matrix.map(QRegion(info.rect));
2626 } else if (info.operation == Qt::UniteClip) {
2627 region |= QRegion(info.rect) * matrix;
2628 } else if (info.operation == Qt::NoClip) {
2629 lastWasNothing = true;
2632 region = QRegion(info.rect) * matrix;
2637 case QPainterClipInfo::RectFClip: {
2638 QTransform matrix = (info.matrix * d->invMatrix);
2639 if (lastWasNothing) {
2640 region = QRegion(info.rectf.toRect()) * matrix;
2641 lastWasNothing = false;
2644 if (info.operation == Qt::IntersectClip) {
2645 // Use rect intersection if possible.
2646 if (matrix.type() <= QTransform::TxScale)
2647 region &= matrix.mapRect(info.rectf.toRect());
2649 region &= matrix.map(QRegion(info.rectf.toRect()));
2650 } else if (info.operation == Qt::UniteClip) {
2651 region |= QRegion(info.rectf.toRect()) * matrix;
2652 } else if (info.operation == Qt::NoClip) {
2653 lastWasNothing = true;
2656 region = QRegion(info.rectf.toRect()) * matrix;
2666 extern QPainterPath qt_regionToPath(const QRegion ®ion);
2669 Returns the currently clip as a path. Note that the clip path is
2670 given in logical coordinates.
2672 \warning QPainter does not store the combined clip explicitly as
2673 this is handled by the underlying QPaintEngine, so the path is
2674 recreated on demand and transformed to the current logical
2675 coordinate system. This is potentially an expensive operation.
2677 \sa setClipPath(), clipRegion(), setClipping()
2679 QPainterPath QPainter::clipPath() const
2681 Q_D(const QPainter);
2683 // ### Since we do not support path intersections and path unions yet,
2684 // we just use clipRegion() here...
2686 qWarning("QPainter::clipPath: Painter not active");
2687 return QPainterPath();
2690 // No clip, return empty
2691 if (d->state->clipInfo.size() == 0) {
2692 return QPainterPath();
2695 // Update inverse matrix, used below.
2697 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2699 // For the simple case avoid conversion.
2700 if (d->state->clipInfo.size() == 1
2701 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2702 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2703 return d->state->clipInfo.at(0).path * matrix;
2705 } else if (d->state->clipInfo.size() == 1
2706 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2707 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2709 path.addRect(d->state->clipInfo.at(0).rect);
2710 return path * matrix;
2712 // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2713 return qt_regionToPath(clipRegion());
2719 Returns the bounding rectangle of the current clip if there is a clip;
2720 otherwise returns an empty rectangle. Note that the clip region is
2721 given in logical coordinates.
2723 The bounding rectangle is not guaranteed to be tight.
2725 \sa setClipRect(), setClipPath(), setClipRegion()
2730 QRectF QPainter::clipBoundingRect() const
2732 Q_D(const QPainter);
2735 qWarning("QPainter::clipBoundingRect: Painter not active");
2739 // Accumulate the bounding box in device space. This is not 100%
2740 // precise, but it fits within the guarantee and it is resonably
2743 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2745 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2747 if (info.clipType == QPainterClipInfo::RectClip)
2749 else if (info.clipType == QPainterClipInfo::RectFClip)
2751 else if (info.clipType == QPainterClipInfo::RegionClip)
2752 r = info.region.boundingRect();
2754 r = info.path.boundingRect();
2756 r = info.matrix.mapRect(r);
2760 else if (info.operation == Qt::IntersectClip)
2762 else if (info.operation == Qt::UniteClip)
2767 // Map the rectangle back into logical space using the inverse
2770 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2772 return d->invMatrix.mapRect(bounds);
2776 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2778 Enables clipping, and sets the clip region to the given \a
2779 rectangle using the given clip \a operation. The default operation
2780 is to replace the current clip rectangle.
2782 Note that the clip rectangle is specified in logical (painter)
2785 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2787 void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2792 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2793 op = Qt::ReplaceClip;
2796 qWarning("QPainter::setClipRect: Painter not active");
2799 qreal right = rect.x() + rect.width();
2800 qreal bottom = rect.y() + rect.height();
2801 qreal pts[] = { rect.x(), rect.y(),
2805 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2806 d->state->clipEnabled = true;
2807 d->extended->clip(vp, op);
2808 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2809 d->state->clipInfo.clear();
2810 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2811 d->state->clipOperation = op;
2815 if (qreal(int(rect.top())) == rect.top()
2816 && qreal(int(rect.bottom())) == rect.bottom()
2817 && qreal(int(rect.left())) == rect.left()
2818 && qreal(int(rect.right())) == rect.right())
2820 setClipRect(rect.toRect(), op);
2824 if (rect.isEmpty()) {
2825 setClipRegion(QRegion(), op);
2831 setClipPath(path, op);
2835 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2838 Enables clipping, and sets the clip region to the given \a rectangle using the given
2841 void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2846 qWarning("QPainter::setClipRect: Painter not active");
2850 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2851 op = Qt::ReplaceClip;
2854 d->state->clipEnabled = true;
2855 d->extended->clip(rect, op);
2856 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2857 d->state->clipInfo.clear();
2858 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2859 d->state->clipOperation = op;
2863 d->state->clipRegion = rect;
2864 d->state->clipOperation = op;
2865 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2866 d->state->clipInfo.clear();
2867 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2868 d->state->clipEnabled = true;
2869 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2870 d->updateState(d->state);
2874 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2876 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2877 with the given \a width and \a height.
2881 \fn void QPainter::setClipRegion(const QRegion ®ion, Qt::ClipOperation operation)
2883 Sets the clip region to the given \a region using the specified clip
2884 \a operation. The default clip operation is to replace the current
2887 Note that the clip region is given in logical coordinates.
2889 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2891 void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2894 #ifdef QT_DEBUG_DRAW
2895 QRect rect = r.boundingRect();
2896 if (qt_show_painter_debug_output)
2897 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2898 r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2901 qWarning("QPainter::setClipRegion: Painter not active");
2905 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2906 op = Qt::ReplaceClip;
2909 d->state->clipEnabled = true;
2910 d->extended->clip(r, op);
2911 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2912 d->state->clipInfo.clear();
2913 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2914 d->state->clipOperation = op;
2918 d->state->clipRegion = r;
2919 d->state->clipOperation = op;
2920 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2921 d->state->clipInfo.clear();
2922 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2923 d->state->clipEnabled = true;
2924 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2925 d->updateState(d->state);
2932 Sets the transformation matrix to \a matrix and enables transformations.
2934 \note It is advisable to use setWorldTransform() instead of this function to
2935 preserve the properties of perspective transformations.
2937 If \a combine is true, then \a matrix is combined with the current
2938 transformation matrix; otherwise \a matrix replaces the current
2939 transformation matrix.
2941 If \a matrix is the identity matrix and \a combine is false, this
2942 function calls setWorldMatrixEnabled(false). (The identity matrix is the
2943 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2946 The following functions can transform the coordinate system without using
2955 They operate on the painter's worldMatrix() and are implemented like this:
2957 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 4
2959 Note that when using setWorldMatrix() function you should always have
2960 \a combine be true when you are drawing into a QPicture. Otherwise
2961 it may not be possible to replay the picture with additional
2962 transformations; using the translate(), scale(), etc. convenience
2965 For more information about the coordinate system, transformations
2966 and window-viewport conversion, see \l {Coordinate System}.
2968 \sa setWorldTransform(), QTransform
2971 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2973 setWorldTransform(QTransform(matrix), combine);
2980 Returns the world transformation matrix.
2982 It is advisable to use worldTransform() because worldMatrix() does not
2983 preserve the properties of perspective transformations.
2985 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2989 const QMatrix &QPainter::worldMatrix() const
2991 Q_D(const QPainter);
2993 qWarning("QPainter::worldMatrix: Painter not active");
2994 return d->fakeState()->transform.toAffine();
2996 return d->state->worldMatrix.toAffine();
3002 Use setWorldTransform() instead.
3004 \sa setWorldTransform()
3007 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
3009 setWorldTransform(QTransform(matrix), combine);
3015 Use worldTransform() instead.
3017 \sa worldTransform()
3020 const QMatrix &QPainter::matrix() const
3022 return worldMatrix();
3030 Returns the transformation matrix combining the current
3031 window/viewport and world transformation.
3033 It is advisable to use combinedTransform() instead of this
3034 function to preserve the properties of perspective transformations.
3036 \sa setWorldTransform(), setWindow(), setViewport()
3038 QMatrix QPainter::combinedMatrix() const
3040 return combinedTransform().toAffine();
3047 Returns the matrix that transforms from logical coordinates to
3048 device coordinates of the platform dependent paint device.
3050 \note It is advisable to use deviceTransform() instead of this
3051 function to preserve the properties of perspective transformations.
3053 This function is \e only needed when using platform painting
3054 commands on the platform dependent handle (Qt::HANDLE), and the
3055 platform does not do transformations nativly.
3057 The QPaintEngine::PaintEngineFeature enum can be queried to
3058 determine whether the platform performs the transformations or
3061 \sa worldMatrix(), QPaintEngine::hasFeature(),
3063 const QMatrix &QPainter::deviceMatrix() const
3065 Q_D(const QPainter);
3067 qWarning("QPainter::deviceMatrix: Painter not active");
3068 return d->fakeState()->transform.toAffine();
3070 return d->state->matrix.toAffine();
3076 Resets any transformations that were made using translate(), scale(),
3077 shear(), rotate(), setWorldMatrix(), setViewport() and
3080 It is advisable to use resetTransform() instead of this function
3081 to preserve the properties of perspective transformations.
3083 \sa {QPainter#Coordinate Transformations}{Coordinate
3087 void QPainter::resetMatrix()
3096 Enables transformations if \a enable is true, or disables
3097 transformations if \a enable is false. The world transformation
3098 matrix is not changed.
3100 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3101 Transformations}{Coordinate Transformations}
3104 void QPainter::setWorldMatrixEnabled(bool enable)
3107 #ifdef QT_DEBUG_DRAW
3108 if (qt_show_painter_debug_output)
3109 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3113 qWarning("QPainter::setMatrixEnabled: Painter not active");
3116 if (enable == d->state->WxF)
3119 d->state->WxF = enable;
3126 Returns true if world transformation is enabled; otherwise returns
3129 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3132 bool QPainter::worldMatrixEnabled() const
3134 Q_D(const QPainter);
3136 qWarning("QPainter::worldMatrixEnabled: Painter not active");
3139 return d->state->WxF;
3145 Use setWorldMatrixEnabled() instead.
3147 \sa setWorldMatrixEnabled()
3150 void QPainter::setMatrixEnabled(bool enable)
3152 setWorldMatrixEnabled(enable);
3158 Use worldMatrixEnabled() instead
3160 \sa worldMatrixEnabled()
3163 bool QPainter::matrixEnabled() const
3165 return worldMatrixEnabled();
3169 Scales the coordinate system by (\a{sx}, \a{sy}).
3171 \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate
3175 void QPainter::scale(qreal sx, qreal sy)
3177 #ifdef QT_DEBUG_DRAW
3178 if (qt_show_painter_debug_output)
3179 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3183 qWarning("QPainter::scale: Painter not active");
3187 d->state->worldMatrix.scale(sx,sy);
3188 d->state->WxF = true;
3193 Shears the coordinate system by (\a{sh}, \a{sv}).
3195 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3199 void QPainter::shear(qreal sh, qreal sv)
3201 #ifdef QT_DEBUG_DRAW
3202 if (qt_show_painter_debug_output)
3203 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3207 qWarning("QPainter::shear: Painter not active");
3211 d->state->worldMatrix.shear(sh, sv);
3212 d->state->WxF = true;
3217 \fn void QPainter::rotate(qreal angle)
3219 Rotates the coordinate system the given \a angle clockwise.
3221 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3225 void QPainter::rotate(qreal a)
3227 #ifdef QT_DEBUG_DRAW
3228 if (qt_show_painter_debug_output)
3229 printf("QPainter::rotate(), angle=%f\n", a);
3233 qWarning("QPainter::rotate: Painter not active");
3237 d->state->worldMatrix.rotate(a);
3238 d->state->WxF = true;
3243 Translates the coordinate system by the given \a offset; i.e. the
3244 given \a offset is added to points.
3246 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3249 void QPainter::translate(const QPointF &offset)
3251 qreal dx = offset.x();
3252 qreal dy = offset.y();
3253 #ifdef QT_DEBUG_DRAW
3254 if (qt_show_painter_debug_output)
3255 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3259 qWarning("QPainter::translate: Painter not active");
3263 d->state->worldMatrix.translate(dx, dy);
3264 d->state->WxF = true;
3269 \fn void QPainter::translate(const QPoint &offset)
3272 Translates the coordinate system by the given \a offset.
3276 \fn void QPainter::translate(qreal dx, qreal dy)
3279 Translates the coordinate system by the vector (\a dx, \a dy).
3283 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3285 Enables clipping, and sets the clip path for the painter to the
3286 given \a path, with the clip \a operation.
3288 Note that the clip path is specified in logical (painter)
3291 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3294 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3296 #ifdef QT_DEBUG_DRAW
3297 if (qt_show_painter_debug_output) {
3298 QRectF b = path.boundingRect();
3299 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3300 path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3306 qWarning("QPainter::setClipPath: Painter not active");
3310 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
3311 op = Qt::ReplaceClip;
3314 d->state->clipEnabled = true;
3315 d->extended->clip(path, op);
3316 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3317 d->state->clipInfo.clear();
3318 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3319 d->state->clipOperation = op;
3323 d->state->clipPath = path;
3324 d->state->clipOperation = op;
3325 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3326 d->state->clipInfo.clear();
3327 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3328 d->state->clipEnabled = true;
3329 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3330 d->updateState(d->state);
3334 Draws the outline (strokes) the path \a path with the pen specified
3337 \sa fillPath(), {QPainter#Drawing}{Drawing}
3339 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3344 qWarning("QPainter::strokePath: Painter not active");
3352 const QGradient *g = qpen_brush(pen).gradient();
3353 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3354 d->extended->stroke(qtVectorPathForPath(path), pen);
3359 QBrush oldBrush = d->state->brush;
3360 QPen oldPen = d->state->pen;
3363 setBrush(Qt::NoBrush);
3373 Fills the given \a path using the given \a brush. The outline is
3376 Alternatively, you can specify a QColor instead of a QBrush; the
3377 QBrush constructor (taking a QColor argument) will automatically
3378 create a solid pattern brush.
3382 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3387 qWarning("QPainter::fillPath: Painter not active");
3395 const QGradient *g = brush.gradient();
3396 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3397 d->extended->fill(qtVectorPathForPath(path), brush);
3402 QBrush oldBrush = d->state->brush;
3403 QPen oldPen = d->state->pen;
3416 Draws the given painter \a path using the current pen for outline
3417 and the current brush for filling.
3421 \o \inlineimage qpainter-path.png
3423 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 5
3426 \sa {painting/painterpaths}{the Painter Paths
3427 example},{demos/deform}{the Vector Deformation demo}
3429 void QPainter::drawPath(const QPainterPath &path)
3431 #ifdef QT_DEBUG_DRAW
3432 QRectF pathBounds = path.boundingRect();
3433 if (qt_show_painter_debug_output)
3434 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3435 path.elementCount(),
3436 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3442 qWarning("QPainter::drawPath: Painter not active");
3447 d->extended->drawPath(path);
3450 d->updateState(d->state);
3452 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3453 d->engine->drawPath(path);
3455 d->draw_helper(path);
3460 \fn void QPainter::drawLine(const QLineF &line)
3462 Draws a line defined by \a line.
3466 \o \inlineimage qpainter-line.png
3468 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 6
3471 \sa drawLines(), drawPolyline(), {Coordinate System}
3475 \fn void QPainter::drawLine(const QLine &line)
3478 Draws a line defined by \a line.
3482 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3485 Draws a line from \a p1 to \a p2.
3489 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3492 Draws a line from \a p1 to \a p2.
3496 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3499 Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3500 current pen position to (\a x2, \a y2).
3504 \fn void QPainter::drawRect(const QRectF &rectangle)
3506 Draws the current \a rectangle with the current pen and brush.
3508 A filled rectangle has a size of \a{rectangle}.size(). A stroked
3509 rectangle has a size of \a{rectangle}.size() plus the pen width.
3513 \o \inlineimage qpainter-rectangle.png
3515 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 7
3518 \sa drawRects(), drawPolygon(), {Coordinate System}
3522 \fn void QPainter::drawRect(const QRect &rectangle)
3526 Draws the current \a rectangle with the current pen and brush.
3530 \fn void QPainter::drawRect(int x, int y, int width, int height)
3534 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3535 with the given \a width and \a height.
3539 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3541 Draws the first \a rectCount of the given \a rectangles using the
3542 current pen and brush.
3546 void QPainter::drawRects(const QRectF *rects, int rectCount)
3548 #ifdef QT_DEBUG_DRAW
3549 if (qt_show_painter_debug_output)
3550 printf("QPainter::drawRects(), count=%d\n", rectCount);
3555 qWarning("QPainter::drawRects: Painter not active");
3563 d->extended->drawRects(rects, rectCount);
3567 d->updateState(d->state);
3569 if (!d->state->emulationSpecifier) {
3570 d->engine->drawRects(rects, rectCount);
3574 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3575 && d->state->matrix.type() == QTransform::TxTranslate) {
3576 for (int i=0; i<rectCount; ++i) {
3577 QRectF r(rects[i].x() + d->state->matrix.dx(),
3578 rects[i].y() + d->state->matrix.dy(),
3581 d->engine->drawRects(&r, 1);
3584 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3585 for (int i=0; i<rectCount; ++i) {
3586 QPainterPath rectPath;
3587 rectPath.addRect(rects[i]);
3588 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3591 QPainterPath rectPath;
3592 for (int i=0; i<rectCount; ++i)
3593 rectPath.addRect(rects[i]);
3594 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3600 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3603 Draws the first \a rectCount of the given \a rectangles using the
3604 current pen and brush.
3606 void QPainter::drawRects(const QRect *rects, int rectCount)
3608 #ifdef QT_DEBUG_DRAW
3609 if (qt_show_painter_debug_output)
3610 printf("QPainter::drawRects(), count=%d\n", rectCount);
3615 qWarning("QPainter::drawRects: Painter not active");
3623 d->extended->drawRects(rects, rectCount);
3627 d->updateState(d->state);
3629 if (!d->state->emulationSpecifier) {
3630 d->engine->drawRects(rects, rectCount);
3634 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3635 && d->state->matrix.type() == QTransform::TxTranslate) {
3636 for (int i=0; i<rectCount; ++i) {
3637 QRectF r(rects[i].x() + d->state->matrix.dx(),
3638 rects[i].y() + d->state->matrix.dy(),
3642 d->engine->drawRects(&r, 1);
3645 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3646 for (int i=0; i<rectCount; ++i) {
3647 QPainterPath rectPath;
3648 rectPath.addRect(rects[i]);
3649 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3652 QPainterPath rectPath;
3653 for (int i=0; i<rectCount; ++i)
3654 rectPath.addRect(rects[i]);
3656 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3662 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3665 Draws the given \a rectangles using the current pen and brush.
3669 \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3673 Draws the given \a rectangles using the current pen and brush.
3677 \fn void QPainter::drawPoint(const QPointF &position)
3679 Draws a single point at the given \a position using the current
3682 \sa {Coordinate System}
3686 \fn void QPainter::drawPoint(const QPoint &position)
3689 Draws a single point at the given \a position using the current
3693 /*! \fn void QPainter::drawPoint(int x, int y)
3697 Draws a single point at position (\a x, \a y).
3701 Draws the first \a pointCount points in the array \a points using
3702 the current pen's color.
3704 \sa {Coordinate System}
3706 void QPainter::drawPoints(const QPointF *points, int pointCount)
3708 #ifdef QT_DEBUG_DRAW
3709 if (qt_show_painter_debug_output)
3710 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3715 qWarning("QPainter::drawPoints: Painter not active");
3719 if (pointCount <= 0)
3723 d->extended->drawPoints(points, pointCount);
3727 d->updateState(d->state);
3729 if (!d->state->emulationSpecifier) {
3730 d->engine->drawPoints(points, pointCount);
3734 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3735 && d->state->matrix.type() == QTransform::TxTranslate) {
3736 // ### use drawPoints function
3737 for (int i=0; i<pointCount; ++i) {
3738 QPointF pt(points[i].x() + d->state->matrix.dx(),
3739 points[i].y() + d->state->matrix.dy());
3740 d->engine->drawPoints(&pt, 1);
3743 QPen pen = d->state->pen;
3744 bool flat_pen = pen.capStyle() == Qt::FlatCap;
3747 pen.setCapStyle(Qt::SquareCap);
3751 for (int i=0; i<pointCount; ++i) {
3752 path.moveTo(points[i].x(), points[i].y());
3753 path.lineTo(points[i].x() + 0.0001, points[i].y());
3755 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3764 Draws the first \a pointCount points in the array \a points using
3765 the current pen's color.
3768 void QPainter::drawPoints(const QPoint *points, int pointCount)
3770 #ifdef QT_DEBUG_DRAW
3771 if (qt_show_painter_debug_output)
3772 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3777 qWarning("QPainter::drawPoints: Painter not active");
3781 if (pointCount <= 0)
3785 d->extended->drawPoints(points, pointCount);
3789 d->updateState(d->state);
3791 if (!d->state->emulationSpecifier) {
3792 d->engine->drawPoints(points, pointCount);
3796 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3797 && d->state->matrix.type() == QTransform::TxTranslate) {
3798 // ### use drawPoints function
3799 for (int i=0; i<pointCount; ++i) {
3800 QPointF pt(points[i].x() + d->state->matrix.dx(),
3801 points[i].y() + d->state->matrix.dy());
3802 d->engine->drawPoints(&pt, 1);
3805 QPen pen = d->state->pen;
3806 bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3809 pen.setCapStyle(Qt::SquareCap);
3813 for (int i=0; i<pointCount; ++i) {
3814 path.moveTo(points[i].x(), points[i].y());
3815 path.lineTo(points[i].x() + 0.0001, points[i].y());
3817 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3824 \fn void QPainter::drawPoints(const QPolygonF &points)
3828 Draws the points in the vector \a points.
3832 \fn void QPainter::drawPoints(const QPolygon &points)
3836 Draws the points in the vector \a points.
3840 \fn void QPainter::drawPoints(const QPolygon &polygon, int index,
3846 Draws \a count points in the vector \a polygon starting on \a index
3847 using the current pen.
3849 Use drawPoints() combined with QPolygon::constData() instead.
3852 QPainter painter(this);
3853 painter.drawPoints(polygon, index, count);
3855 int pointCount = (count == -1) ? polygon.size() - index : count;
3857 QPainter painter(this);
3858 painter.drawPoints(polygon.constData() + index, pointCount);
3863 Sets the background mode of the painter to the given \a mode
3865 Qt::TransparentMode (the default) draws stippled lines and text
3866 without setting the background pixels. Qt::OpaqueMode fills these
3867 space with the current background color.
3869 Note that in order to draw a bitmap or pixmap transparently, you
3870 must use QPixmap::setMask().
3872 \sa backgroundMode(), setBackground(),
3873 {QPainter#Settings}{Settings}
3876 void QPainter::setBackgroundMode(Qt::BGMode mode)
3878 #ifdef QT_DEBUG_DRAW
3879 if (qt_show_painter_debug_output)
3880 printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3885 qWarning("QPainter::setBackgroundMode: Painter not active");
3888 if (d->state->bgMode == mode)
3891 d->state->bgMode = mode;
3893 d->checkEmulation();
3895 d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3900 Returns the current background mode.
3902 \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3904 Qt::BGMode QPainter::backgroundMode() const
3906 Q_D(const QPainter);
3908 qWarning("QPainter::backgroundMode: Painter not active");
3909 return Qt::TransparentMode;
3911 return d->state->bgMode;
3918 Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3922 void QPainter::setPen(const QColor &color)
3924 #ifdef QT_DEBUG_DRAW
3925 if (qt_show_painter_debug_output)
3926 printf("QPainter::setPen(), color=%04x\n", color.rgb());
3930 qWarning("QPainter::setPen: Painter not active");
3934 if (d->state->pen.style() == Qt::SolidLine
3935 && d->state->pen.widthF() == 0
3936 && d->state->pen.isSolid()
3937 && d->state->pen.color() == color)
3940 QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
3942 d->state->pen = pen;
3944 d->extended->penChanged();
3946 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3950 Sets the painter's pen to be the given \a pen.
3952 The \a pen defines how to draw lines and outlines, and it also
3953 defines the text color.
3955 \sa pen(), {QPainter#Settings}{Settings}
3958 void QPainter::setPen(const QPen &pen)
3961 #ifdef QT_DEBUG_DRAW
3962 if (qt_show_painter_debug_output)
3963 printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3964 pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3968 qWarning("QPainter::setPen: Painter not active");
3972 if (d->state->pen == pen)
3975 d->state->pen = pen;
3978 d->checkEmulation();
3979 d->extended->penChanged();
3983 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3989 Sets the painter's pen to have the given \a style, width 0 and
3993 void QPainter::setPen(Qt::PenStyle style)
3997 qWarning("QPainter::setPen: Painter not active");
4001 if (d->state->pen.style() == style
4002 && (style == Qt::NoPen || (d->state->pen.widthF() == 0
4003 && d->state->pen.isSolid()
4004 && d->state->pen.color() == QColor(Qt::black))))
4007 // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
4008 // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
4009 d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
4012 d->extended->penChanged();
4014 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
4019 Returns the painter's current pen.
4021 \sa setPen(), {QPainter#Settings}{Settings}
4024 const QPen &QPainter::pen() const
4026 Q_D(const QPainter);
4028 qWarning("QPainter::pen: Painter not active");
4029 return d->fakeState()->pen;
4031 return d->state->pen;
4036 Sets the painter's brush to the given \a brush.
4038 The painter's brush defines how shapes are filled.
4040 \sa brush(), {QPainter#Settings}{Settings}
4043 void QPainter::setBrush(const QBrush &brush)
4045 #ifdef QT_DEBUG_DRAW
4046 if (qt_show_painter_debug_output)
4047 printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
4051 qWarning("QPainter::setBrush: Painter not active");
4055 if (d->state->brush.d == brush.d)
4059 d->state->brush = brush;
4060 d->checkEmulation();
4061 d->extended->brushChanged();
4065 d->state->brush = brush;
4066 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4073 Sets the painter's brush to black color and the specified \a
4077 void QPainter::setBrush(Qt::BrushStyle style)
4081 qWarning("QPainter::setBrush: Painter not active");
4084 if (d->state->brush.style() == style &&
4085 (style == Qt::NoBrush
4086 || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
4088 d->state->brush = QBrush(Qt::black, style);
4090 d->extended->brushChanged();
4092 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4096 Returns the painter's current brush.
4098 \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
4101 const QBrush &QPainter::brush() const
4103 Q_D(const QPainter);
4105 qWarning("QPainter::brush: Painter not active");
4106 return d->fakeState()->brush;
4108 return d->state->brush;
4112 \fn void QPainter::setBackground(const QBrush &brush)
4114 Sets the background brush of the painter to the given \a brush.
4116 The background brush is the brush that is filled in when drawing
4117 opaque text, stippled lines and bitmaps. The background brush has
4118 no effect in transparent background mode (which is the default).
4120 \sa background(), setBackgroundMode(),
4121 {QPainter#Settings}{Settings}
4124 void QPainter::setBackground(const QBrush &bg)
4126 #ifdef QT_DEBUG_DRAW
4127 if (qt_show_painter_debug_output)
4128 printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4133 qWarning("QPainter::setBackground: Painter not active");
4136 d->state->bgBrush = bg;
4138 d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4142 Sets the painter's font to the given \a font.
4144 This font is used by subsequent drawText() functions. The text
4145 color is the same as the pen color.
4147 If you set a font that isn't available, Qt finds a close match.
4148 font() will return what you set using setFont() and fontInfo() returns the
4149 font actually being used (which may be the same).
4151 \sa font(), drawText(), {QPainter#Settings}{Settings}
4154 void QPainter::setFont(const QFont &font)
4158 #ifdef QT_DEBUG_DRAW
4159 if (qt_show_painter_debug_output)
4160 printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4164 qWarning("QPainter::setFont: Painter not active");
4168 d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4170 d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4174 Returns the currently set font used for drawing text.
4176 \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4178 const QFont &QPainter::font() const
4180 Q_D(const QPainter);
4182 qWarning("QPainter::font: Painter not active");
4183 return d->fakeState()->font;
4185 return d->state->font;
4191 Draws the given rectangle \a rect with rounded corners.
4193 The \a xRadius and \a yRadius arguments specify the radii
4194 of the ellipses defining the corners of the rounded rectangle.
4195 When \a mode is Qt::RelativeSize, \a xRadius and
4196 \a yRadius are specified in percentage of half the rectangle's
4197 width and height respectively, and should be in the range
4200 A filled rectangle has a size of rect.size(). A stroked rectangle
4201 has a size of rect.size() plus the pen width.
4205 \o \inlineimage qpainter-roundrect.png
4207 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 8
4210 \sa drawRect(), QPen
4212 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4214 #ifdef QT_DEBUG_DRAW
4215 if (qt_show_painter_debug_output)
4216 printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4223 if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
4229 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4234 path.addRoundedRect(rect, xRadius, yRadius, mode);
4239 \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4240 Qt::SizeMode mode = Qt::AbsoluteSize);
4244 Draws the given rectangle \a rect with rounded corners.
4248 \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4249 Qt::SizeMode mode = Qt::AbsoluteSize);
4253 Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4259 Draws a rectangle \a r with rounded corners.
4261 The \a xRnd and \a yRnd arguments specify how rounded the corners
4262 should be. 0 is angled corners, 99 is maximum roundedness.
4264 A filled rectangle has a size of r.size(). A stroked rectangle
4265 has a size of r.size() plus the pen width.
4267 \sa drawRoundedRect()
4269 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4271 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4276 \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4281 Draws the rectangle \a r with rounded corners.
4287 \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4291 Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4295 \fn void QPainter::drawEllipse(const QRectF &rectangle)
4297 Draws the ellipse defined by the given \a rectangle.
4299 A filled ellipse has a size of \a{rectangle}.\l
4300 {QRect::size()}{size()}. A stroked ellipse has a size of
4301 \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4305 \o \inlineimage qpainter-ellipse.png
4307 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 9
4310 \sa drawPie(), {Coordinate System}
4312 void QPainter::drawEllipse(const QRectF &r)
4314 #ifdef QT_DEBUG_DRAW
4315 if (qt_show_painter_debug_output)
4316 printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4323 QRectF rect(r.normalized());
4326 d->extended->drawEllipse(rect);
4330 d->updateState(d->state);
4331 if (d->state->emulationSpecifier) {
4332 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4333 && d->state->matrix.type() == QTransform::TxTranslate) {
4334 rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4337 path.addEllipse(rect);
4338 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4343 d->engine->drawEllipse(rect);
4347 \fn QPainter::drawEllipse(const QRect &rectangle)
4351 Draws the ellipse defined by the given \a rectangle.
4353 void QPainter::drawEllipse(const QRect &r)
4355 #ifdef QT_DEBUG_DRAW
4356 if (qt_show_painter_debug_output)
4357 printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4364 QRect rect(r.normalized());
4367 d->extended->drawEllipse(rect);
4371 d->updateState(d->state);
4373 if (d->state->emulationSpecifier) {
4374 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4375 && d->state->matrix.type() == QTransform::TxTranslate) {
4376 rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4379 path.addEllipse(rect);
4380 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4385 d->engine->drawEllipse(rect);
4389 \fn QPainter::drawEllipse(int x, int y, int width, int height)
4393 Draws the ellipse defined by the rectangle beginning at (\a{x},
4394 \a{y}) with the given \a width and \a height.
4400 \fn QPainter::drawEllipse(const QPointF ¢er, qreal rx, qreal ry)
4404 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4410 \fn QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)
4414 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4418 \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4420 Draws the arc defined by the given \a rectangle, \a startAngle and
4423 The \a startAngle and \a spanAngle must be specified in 1/16th of
4424 a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4425 values for the angles mean counter-clockwise while negative values
4426 mean the clockwise direction. Zero degrees is at the 3 o'clock
4431 \o \inlineimage qpainter-arc.png
4433 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 10
4436 \sa drawPie(), drawChord(), {Coordinate System}
4439 void QPainter::drawArc(const QRectF &r, int a, int alen)
4441 #ifdef QT_DEBUG_DRAW
4442 if (qt_show_painter_debug_output)
4443 printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4444 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4451 QRectF rect = r.normalized();
4454 path.arcMoveTo(rect, a/16.0);
4455 path.arcTo(rect, a/16.0, alen/16.0);
4456 strokePath(path, d->state->pen);
4459 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4464 Draws the arc defined by the given \a rectangle, \a startAngle and
4469 \fn void QPainter::drawArc(int x, int y, int width, int height,
4470 int startAngle, int spanAngle)
4474 Draws the arc defined by the rectangle beginning at (\a x, \a y)
4475 with the specified \a width and \a height, and the given \a
4476 startAngle and \a spanAngle.
4480 \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4482 Draws a pie defined by the given \a rectangle, \a startAngle and
4485 The pie is filled with the current brush().
4487 The startAngle and spanAngle must be specified in 1/16th of a
4488 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4489 for the angles mean counter-clockwise while negative values mean
4490 the clockwise direction. Zero degrees is at the 3 o'clock
4495 \o \inlineimage qpainter-pie.png
4497 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 11
4500 \sa drawEllipse(), drawChord(), {Coordinate System}
4502 void QPainter::drawPie(const QRectF &r, int a, int alen)
4504 #ifdef QT_DEBUG_DRAW
4505 if (qt_show_painter_debug_output)
4506 printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4507 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4518 if (a < 0) a += (360*16);
4521 QRectF rect = r.normalized();
4524 path.moveTo(rect.center());
4525 path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4526 path.closeSubpath();
4532 \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4535 Draws a pie defined by the given \a rectangle, \a startAngle and
4540 \fn void QPainter::drawPie(int x, int y, int width, int height, int
4541 startAngle, int spanAngle)
4545 Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4546 the specified \a width and \a height, and the given \a startAngle and
4551 \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4553 Draws the chord defined by the given \a rectangle, \a startAngle and
4554 \a spanAngle. The chord is filled with the current brush().
4556 The startAngle and spanAngle must be specified in 1/16th of a
4557 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4558 for the angles mean counter-clockwise while negative values mean
4559 the clockwise direction. Zero degrees is at the 3 o'clock
4564 \o \inlineimage qpainter-chord.png
4566 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 12
4569 \sa drawArc(), drawPie(), {Coordinate System}
4571 void QPainter::drawChord(const QRectF &r, int a, int alen)
4573 #ifdef QT_DEBUG_DRAW
4574 if (qt_show_painter_debug_output)
4575 printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4576 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4583 QRectF rect = r.normalized();
4586 path.arcMoveTo(rect, a/16.0);
4587 path.arcTo(rect, a/16.0, alen/16.0);
4588 path.closeSubpath();
4592 \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4596 Draws the chord defined by the given \a rectangle, \a startAngle and
4601 \fn void QPainter::drawChord(int x, int y, int width, int height, int
4602 startAngle, int spanAngle)
4606 Draws the chord defined by the rectangle beginning at (\a x, \a y)
4607 with the specified \a width and \a height, and the given \a
4608 startAngle and \a spanAngle.
4613 \fn void QPainter::drawLineSegments(const QPolygon &polygon, int
4616 Draws \a count separate lines from points defined by the \a
4617 polygon, starting at \a{polygon}\e{[index]} (\a index defaults to
4618 0). If \a count is -1 (the default) all points until the end of
4621 Use drawLines() combined with QPolygon::constData() instead.
4624 QPainter painter(this);
4625 painter.drawLineSegments(polygon, index, count);
4627 int lineCount = (count == -1) ? (polygon.size() - index) / 2 : count;
4629 QPainter painter(this);
4630 painter.drawLines(polygon.constData() + index * 2, lineCount);
4634 void QPainter::drawLineSegments(const QPolygon &a, int index, int nlines)
4636 #ifdef QT_DEBUG_DRAW
4637 if (qt_show_painter_debug_output)
4638 printf("QPainter::drawLineSegments(), count=%d\n", a.size()/2);
4646 nlines = a.size()/2 - index/2;
4647 if (index + nlines*2 > (int)a.size())
4648 nlines = (a.size() - index)/2;
4649 if (nlines < 1 || index < 0)
4653 // FALCON: Use QVectorPath
4654 QVector<QLineF> lines;
4655 for (int i=index; i<index + nlines*2; i+=2)
4656 lines << QLineF(a.at(i), a.at(i+1));
4657 d->extended->drawLines(lines.data(), lines.size());
4661 d->updateState(d->state);
4663 QVector<QLineF> lines;
4664 if (d->state->emulationSpecifier) {
4665 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4666 && d->state->matrix.type() == QTransform::TxTranslate) {
4667 QPointF offset(d->state->matrix.dx(), d->state->matrix.dy());
4668 for (int i=index; i<index + nlines*2; i+=2)
4669 lines << QLineF(a.at(i) + offset, a.at(i+1) + offset);
4671 QPainterPath linesPath;
4672 for (int i=index; i<index + nlines*2; i+=2) {
4673 linesPath.moveTo(a.at(i));
4674 linesPath.lineTo(a.at(i+1));
4676 d->draw_helper(linesPath, QPainterPrivate::StrokeDraw);
4680 for (int i=index; i<index + nlines*2; i+=2)
4681 lines << QLineF(a.at(i), a.at(i+1));
4684 d->engine->drawLines(lines.data(), lines.size());
4686 #endif // QT3_SUPPORT
4689 Draws the first \a lineCount lines in the array \a lines
4690 using the current pen.
4692 \sa drawLine(), drawPolyline()
4694 void QPainter::drawLines(const QLineF *lines, int lineCount)
4696 #ifdef QT_DEBUG_DRAW
4697 if (qt_show_painter_debug_output)
4698 printf("QPainter::drawLines(), line count=%d\n", lineCount);
4703 if (!d->engine || lineCount < 1)
4707 d->extended->drawLines(lines, lineCount);
4711 d->updateState(d->state);
4713 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4715 if (lineEmulation) {
4716 if (lineEmulation == QPaintEngine::PrimitiveTransform
4717 && d->state->matrix.type() == QTransform::TxTranslate) {
4718 for (int i = 0; i < lineCount; ++i) {
4719 QLineF line = lines[i];
4720 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4721 d->engine->drawLines(&line, 1);
4724 QPainterPath linePath;
4725 for (int i = 0; i < lineCount; ++i) {
4726 linePath.moveTo(lines[i].p1());
4727 linePath.lineTo(lines[i].p2());
4729 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4733 d->engine->drawLines(lines, lineCount);
4737 \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4740 Draws the first \a lineCount lines in the array \a lines
4741 using the current pen.
4743 void QPainter::drawLines(const QLine *lines, int lineCount)
4745 #ifdef QT_DEBUG_DRAW
4746 if (qt_show_painter_debug_output)
4747 printf("QPainter::drawLine(), line count=%d\n", lineCount);
4752 if (!d->engine || lineCount < 1)
4756 d->extended->drawLines(lines, lineCount);
4760 d->updateState(d->state);
4762 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4764 if (lineEmulation) {
4765 if (lineEmulation == QPaintEngine::PrimitiveTransform
4766 && d->state->matrix.type() == QTransform::TxTranslate) {
4767 for (int i = 0; i < lineCount; ++i) {
4768 QLineF line = lines[i];
4769 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4770 d->engine->drawLines(&line, 1);
4773 QPainterPath linePath;
4774 for (int i = 0; i < lineCount; ++i) {
4775 linePath.moveTo(lines[i].p1());
4776 linePath.lineTo(lines[i].p2());
4778 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4782 d->engine->drawLines(lines, lineCount);
4788 Draws the first \a lineCount lines in the array \a pointPairs
4789 using the current pen. The lines are specified as pairs of points
4790 so the number of entries in \a pointPairs must be at least \a
4793 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4795 Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4797 drawLines((QLineF*)pointPairs, lineCount);
4803 Draws the first \a lineCount lines in the array \a pointPairs
4804 using the current pen.
4806 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4808 Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4810 drawLines((QLine*)pointPairs, lineCount);
4815 \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4818 Draws a line for each pair of points in the vector \a pointPairs
4819 using the current pen. If there is an odd number of points in the
4820 array, the last point will be ignored.
4824 \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4827 Draws a line for each pair of points in the vector \a pointPairs
4828 using the current pen.
4832 \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4835 Draws the set of lines defined by the list \a lines using the
4836 current pen and brush.
4840 \fn void QPainter::drawLines(const QVector<QLine> &lines)
4843 Draws the set of lines defined by the list \a lines using the
4844 current pen and brush.
4848 Draws the polyline defined by the first \a pointCount points in \a
4849 points using the current pen.
4851 Note that unlike the drawPolygon() function the last point is \e
4852 not connected to the first, neither is the polyline filled.
4857 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 13
4860 \sa drawLines(), drawPolygon(), {Coordinate System}
4862 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4864 #ifdef QT_DEBUG_DRAW
4865 if (qt_show_painter_debug_output)
4866 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4870 if (!d->engine || pointCount < 2)
4874 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4878 d->updateState(d->state);
4880 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4882 if (lineEmulation) {
4884 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4885 // && d->state->matrix.type() == QTransform::TxTranslate) {
4887 QPainterPath polylinePath(points[0]);
4888 for (int i=1; i<pointCount; ++i)
4889 polylinePath.lineTo(points[i]);
4890 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4893 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4900 Draws the polyline defined by the first \a pointCount points in \a
4901 points using the current pen.
4903 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4905 #ifdef QT_DEBUG_DRAW
4906 if (qt_show_painter_debug_output)
4907 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4911 if (!d->engine || pointCount < 2)
4915 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4919 d->updateState(d->state);
4921 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4923 if (lineEmulation) {
4925 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4926 // && d->state->matrix.type() == QTransform::TxTranslate) {
4928 QPainterPath polylinePath(points[0]);
4929 for (int i=1; i<pointCount; ++i)
4930 polylinePath.lineTo(points[i]);
4931 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4934 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4939 \fn void QPainter::drawPolyline(const QPolygon &polygon, int index, int
4945 Draws the polyline defined by the \a count lines of the given \a
4946 polygon starting at \a index (\a index defaults to 0).
4948 Use drawPolyline() combined with QPolygon::constData() instead.
4951 QPainter painter(this);
4952 painter.drawPolyline(polygon, index, count);
4954 int pointCount = (count == -1) ? polygon.size() - index : count;
4956 QPainter painter(this);
4957 painter.drawPolyline(polygon.constData() + index, pointCount);
4962 \fn void QPainter::drawPolyline(const QPolygonF &points)
4966 Draws the polyline defined by the given \a points using the
4971 \fn void QPainter::drawPolyline(const QPolygon &points)
4975 Draws the polyline defined by the given \a points using the
4980 Draws the polygon defined by the first \a pointCount points in the
4981 array \a points using the current pen and brush.
4985 \o \inlineimage qpainter-polygon.png
4987 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 14
4990 The first point is implicitly connected to the last point, and the
4991 polygon is filled with the current brush().
4993 If \a fillRule is Qt::WindingFill, the polygon is filled using the
4994 winding fill algorithm. If \a fillRule is Qt::OddEvenFill, the
4995 polygon is filled using the odd-even fill algorithm. See
4996 \l{Qt::FillRule} for a more detailed description of these fill
4999 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
5001 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
5003 #ifdef QT_DEBUG_DRAW
5004 if (qt_show_painter_debug_output)
5005 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
5010 if (!d->engine || pointCount < 2)
5014 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5018 d->updateState(d->state);
5020 uint emulationSpecifier = d->state->emulationSpecifier;
5022 if (emulationSpecifier) {
5023 QPainterPath polygonPath(points[0]);
5024 for (int i=1; i<pointCount; ++i)
5025 polygonPath.lineTo(points[i]);
5026 polygonPath.closeSubpath();
5027 polygonPath.setFillRule(fillRule);
5028 d->draw_helper(polygonPath);
5032 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5037 Draws the polygon defined by the first \a pointCount points in the
5040 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
5042 #ifdef QT_DEBUG_DRAW
5043 if (qt_show_painter_debug_output)
5044 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
5049 if (!d->engine || pointCount < 2)
5053 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5057 d->updateState(d->state);
5059 uint emulationSpecifier = d->state->emulationSpecifier;
5061 if (emulationSpecifier) {
5062 QPainterPath polygonPath(points[0]);
5063 for (int i=1; i<pointCount; ++i)
5064 polygonPath.lineTo(points[i]);
5065 polygonPath.closeSubpath();
5066 polygonPath.setFillRule(fillRule);
5067 d->draw_helper(polygonPath);
5071 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5074 /*! \fn void QPainter::drawPolygon(const QPolygonF &polygon, bool winding, int index = 0,
5079 Use drawPolygon() combined with QPolygonF::constData() instead.
5082 QPainter painter(this);
5083 painter.drawPolygon(polygon, winding, index, count);
5085 int pointCount = (count == -1) ? polygon.size() - index : count;
5086 int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
5088 QPainter painter(this);
5089 painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
5093 /*! \fn void QPainter::drawPolygon(const QPolygon &polygon, bool winding,
5094 int index = 0, int count = -1)
5099 Use drawPolygon() combined with QPolygon::constData() instead.
5102 QPainter painter(this);
5103 painter.drawPolygon(polygon, winding, index, count);
5105 int pointCount = (count == -1) ? polygon.size() - index : count;
5106 int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
5108 QPainter painter(this);
5109 painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
5113 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
5117 Draws the polygon defined by the given \a points using the fill
5121 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
5125 Draws the polygon defined by the given \a points using the fill
5130 \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
5132 Draws the convex polygon defined by the first \a pointCount points
5133 in the array \a points using the current pen.
5137 \o \inlineimage qpainter-polygon.png
5139 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 15
5142 The first point is implicitly connected to the last point, and the
5143 polygon is filled with the current brush(). If the supplied
5144 polygon is not convex, i.e. it contains at least one angle larger
5145 than 180 degrees, the results are undefined.
5147 On some platforms (e.g. X11), the drawConvexPolygon() function can
5148 be faster than the drawPolygon() function.
5150 \sa drawPolygon(), drawPolyline(), {Coordinate System}
5154 \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
5157 Draws the convex polygon defined by the first \a pointCount points
5158 in the array \a points using the current pen.
5162 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
5166 Draws the convex polygon defined by \a polygon using the current
5171 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
5174 Draws the convex polygon defined by \a polygon using the current
5179 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon, int
5185 Use drawConvexPolygon() combined with QPolygonF::constData()
5189 QPainter painter(this);
5190 painter.drawConvexPolygon(polygon, index, count);
5192 int pointCount = (count == -1) ? polygon.size() - index : count;
5194 QPainter painter(this);
5195 painter.drawConvexPolygon(polygon.constData() + index, pointCount);
5200 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon, int
5206 Use drawConvexPolygon() combined with QPolygon::constData()
5210 QPainter painter(this);
5211 painter.drawConvexPolygon(polygon, index, count);
5213 int pointCount = (count == -1) ? polygon.size() - index : count;
5215 QPainter painter(this);
5216 painter.drawConvexPolygon(polygon.constData() + index, pointCount);
5220 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
5222 #ifdef QT_DEBUG_DRAW
5223 if (qt_show_painter_debug_output)
5224 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5229 if (!d->engine || pointCount < 2)
5233 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5237 d->updateState(d->state);
5239 uint emulationSpecifier = d->state->emulationSpecifier;
5241 if (emulationSpecifier) {
5242 QPainterPath polygonPath(points[0]);
5243 for (int i=1; i<pointCount; ++i)
5244 polygonPath.lineTo(points[i]);
5245 polygonPath.closeSubpath();
5246 polygonPath.setFillRule(Qt::WindingFill);
5247 d->draw_helper(polygonPath);
5251 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5254 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
5256 #ifdef QT_DEBUG_DRAW
5257 if (qt_show_painter_debug_output)
5258 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5263 if (!d->engine || pointCount < 2)
5267 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5271 d->updateState(d->state);
5273 uint emulationSpecifier = d->state->emulationSpecifier;
5275 if (emulationSpecifier) {
5276 QPainterPath polygonPath(points[0]);
5277 for (int i=1; i<pointCount; ++i)
5278 polygonPath.lineTo(points[i]);
5279 polygonPath.closeSubpath();
5280 polygonPath.setFillRule(Qt::WindingFill);
5281 d->draw_helper(polygonPath);
5285 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5288 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5290 return m.inverted().map(QPointF(m.map(p).toPoint()));
5294 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5296 Draws the rectangular portion \a source of the given \a pixmap
5297 into the given \a target in the paint device.
5299 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5304 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 16
5307 If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5308 using the pens color. If backgroundMode is Qt::OpaqueMode, the
5309 "unset" bits are drawn using the color of the background brush; if
5310 backgroundMode is Qt::TransparentMode, the "unset" bits are
5311 transparent. Drawing bitmaps with gradient or texture colors is
5316 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5318 #if defined QT_DEBUG_DRAW
5319 if (qt_show_painter_debug_output)
5320 printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5322 pm.width(), pm.height());
5327 if (!d->engine || pm.isNull())
5331 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5335 d->extended->drawPixmap(p, pm);
5343 int h = pm.height();
5348 // Emulate opaque background for bitmaps
5349 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5350 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5353 d->updateState(d->state);
5355 if ((d->state->matrix.type() > QTransform::TxTranslate
5356 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5357 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5358 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5361 // If there is no rotation involved we have to make sure we use the
5362 // antialiased and not the aliased coordinate system by rounding the coordinates.
5363 if (d->state->matrix.type() <= QTransform::TxScale) {
5364 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5369 setBackgroundMode(Qt::TransparentMode);
5370 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5371 QBrush brush(d->state->pen.color(), pm);
5374 setBrushOrigin(QPointF(0, 0));
5376 drawRect(pm.rect());
5379 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5380 x += d->state->matrix.dx();
5381 y += d->state->matrix.dy();
5383 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5387 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5389 #if defined QT_DEBUG_DRAW
5390 if (qt_show_painter_debug_output)
5391 printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5392 r.x(), r.y(), r.width(), r.height(),
5393 pm.width(), pm.height(),
5394 sr.x(), sr.y(), sr.width(), sr.height());
5398 if (!d->engine || pm.isNull())
5401 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5406 qreal w = r.width();
5407 qreal h = r.height();
5410 qreal sw = sr.width();
5411 qreal sh = sr.height();
5413 // Sanity-check clipping
5415 sw = pm.width() - sx;
5418 sh = pm.height() - sy;
5426 qreal w_ratio = sx * w/sw;
5434 qreal h_ratio = sy * h/sh;
5441 if (sw + sx > pm.width()) {
5442 qreal delta = sw - (pm.width() - sx);
5443 qreal w_ratio = delta * w/sw;
5448 if (sh + sy > pm.height()) {
5449 qreal delta = sh - (pm.height() - sy);
5450 qreal h_ratio = delta * h/sh;
5455 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5459 d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5463 // Emulate opaque background for bitmaps
5464 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5465 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5467 d->updateState(d->state);
5469 if ((d->state->matrix.type() > QTransform::TxTranslate
5470 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5471 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5472 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5473 || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5476 // If there is no rotation involved we have to make sure we use the
5477 // antialiased and not the aliased coordinate system by rounding the coordinates.
5478 if (d->state->matrix.type() <= QTransform::TxScale) {
5479 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5484 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5492 scale(w / sw, h / sh);
5493 setBackgroundMode(Qt::TransparentMode);
5494 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5497 if (sw == pm.width() && sh == pm.height())
5498 brush = QBrush(d->state->pen.color(), pm);
5500 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5505 drawRect(QRectF(0, 0, sw, sh));
5508 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5509 x += d->state->matrix.dx();
5510 y += d->state->matrix.dy();
5512 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5518 \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5519 const QRect &source)
5522 Draws the rectangular portion \a source of the given \a pixmap
5523 into the given \a target in the paint device.
5525 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5529 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5530 const QRectF &source)
5533 Draws the rectangular portion \a source of the given \a pixmap
5534 with its origin at the given \a point.
5538 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5539 const QRect &source)
5543 Draws the rectangular portion \a source of the given \a pixmap
5544 with its origin at the given \a point.
5548 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5551 Draws the given \a pixmap with its origin at the given \a point.
5555 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5558 Draws the given \a pixmap with its origin at the given \a point.
5562 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5566 Draws the given \a pixmap at position (\a{x}, \a{y}).
5570 \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5573 Draws the given \a pixmap into the given \a rectangle.
5575 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5579 \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5580 const QPixmap &pixmap)
5584 Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5585 with the given \a width and \a height.
5589 \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5590 int sx, int sy, int sw, int sh)
5594 Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5595 width \a sw and height \a sh, of the given \a pixmap , at the
5596 point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5597 If sw or sh are equal to zero the width/height of the pixmap
5598 is used and adjusted by the offset sx/sy;
5602 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5603 int sx, int sy, int sw, int sh)
5607 Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5608 pixmap into the paint device.
5610 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5611 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5612 pixmap that is to be drawn. The default is (0, 0).
5614 (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5615 The default, (0, 0) (and negative) means all the way to the
5616 bottom-right of the pixmap.
5619 void QPainter::drawImage(const QPointF &p, const QImage &image)
5623 if (!d->engine || image.isNull())
5627 d->extended->drawImage(p, image);
5634 int w = image.width();
5635 int h = image.height();
5637 d->updateState(d->state);
5639 if (((d->state->matrix.type() > QTransform::TxTranslate)
5640 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5641 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5642 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5645 // If there is no rotation involved we have to make sure we use the
5646 // antialiased and not the aliased coordinate system by rounding the coordinates.
5647 if (d->state->matrix.type() <= QTransform::TxScale) {
5648 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5653 setBackgroundMode(Qt::TransparentMode);
5654 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5655 QBrush brush(image);
5658 setBrushOrigin(QPointF(0, 0));
5660 drawRect(image.rect());
5665 if (d->state->matrix.type() == QTransform::TxTranslate
5666 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5667 x += d->state->matrix.dx();
5668 y += d->state->matrix.dy();
5671 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5674 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5675 Qt::ImageConversionFlags flags)
5679 if (!d->engine || image.isNull())
5682 qreal x = targetRect.x();
5683 qreal y = targetRect.y();
5684 qreal w = targetRect.width();
5685 qreal h = targetRect.height();
5686 qreal sx = sourceRect.x();
5687 qreal sy = sourceRect.y();
5688 qreal sw = sourceRect.width();
5689 qreal sh = sourceRect.height();
5691 // Sanity-check clipping
5693 sw = image.width() - sx;
5696 sh = image.height() - sy;
5704 qreal w_ratio = sx * w/sw;
5712 qreal h_ratio = sy * h/sh;
5719 if (sw + sx > image.width()) {
5720 qreal delta = sw - (image.width() - sx);
5721 qreal w_ratio = delta * w/sw;
5726 if (sh + sy > image.height()) {
5727 qreal delta = sh - (image.height() - sy);
5728 qreal h_ratio = delta * h/sh;
5733 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5737 d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5741 d->updateState(d->state);
5743 if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5744 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5745 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5746 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5749 // If there is no rotation involved we have to make sure we use the
5750 // antialiased and not the aliased coordinate system by rounding the coordinates.
5751 if (d->state->matrix.type() <= QTransform::TxScale) {
5752 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5757 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5764 scale(w / sw, h / sh);
5765 setBackgroundMode(Qt::TransparentMode);
5766 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5767 QBrush brush(image);
5770 setBrushOrigin(QPointF(-sx, -sy));
5772 drawRect(QRectF(0, 0, sw, sh));
5777 if (d->state->matrix.type() == QTransform::TxTranslate
5778 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5779 x += d->state->matrix.dx();
5780 y += d->state->matrix.dy();
5783 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5787 Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5788 edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5789 selected on \a glyphs and at offsets given by the positions in \a glyphs.
5793 \sa QGlyphs::setFont(), QGlyphs::setPositions(), QGlyphs::setGlyphIndexes()
5795 #if !defined(QT_NO_RAWFONT)
5796 void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs)
5800 QRawFont font = glyphs.font();
5801 if (!font.isValid())
5804 QVector<quint32> glyphIndexes = glyphs.glyphIndexes();
5805 QVector<QPointF> glyphPositions = glyphs.positions();
5807 int count = qMin(glyphIndexes.size(), glyphPositions.size());
5808 QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5810 bool paintEngineSupportsTransformations =
5812 ? qt_paintengine_supports_transformations(d->extended->type())
5813 : qt_paintengine_supports_transformations(d->engine->type());
5815 // If the matrix is not affine, the paint engine will fall back to
5816 // drawing the glyphs as paths, which in turn means we should not
5817 // preprocess the glyph positions
5818 if (!d->state->matrix.isAffine())
5819 paintEngineSupportsTransformations = true;
5821 for (int i=0; i<count; ++i) {
5822 QPointF processedPosition = position + glyphPositions.at(i);
5823 if (!paintEngineSupportsTransformations)
5824 processedPosition = d->state->transform().map(processedPosition);
5825 fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5828 d->drawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count, font, glyphs.overline(),
5829 glyphs.underline(), glyphs.strikeOut());
5832 void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, int glyphCount,
5833 const QRawFont &font, bool overline, bool underline,
5840 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5841 QFontEngine *fontEngine = fontD->fontEngine;
5846 for (int i=0; i<glyphCount; ++i) {
5847 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5848 if (i == 0 || leftMost > positions[i].x)
5849 leftMost = positions[i].x;
5851 // We don't support glyphs that do not share a common baseline. If this turns out to
5852 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5853 // and do a drawTextItemDecorations call per cluster.
5854 if (i == 0 || baseLine < positions[i].y)
5855 baseLine = positions[i].y;
5857 // We use the advance rather than the actual bounds to match the algorithm in drawText()
5858 if (i == 0 || rightMost < positions[i].x + gm.xoff)
5859 rightMost = positions[i].x + gm.xoff;
5862 QFixed width = rightMost - leftMost;
5864 if (extended != 0 && state->matrix.isAffine()) {
5865 QStaticTextItem staticTextItem;
5866 staticTextItem.color = state->pen.color();
5867 staticTextItem.font = state->font;
5868 staticTextItem.setFontEngine(fontEngine);
5869 staticTextItem.numGlyphs = glyphCount;
5870 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5871 staticTextItem.glyphPositions = positions;
5873 extended->drawStaticTextItem(&staticTextItem);
5875 QTextItemInt textItem;
5876 textItem.fontEngine = fontEngine;
5878 QVarLengthArray<QFixed, 128> advances(glyphCount);
5879 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5880 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5881 qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5882 qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
5883 qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5885 textItem.glyphs.numGlyphs = glyphCount;
5886 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5887 textItem.glyphs.offsets = positions;
5888 textItem.glyphs.advances_x = advances.data();
5889 textItem.glyphs.advances_y = advances.data();
5890 textItem.glyphs.justifications = glyphJustifications.data();
5891 textItem.glyphs.attributes = glyphAttributes.data();
5893 engine->drawTextItem(QPointF(0, 0), textItem);
5896 QTextItemInt::RenderFlags flags;
5898 flags |= QTextItemInt::Underline;
5900 flags |= QTextItemInt::Overline;
5902 flags |= QTextItemInt::StrikeOut;
5904 drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5907 ? QTextCharFormat::SingleUnderline
5908 : QTextCharFormat::NoUnderline),
5909 flags, width.toReal(), QTextCharFormat());
5911 #endif // QT_NO_RAWFONT
5915 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5919 Draws the \a staticText at the \a topLeftPosition.
5921 \note The y-position is used as the top of the font.
5926 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5930 Draws the \a staticText at coordinates \a left and \a top.
5932 \note The y-position is used as the top of the font.
5936 \fn void QPainter::drawText(const QPointF &position, const QString &text)
5938 Draws the given \a text with the currently defined text direction,
5939 beginning at the given \a position.
5941 This function does not handle the newline character (\n), as it cannot
5942 break text into multiple lines, and it cannot display the newline character.
5943 Use the QPainter::drawText() overload that takes a rectangle instead
5944 if you want to draw multiple lines of text with the newline character, or
5945 if you want the text to be wrapped.
5947 By default, QPainter draws text anti-aliased.
5949 \note The y-position is used as the baseline of the font.
5952 void QPainter::drawText(const QPointF &p, const QString &str)
5954 drawText(p, str, 0, 0);
5960 Draws the given \a staticText at the given \a topLeftPosition.
5962 The text will be drawn using the font and the transformation set on the painter. If the
5963 font and/or transformation set on the painter are different from the ones used to initialize
5964 the layout of the QStaticText, then the layout will have to be recalculated. Use
5965 QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5966 it will later be drawn.
5968 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5969 last drawn, then there will be a slight overhead when translating the text to its new position.
5971 \note If the painter's transformation is not affine, then \a staticText will be drawn using
5972 regular calls to drawText(), losing any potential for performance improvement.
5974 \note The y-position is used as the top of the font.
5978 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5981 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5984 QStaticTextPrivate *staticText_d =
5985 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5987 if (font() != staticText_d->font) {
5988 staticText_d->font = font();
5989 staticText_d->needsRelayout = true;
5992 // If we don't have an extended paint engine, or if the painter is projected,
5993 // we go through standard code path
5994 if (d->extended == 0 || !d->state->matrix.isAffine()) {
5995 staticText_d->paintText(topLeftPosition, this);
5999 bool paintEngineSupportsTransformations = qt_paintengine_supports_transformations(d->extended->type());
6000 if (paintEngineSupportsTransformations && !staticText_d->untransformedCoordinates) {
6001 staticText_d->untransformedCoordinates = true;
6002 staticText_d->needsRelayout = true;
6003 } else if (!paintEngineSupportsTransformations && staticText_d->untransformedCoordinates) {
6004 staticText_d->untransformedCoordinates = false;
6005 staticText_d->needsRelayout = true;
6008 // Don't recalculate entire layout because of translation, rather add the dx and dy
6009 // into the position to move each text item the correct distance.
6010 QPointF transformedPosition = topLeftPosition;
6011 if (!staticText_d->untransformedCoordinates)
6012 transformedPosition = transformedPosition * d->state->matrix;
6013 QTransform oldMatrix;
6015 // The translation has been applied to transformedPosition. Remove translation
6016 // component from matrix.
6017 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
6018 qreal m11 = d->state->matrix.m11();
6019 qreal m12 = d->state->matrix.m12();
6020 qreal m13 = d->state->matrix.m13();
6021 qreal m21 = d->state->matrix.m21();
6022 qreal m22 = d->state->matrix.m22();
6023 qreal m23 = d->state->matrix.m23();
6024 qreal m33 = d->state->matrix.m33();
6026 oldMatrix = d->state->matrix;
6027 d->state->matrix.setMatrix(m11, m12, m13,
6032 // If the transform is not identical to the text transform,
6033 // we have to relayout the text (for other transformations than plain translation)
6034 bool staticTextNeedsReinit = staticText_d->needsRelayout;
6035 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
6036 staticText_d->matrix = d->state->matrix;
6037 staticTextNeedsReinit = true;
6040 // Recreate the layout of the static text because the matrix or font has changed
6041 if (staticTextNeedsReinit)
6042 staticText_d->init();
6044 if (transformedPosition != staticText_d->position) { // Translate to actual position
6045 QFixed fx = QFixed::fromReal(transformedPosition.x());
6046 QFixed fy = QFixed::fromReal(transformedPosition.y());
6047 QFixed oldX = QFixed::fromReal(staticText_d->position.x());
6048 QFixed oldY = QFixed::fromReal(staticText_d->position.y());
6049 for (int item=0; item<staticText_d->itemCount;++item) {
6050 QStaticTextItem *textItem = staticText_d->items + item;
6051 for (int i=0; i<textItem->numGlyphs; ++i) {
6052 textItem->glyphPositions[i].x += fx - oldX;
6053 textItem->glyphPositions[i].y += fy - oldY;
6055 textItem->userDataNeedsUpdate = true;
6058 staticText_d->position = transformedPosition;
6061 QPen oldPen = d->state->pen;
6062 QColor currentColor = oldPen.color();
6063 for (int i=0; i<staticText_d->itemCount; ++i) {
6064 QStaticTextItem *item = staticText_d->items + i;
6065 if (item->color.isValid() && currentColor != item->color) {
6066 setPen(item->color);
6067 currentColor = item->color;
6069 d->extended->drawStaticTextItem(item);
6071 qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
6072 item->numGlyphs, item->fontEngine(), staticText_d->font,
6075 if (currentColor != oldPen.color())
6078 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
6079 d->state->matrix = oldMatrix;
6085 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
6087 #ifdef QT_DEBUG_DRAW
6088 if (qt_show_painter_debug_output)
6089 printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
6094 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
6097 if (tf & Qt::TextBypassShaping) {
6098 // Skip harfbuzz complex shaping, shape using glyph advances only
6099 int len = str.length();
6100 int numGlyphs = len;
6101 QVarLengthGlyphLayoutArray glyphs(len);
6102 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
6103 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
6104 glyphs.resize(numGlyphs);
6105 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
6106 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
6109 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
6110 drawTextItem(p, gf);
6114 QStackTextEngine engine(str, d->state->font);
6115 engine.option.setTextDirection(d->state->layoutDirection);
6116 if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
6117 engine.ignoreBidi = true;
6118 engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
6122 line.length = str.length();
6123 engine.shapeLine(line);
6125 int nItems = engine.layoutData->items.size();
6126 QVarLengthArray<int> visualOrder(nItems);
6127 QVarLengthArray<uchar> levels(nItems);
6128 for (int i = 0; i < nItems; ++i)
6129 levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
6130 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
6132 if (justificationPadding > 0) {
6133 engine.option.setAlignment(Qt::AlignJustify);
6134 engine.forceJustification = true;
6135 // this works because justify() is only interested in the difference between width and textWidth
6136 line.width = justificationPadding;
6137 engine.justify(line);
6139 QFixed x = QFixed::fromReal(p.x());
6141 for (int i = 0; i < nItems; ++i) {
6142 int item = visualOrder[i];
6143 const QScriptItem &si = engine.layoutData->items.at(item);
6144 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
6148 QFont f = engine.font(si);
6149 QTextItemInt gf(si, &f);
6150 gf.glyphs = engine.shapedGlyphs(&si);
6151 gf.chars = engine.layoutData->string.unicode() + si.position;
6152 gf.num_chars = engine.length(item);
6153 if (engine.forceJustification) {
6154 for (int j=0; j<gf.glyphs.numGlyphs; ++j)
6155 gf.width += gf.glyphs.effectiveAdvance(j);
6157 gf.width = si.width;
6159 gf.logClusters = engine.logClusters(&si);
6161 drawTextItem(QPointF(x.toReal(), p.y()), gf);
6167 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
6169 #ifdef QT_DEBUG_DRAW
6170 if (qt_show_painter_debug_output)
6171 printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
6172 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6177 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6181 d->updateState(d->state);
6184 qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
6186 *br = bounds.toAlignedRect();
6190 \fn void QPainter::drawText(const QPoint &position, const QString &text)
6194 Draws the given \a text with the currently defined text direction,
6195 beginning at the given \a position.
6197 By default, QPainter draws text anti-aliased.
6199 \note The y-position is used as the baseline of the font.
6204 \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
6207 Draws the given \a text within the provided \a rectangle.
6211 \o \inlineimage qpainter-text.png
6213 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 17
6216 The \a boundingRect (if not null) is set to the what the bounding rectangle
6217 should be in order to enclose the whole text. The \a flags argument is a bitwise
6218 OR of the following flags:
6230 \o Qt::TextSingleLine
6231 \o Qt::TextExpandTabs
6232 \o Qt::TextShowMnemonic
6234 \o Qt::TextIncludeTrailingSpaces
6237 \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
6239 By default, QPainter draws text anti-aliased.
6241 \note The y-coordinate of \a rectangle is used as the top of the font.
6243 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
6245 #ifdef QT_DEBUG_DRAW
6246 if (qt_show_painter_debug_output)
6247 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
6248 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6253 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6257 d->updateState(d->state);
6259 qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
6263 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
6266 Draws the given \a text within the provided \a rectangle according
6267 to the specified \a flags. The \a boundingRect (if not null) is set to
6268 the what the bounding rectangle should be in order to enclose the whole text.
6270 By default, QPainter draws text anti-aliased.
6272 \note The y-coordinate of \a rectangle is used as the top of the font.
6276 \fn void QPainter::drawText(int x, int y, const QString &text)
6280 Draws the given \a text at position (\a{x}, \a{y}), using the painter's
6281 currently defined text direction.
6283 By default, QPainter draws text anti-aliased.
6285 \note The y-position is used as the baseline of the font.
6290 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6291 const QString &text, QRect *boundingRect)
6295 Draws the given \a text within the rectangle with origin (\a{x},
6296 \a{y}), \a width and \a height.
6298 The \a boundingRect (if not null) is set to the actual bounding
6299 rectangle of the output. The \a flags argument is a bitwise OR of
6300 the following flags:
6311 \o Qt::TextSingleLine
6312 \o Qt::TextExpandTabs
6313 \o Qt::TextShowMnemonic
6317 By default, QPainter draws text anti-aliased.
6319 \note The y-position is used as the top of the font.
6321 \sa Qt::AlignmentFlag, Qt::TextFlag
6325 \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6326 const QTextOption &option)
6329 Draws the given \a text in the \a rectangle specified using the \a option
6330 to control its positioning and orientation.
6332 By default, QPainter draws text anti-aliased.
6334 \note The y-coordinate of \a rectangle is used as the top of the font.
6336 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6338 #ifdef QT_DEBUG_DRAW
6339 if (qt_show_painter_debug_output)
6340 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6341 r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6346 if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6350 d->updateState(d->state);
6352 qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6356 \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6363 \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6368 Draws the text item \a ti at position \a p.
6372 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6377 Draws the text item \a ti at position \a p.
6379 This method ignores the painters background mode and
6380 color. drawText and qt_format_text have to do it themselves, as
6381 only they know the extents of the complete string.
6383 It ignores the font set on the painter as the text item has one of its own.
6385 The underline and strikeout parameters of the text items font are
6386 ignored aswell. You'll need to pass in the correct flags to get
6387 underlining and strikeout.
6390 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6392 const qreal radiusBase = qMax(qreal(1), maxRadius);
6394 QString key = QLatin1Literal("WaveUnderline-")
6395 % pen.color().name()
6396 % HexString<qreal>(radiusBase);
6399 if (QPixmapCache::find(key, pixmap))
6402 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6403 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6404 const int radius = qFloor(radiusBase);
6411 while (xs < width) {
6414 path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6417 pixmap = QPixmap(width, radius * 2);
6418 pixmap.fill(Qt::transparent);
6421 wavePen.setCapStyle(Qt::SquareCap);
6423 // This is to protect against making the line too fat, as happens on Mac OS X
6424 // due to it having a rather thick width for the regular underline.
6425 const qreal maxPenWidth = .8 * radius;
6426 if (wavePen.widthF() > maxPenWidth)
6427 wavePen.setWidth(maxPenWidth);
6429 QPainter imgPainter(&pixmap);
6430 imgPainter.setPen(wavePen);
6431 imgPainter.setRenderHint(QPainter::Antialiasing);
6432 imgPainter.translate(0, radius);
6433 imgPainter.drawPath(path);
6436 QPixmapCache::insert(key, pixmap);
6441 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
6442 QTextCharFormat::UnderlineStyle underlineStyle,
6443 QTextItem::RenderFlags flags, qreal width,
6444 const QTextCharFormat &charFormat)
6446 if (underlineStyle == QTextCharFormat::NoUnderline
6447 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6450 const QPen oldPen = painter->pen();
6451 const QBrush oldBrush = painter->brush();
6452 painter->setBrush(Qt::NoBrush);
6454 pen.setStyle(Qt::SolidLine);
6455 pen.setWidthF(fe->lineThickness().toReal());
6456 pen.setCapStyle(Qt::FlatCap);
6458 QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6460 const qreal underlineOffset = fe->underlinePosition().toReal();
6461 // deliberately ceil the offset to avoid the underline coming too close to
6462 // the text above it.
6463 const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
6464 const qreal underlinePos = pos.y() + qCeil(underlineOffset) - aliasedCoordinateDelta;
6466 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6467 underlineStyle = QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle));
6470 if (underlineStyle == QTextCharFormat::WaveUnderline) {
6472 painter->translate(0, pos.y() + 1);
6474 QColor uc = charFormat.underlineColor();
6478 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6479 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6480 const int descent = (int) fe->descent().toReal();
6482 painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6483 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6485 } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6486 QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos);
6488 QColor uc = charFormat.underlineColor();
6492 pen.setStyle((Qt::PenStyle)(underlineStyle));
6493 painter->setPen(pen);
6494 painter->drawLine(underLine);
6497 pen.setStyle(Qt::SolidLine);
6498 pen.setColor(oldPen.color());
6500 if (flags & QTextItem::StrikeOut) {
6501 QLineF strikeOutLine = line;
6502 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6503 painter->setPen(pen);
6504 painter->drawLine(strikeOutLine);
6507 if (flags & QTextItem::Overline) {
6508 QLineF overLine = line;
6509 overLine.translate(0., - fe->ascent().toReal());
6510 painter->setPen(pen);
6511 painter->drawLine(overLine);
6514 painter->setPen(oldPen);
6515 painter->setBrush(oldBrush);
6518 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6519 const QFixedPoint *positions, int glyphCount,
6520 QFontEngine *fontEngine, const QFont &font,
6521 const QTextCharFormat &charFormat)
6523 if (!(font.underline() || font.strikeOut() || font.overline()))
6529 for (int i=0; i<glyphCount; ++i) {
6530 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6531 if (i == 0 || leftMost > positions[i].x)
6532 leftMost = positions[i].x;
6534 // We don't support glyphs that do not share a common baseline. If this turns out to
6535 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6536 // and do a drawTextItemDecorations call per cluster.
6537 if (i == 0 || baseLine < positions[i].y)
6538 baseLine = positions[i].y;
6540 // We use the advance rather than the actual bounds to match the algorithm in drawText()
6541 if (i == 0 || rightMost < positions[i].x + gm.xoff)
6542 rightMost = positions[i].x + gm.xoff;
6545 QFixed width = rightMost - leftMost;
6546 QTextItem::RenderFlags flags = 0;
6548 if (font.underline())
6549 flags |= QTextItem::Underline;
6550 if (font.overline())
6551 flags |= QTextItem::Overline;
6552 if (font.strikeOut())
6553 flags |= QTextItem::StrikeOut;
6555 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6557 font.underline() ? QTextCharFormat::SingleUnderline
6558 : QTextCharFormat::NoUnderline, flags,
6559 width.toReal(), charFormat);
6562 void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
6564 #ifdef QT_DEBUG_DRAW
6565 if (qt_show_painter_debug_output)
6566 printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6567 p.x(), p.y(), qPrintable(_ti.text()));
6576 qt_painter_thread_test(d->device->devType(),
6578 QFontDatabase::supportsThreadedFontRendering());
6581 QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6583 if (!d->extended && d->state->bgMode == Qt::OpaqueMode) {
6584 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6585 fillRect(rect, d->state->bgBrush);
6588 if (pen().style() == Qt::NoPen)
6591 const RenderHints oldRenderHints = d->state->renderHints;
6592 if (!d->state->renderHints & QPainter::Antialiasing && d->state->matrix.type() >= QTransform::TxScale) {
6593 // draw antialias decoration (underline/overline/strikeout) with
6597 const QTransform &m = d->state->matrix;
6598 if (d->state->matrix.type() < QTransform::TxShear) {
6599 bool isPlain90DegreeRotation =
6600 (qFuzzyIsNull(m.m11())
6601 && qFuzzyIsNull(m.m12() - qreal(1))
6602 && qFuzzyIsNull(m.m21() + qreal(1))
6603 && qFuzzyIsNull(m.m22())
6606 (qFuzzyIsNull(m.m11() + qreal(1))
6607 && qFuzzyIsNull(m.m12())
6608 && qFuzzyIsNull(m.m21())
6609 && qFuzzyIsNull(m.m22() + qreal(1))
6612 (qFuzzyIsNull(m.m11())
6613 && qFuzzyIsNull(m.m12() + qreal(1))
6614 && qFuzzyIsNull(m.m21() - qreal(1))
6615 && qFuzzyIsNull(m.m22())
6618 aa = !isPlain90DegreeRotation;
6621 setRenderHint(QPainter::Antialiasing, true);
6625 d->updateState(d->state);
6627 if (!ti.glyphs.numGlyphs) {
6629 } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6630 QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6632 const QGlyphLayout &glyphs = ti.glyphs;
6633 int which = glyphs.glyphs[0] >> 24;
6640 for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6641 const int e = glyphs.glyphs[end] >> 24;
6646 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6648 // set the high byte to zero and calc the width
6649 for (i = start; i < end; ++i) {
6650 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6651 ti2.width += ti.glyphs.effectiveAdvance(i);
6654 d->engine->drawTextItem(QPointF(x, y), ti2);
6656 // reset the high byte for all glyphs and advance to the next sub-string
6657 const int hi = which << 24;
6658 for (i = start; i < end; ++i) {
6659 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6661 x += ti2.width.toReal();
6668 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6670 // set the high byte to zero and calc the width
6671 for (i = start; i < end; ++i) {
6672 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6673 ti2.width += ti.glyphs.effectiveAdvance(i);
6677 d->extended->drawTextItem(QPointF(x, y), ti2);
6679 d->engine->drawTextItem(QPointF(x,y), ti2);
6681 // reset the high byte for all glyphs
6682 const int hi = which << 24;
6683 for (i = start; i < end; ++i)
6684 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6688 d->extended->drawTextItem(p, ti);
6690 d->engine->drawTextItem(p, ti);
6692 drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(),
6695 if (d->state->renderHints != oldRenderHints) {
6696 d->state->renderHints = oldRenderHints;
6698 d->extended->renderHintsChanged();
6700 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
6705 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6707 Returns the bounding rectangle of the \a text as it will appear
6708 when drawn inside the given \a rectangle with the specified \a
6709 flags using the currently set font(); i.e the function tells you
6710 where the drawText() function will draw when given the same
6713 If the \a text does not fit within the given \a rectangle using
6714 the specified \a flags, the function returns the required
6717 The \a flags argument is a bitwise OR of the following flags:
6726 \o Qt::TextSingleLine
6727 \o Qt::TextExpandTabs
6728 \o Qt::TextShowMnemonic
6730 \o Qt::TextIncludeTrailingSpaces
6732 If several of the horizontal or several of the vertical alignment
6733 flags are set, the resulting alignment is undefined.
6735 \sa drawText(), Qt::Alignment, Qt::TextFlag
6739 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6740 const QString &text)
6744 Returns the bounding rectangle of the \a text as it will appear
6745 when drawn inside the given \a rectangle with the specified \a
6746 flags using the currently set font().
6750 \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6751 const QString &text);
6755 Returns the bounding rectangle of the given \a text as it will
6756 appear when drawn inside the rectangle beginning at the point
6757 (\a{x}, \a{y}) with width \a w and height \a h.
6759 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6762 return QRect(rect.x(),rect.y(), 0,0);
6764 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6770 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6773 return QRectF(rect.x(),rect.y(), 0,0);
6775 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6780 \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6781 const QString &text, const QTextOption &option)
6785 Instead of specifying flags as a bitwise OR of the
6786 Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6787 an \a option argument. The QTextOption class provides a
6788 description of general rich text properties.
6792 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6796 if (!d->engine || text.length() == 0)
6797 return QRectF(r.x(),r.y(), 0,0);
6800 qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6805 \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6807 Draws a tiled \a pixmap, inside the given \a rectangle with its
6808 origin at the given \a position.
6810 Calling drawTiledPixmap() is similar to calling drawPixmap()
6811 several times to fill (tile) an area with a pixmap, but is
6812 potentially much more efficient depending on the underlying window
6817 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6819 #ifdef QT_DEBUG_DRAW
6820 if (qt_show_painter_debug_output)
6821 printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6822 r.x(), r.y(), r.width(), r.height(),
6823 pixmap.width(), pixmap.height(),
6828 if (!d->engine || pixmap.isNull() || r.isEmpty())
6832 qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6835 qreal sw = pixmap.width();
6836 qreal sh = pixmap.height();
6840 sx = qRound(sw) - qRound(-sx) % qRound(sw);
6842 sx = qRound(sx) % qRound(sw);
6844 sy = qRound(sh) - -qRound(sy) % qRound(sh);
6846 sy = qRound(sy) % qRound(sh);
6850 d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6854 if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6855 fillRect(r, d->state->bgBrush);
6857 d->updateState(d->state);
6858 if ((d->state->matrix.type() > QTransform::TxTranslate
6859 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6860 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6863 setBackgroundMode(Qt::TransparentMode);
6864 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6865 setBrush(QBrush(d->state->pen.color(), pixmap));
6868 // If there is no rotation involved we have to make sure we use the
6869 // antialiased and not the aliased coordinate system by rounding the coordinates.
6870 if (d->state->matrix.type() <= QTransform::TxScale) {
6871 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6873 if (d->state->matrix.type() <= QTransform::TxTranslate) {
6878 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6879 drawRect(QRectF(p, r.size()));
6881 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6890 if (d->state->matrix.type() == QTransform::TxTranslate
6891 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6892 x += d->state->matrix.dx();
6893 y += d->state->matrix.dy();
6896 d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6900 \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6901 const QPoint &position = QPoint())
6904 Draws a tiled \a pixmap, inside the given \a rectangle with its
6905 origin at the given \a position.
6909 \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6910 QPixmap &pixmap, int sx, int sy);
6913 Draws a tiled \a pixmap in the specified rectangle.
6915 (\a{x}, \a{y}) specifies the top-left point in the paint device
6916 that is to be drawn onto; with the given \a width and \a
6917 height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6918 pixmap that is to be drawn; this defaults to (0, 0).
6921 #ifndef QT_NO_PICTURE
6924 \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6926 Replays the given \a picture at the given \a point.
6928 The QPicture class is a paint device that records and replays
6929 QPainter commands. A picture serializes the painter commands to an
6930 IO device in a platform-independent format. Everything that can be
6931 painted on a widget or pixmap can also be stored in a picture.
6933 This function does exactly the same as QPicture::play() when
6934 called with \a point = QPoint(0, 0).
6939 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 18
6942 \sa QPicture::play()
6945 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6953 d->updateState(d->state);
6957 const_cast<QPicture *>(&picture)->play(this);
6962 \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6965 Replays the given \a picture at the given \a point.
6969 \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6972 Draws the given \a picture at point (\a x, \a y).
6975 #endif // QT_NO_PICTURE
6978 \fn void QPainter::eraseRect(const QRectF &rectangle)
6980 Erases the area inside the given \a rectangle. Equivalent to
6982 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 19
6986 void QPainter::eraseRect(const QRectF &r)
6990 fillRect(r, d->state->bgBrush);
6993 static inline bool needsResolving(const QBrush &brush)
6995 Qt::BrushStyle s = brush.style();
6996 return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
6997 s == Qt::ConicalGradientPattern) &&
6998 brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
7002 \fn void QPainter::eraseRect(const QRect &rectangle)
7005 Erases the area inside the given \a rectangle.
7009 \fn void QPainter::eraseRect(int x, int y, int width, int height)
7012 Erases the area inside the rectangle beginning at (\a x, \a y)
7013 with the given \a width and \a height.
7018 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
7021 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7022 width and \a height, using the brush \a style specified.
7028 \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
7031 Fills the given \a rectangle with the brush \a style specified.
7037 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
7040 Fills the given \a rectangle with the brush \a style specified.
7046 \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
7048 Fills the given \a rectangle with the \a brush specified.
7050 Alternatively, you can specify a QColor instead of a QBrush; the
7051 QBrush constructor (taking a QColor argument) will automatically
7052 create a solid pattern brush.
7056 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
7064 const QGradient *g = brush.gradient();
7065 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
7066 d->extended->fillRect(r, brush);
7071 QPen oldPen = pen();
7072 QBrush oldBrush = this->brush();
7074 if (brush.style() == Qt::SolidPattern) {
7075 d->colorBrush.setStyle(Qt::SolidPattern);
7076 d->colorBrush.setColor(brush.color());
7077 setBrush(d->colorBrush);
7088 \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
7091 Fills the given \a rectangle with the specified \a brush.
7094 void QPainter::fillRect(const QRect &r, const QBrush &brush)
7102 const QGradient *g = brush.gradient();
7103 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
7104 d->extended->fillRect(r, brush);
7109 QPen oldPen = pen();
7110 QBrush oldBrush = this->brush();
7112 if (brush.style() == Qt::SolidPattern) {
7113 d->colorBrush.setStyle(Qt::SolidPattern);
7114 d->colorBrush.setColor(brush.color());
7115 setBrush(d->colorBrush);
7128 \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
7131 Fills the given \a rectangle with the \a color specified.
7135 void QPainter::fillRect(const QRect &r, const QColor &color)
7143 d->extended->fillRect(r, color);
7147 fillRect(r, QBrush(color));
7152 \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
7155 Fills the given \a rectangle with the \a color specified.
7159 void QPainter::fillRect(const QRectF &r, const QColor &color)
7167 d->extended->fillRect(r, color);
7171 fillRect(r, QBrush(color));
7175 \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
7179 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7180 width and \a height, using the given \a brush.
7184 \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
7188 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7189 width and \a height, using the given \a color.
7195 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
7199 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7200 width and \a height, using the given \a color.
7206 \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
7210 Fills the given \a rectangle with the specified \a color.
7216 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
7220 Fills the given \a rectangle with the specified \a color.
7226 Sets the given render \a hint on the painter if \a on is true;
7227 otherwise clears the render hint.
7229 \sa setRenderHints(), renderHints(), {QPainter#Rendering
7230 Quality}{Rendering Quality}
7232 void QPainter::setRenderHint(RenderHint hint, bool on)
7234 #ifdef QT_DEBUG_DRAW
7235 if (qt_show_painter_debug_output)
7236 printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
7240 static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
7241 if (hint == QPainter::Antialiasing && antialiasingDisabled)
7245 setRenderHints(hint, on);
7251 Sets the given render \a hints on the painter if \a on is true;
7252 otherwise clears the render hints.
7254 \sa setRenderHint(), renderHints(), {QPainter#Rendering
7255 Quality}{Rendering Quality}
7258 void QPainter::setRenderHints(RenderHints hints, bool on)
7263 qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7268 d->state->renderHints |= hints;
7270 d->state->renderHints &= ~hints;
7273 d->extended->renderHintsChanged();
7275 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7279 Returns a flag that specifies the rendering hints that are set for
7282 \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7284 QPainter::RenderHints QPainter::renderHints() const
7286 Q_D(const QPainter);
7291 return d->state->renderHints;
7295 \fn bool QPainter::testRenderHint(RenderHint hint) const
7298 Returns true if \a hint is set; otherwise returns false.
7300 \sa renderHints(), setRenderHint()
7304 Returns true if view transformation is enabled; otherwise returns
7307 \sa setViewTransformEnabled(), worldTransform()
7310 bool QPainter::viewTransformEnabled() const
7312 Q_D(const QPainter);
7314 qWarning("QPainter::viewTransformEnabled: Painter not active");
7317 return d->state->VxF;
7321 \fn void QPainter::setWindow(const QRect &rectangle)
7323 Sets the painter's window to the given \a rectangle, and enables
7324 view transformations.
7326 The window rectangle is part of the view transformation. The
7327 window specifies the logical coordinate system. Its sister, the
7328 viewport(), specifies the device coordinate system.
7330 The default window rectangle is the same as the device's
7333 \sa window(), viewTransformEnabled(), {Coordinate
7334 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7338 \fn void QPainter::setWindow(int x, int y, int width, int height)
7341 Sets the painter's window to the rectangle beginning at (\a x, \a
7342 y) and the given \a width and \a height.
7345 void QPainter::setWindow(const QRect &r)
7347 #ifdef QT_DEBUG_DRAW
7348 if (qt_show_painter_debug_output)
7349 printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7355 qWarning("QPainter::setWindow: Painter not active");
7359 d->state->wx = r.x();
7360 d->state->wy = r.y();
7361 d->state->ww = r.width();
7362 d->state->wh = r.height();
7364 d->state->VxF = true;
7369 Returns the window rectangle.
7371 \sa setWindow(), setViewTransformEnabled()
7374 QRect QPainter::window() const
7376 Q_D(const QPainter);
7378 qWarning("QPainter::window: Painter not active");
7381 return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7385 \fn void QPainter::setViewport(const QRect &rectangle)
7387 Sets the painter's viewport rectangle to the given \a rectangle,
7388 and enables view transformations.
7390 The viewport rectangle is part of the view transformation. The
7391 viewport specifies the device coordinate system. Its sister, the
7392 window(), specifies the logical coordinate system.
7394 The default viewport rectangle is the same as the device's
7397 \sa viewport(), viewTransformEnabled() {Coordinate
7398 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7402 \fn void QPainter::setViewport(int x, int y, int width, int height)
7405 Sets the painter's viewport rectangle to be the rectangle
7406 beginning at (\a x, \a y) with the given \a width and \a height.
7409 void QPainter::setViewport(const QRect &r)
7411 #ifdef QT_DEBUG_DRAW
7412 if (qt_show_painter_debug_output)
7413 printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7419 qWarning("QPainter::setViewport: Painter not active");
7423 d->state->vx = r.x();
7424 d->state->vy = r.y();
7425 d->state->vw = r.width();
7426 d->state->vh = r.height();
7428 d->state->VxF = true;
7433 Returns the viewport rectangle.
7435 \sa setViewport(), setViewTransformEnabled()
7438 QRect QPainter::viewport() const
7440 Q_D(const QPainter);
7442 qWarning("QPainter::viewport: Painter not active");
7445 return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7448 /*! \fn bool QPainter::hasViewXForm() const
7451 Use viewTransformEnabled() instead.
7454 /*! \fn bool QPainter::hasWorldXForm() const
7457 Use worldMatrixEnabled() instead.
7460 /*! \fn void QPainter::resetXForm()
7463 Use resetTransform() instead.
7466 /*! \fn void QPainter::setViewXForm(bool enabled)
7469 Use setViewTransformEnabled() instead.
7472 /*! \fn void QPainter::setWorldXForm(bool enabled)
7475 Use setWorldMatrixEnabled() instead.
7478 Enables view transformations if \a enable is true, or disables
7479 view transformations if \a enable is false.
7481 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7482 Conversion}{Window-Viewport Conversion}
7485 void QPainter::setViewTransformEnabled(bool enable)
7487 #ifdef QT_DEBUG_DRAW
7488 if (qt_show_painter_debug_output)
7489 printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7495 qWarning("QPainter::setViewTransformEnabled: Painter not active");
7499 if (enable == d->state->VxF)
7502 d->state->VxF = enable;
7511 Use the worldTransform() combined with QTransform::dx() instead.
7514 QPainter painter(this);
7515 qreal x = painter.translationX();
7517 QPainter painter(this);
7518 qreal x = painter.worldTransform().dx();
7521 qreal QPainter::translationX() const
7523 Q_D(const QPainter);
7525 qWarning("QPainter::translationX: Painter not active");
7528 return d->state->worldMatrix.dx();
7534 Use the worldTransform() combined with QTransform::dy() instead.
7537 QPainter painter(this);
7538 qreal y = painter.translationY();
7540 QPainter painter(this);
7541 qreal y = painter.worldTransform().dy();
7544 qreal QPainter::translationY() const
7546 Q_D(const QPainter);
7548 qWarning("QPainter::translationY: Painter not active");
7551 return d->state->worldMatrix.dy();
7555 \fn void QPainter::map(int x, int y, int *rx, int *ry) const
7559 Sets (\a{rx}, \a{ry}) to the point that results from applying the
7560 painter's current transformation on the point (\a{x}, \a{y}).
7562 void QPainter::map(int x, int y, int *rx, int *ry) const
7565 p = p * combinedMatrix();
7571 \fn QPoint QPainter::xForm(const QPoint &point) const
7573 Use combinedTransform() instead.
7576 QPoint QPainter::xForm(const QPoint &p) const
7578 Q_D(const QPainter);
7580 qWarning("QPainter::xForm: Painter not active");
7583 if (d->state->matrix.type() == QTransform::TxNone)
7585 return p * combinedMatrix();
7590 \fn QRect QPainter::xForm(const QRect &rectangle) const
7593 Use combinedTransform() instead of this function and call
7594 mapRect() on the result to obtain a QRect.
7597 QRect QPainter::xForm(const QRect &r) const
7599 Q_D(const QPainter);
7601 qWarning("QPainter::xForm: Painter not active");
7604 if (d->state->matrix.type() == QTransform::TxNone)
7606 return combinedMatrix().mapRect(r);
7610 \fn QPolygon QPainter::xForm(const QPolygon &polygon) const
7613 Use combinedTransform() instead.
7616 QPolygon QPainter::xForm(const QPolygon &a) const
7618 Q_D(const QPainter);
7620 qWarning("QPainter::xForm: Painter not active");
7623 if (d->state->matrix.type() == QTransform::TxNone)
7625 return a * combinedMatrix();
7629 \fn QPolygon QPainter::xForm(const QPolygon &polygon, int index, int count) const
7632 Use combinedTransform() combined with QPolygon::mid() instead.
7635 QPainter painter(this);
7636 QPolygon transformed = painter.xForm(polygon, index, count)
7638 QPainter painter(this);
7639 QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform();
7643 QPolygon QPainter::xForm(const QPolygon &av, int index, int npoints) const
7645 int lastPoint = npoints < 0 ? av.size() : index+npoints;
7646 QPolygon a(lastPoint-index);
7647 memcpy(a.data(), av.data()+index, (lastPoint-index)*sizeof(QPoint));
7648 return a * combinedMatrix();
7652 \fn QPoint QPainter::xFormDev(const QPoint &point) const
7656 Use combinedTransform() combined with QTransform::inverted() instead.
7659 QPainter painter(this);
7660 QPoint transformed = painter.xFormDev(point);
7662 QPainter painter(this);
7663 QPoint transformed = point * painter.combinedTransform().inverted();
7667 QPoint QPainter::xFormDev(const QPoint &p) const
7669 Q_D(const QPainter);
7671 qWarning("QPainter::xFormDev: Painter not active");
7674 if(d->state->matrix.type() == QTransform::TxNone)
7676 return p * combinedMatrix().inverted();
7680 \fn QRect QPainter::xFormDev(const QRect &rectangle) const
7684 Use combinedTransform() combined with QTransform::inverted() instead.
7687 QPainter painter(this);
7688 QRect transformed = painter.xFormDev(rectangle);
7690 QPainter painter(this);
7691 QRegion region = QRegion(rectangle) * painter.combinedTransform().inverted();
7692 QRect transformed = region.boundingRect();
7696 QRect QPainter::xFormDev(const QRect &r) const
7698 Q_D(const QPainter);
7700 qWarning("QPainter::xFormDev: Painter not active");
7703 if (d->state->matrix.type() == QTransform::TxNone)
7705 return combinedMatrix().inverted().mapRect(r);
7711 \fn QPoint QPainter::xFormDev(const QPolygon &polygon) const
7714 Use combinedTransform() combined with QTransform::inverted() instead.
7717 QPainter painter(this);
7718 QPolygon transformed = painter.xFormDev(rectangle);
7720 QPainter painter(this);
7721 QPolygon transformed = polygon * painter.combinedTransform().inverted();
7725 QPolygon QPainter::xFormDev(const QPolygon &a) const
7727 Q_D(const QPainter);
7729 qWarning("QPainter::xFormDev: Painter not active");
7732 if (d->state->matrix.type() == QTransform::TxNone)
7734 return a * combinedMatrix().inverted();
7738 \fn QPolygon QPainter::xFormDev(const QPolygon &polygon, int index, int count) const
7742 Use combinedTransform() combined with QPolygon::mid() and QTransform::inverted() instead.
7745 QPainter painter(this);
7746 QPolygon transformed = painter.xFormDev(polygon, index, count);
7748 QPainter painter(this);
7749 QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform().inverted();
7753 QPolygon QPainter::xFormDev(const QPolygon &ad, int index, int npoints) const
7755 Q_D(const QPainter);
7756 int lastPoint = npoints < 0 ? ad.size() : index+npoints;
7757 QPolygon a(lastPoint-index);
7758 memcpy(a.data(), ad.data()+index, (lastPoint-index)*sizeof(QPoint));
7759 if (d->state->matrix.type() == QTransform::TxNone)
7761 return a * combinedMatrix().inverted();
7765 \fn void QPainter::drawCubicBezier(const QPolygon &controlPoints, int index)
7767 Draws a cubic Bezier curve defined by the \a controlPoints,
7768 starting at \a{controlPoints}\e{[index]} (\a index defaults to 0).
7769 Points after \a{controlPoints}\e{[index + 3]} are ignored. Nothing
7770 happens if there aren't enough control points.
7772 Use strokePath() instead.
7775 QPainter painter(this);
7776 painter.drawCubicBezier(controlPoints, index)
7779 path.moveTo(controlPoints.at(index));
7780 path.cubicTo(controlPoints.at(index+1),
7781 controlPoints.at(index+2),
7782 controlPoints.at(index+3));
7784 QPainter painter(this);
7785 painter.strokePath(path, painter.pen());
7788 void QPainter::drawCubicBezier(const QPolygon &a, int index)
7795 if ((int)a.size() - index < 4) {
7796 qWarning("QPainter::drawCubicBezier: Cubic Bezier needs 4 control "
7802 path.moveTo(a.at(index));
7803 path.cubicTo(a.at(index+1), a.at(index+2), a.at(index+3));
7804 strokePath(path, d->state->pen);
7808 struct QPaintDeviceRedirection
7810 QPaintDeviceRedirection() : device(0), replacement(0), internalWidgetRedirectionIndex(-1) {}
7811 QPaintDeviceRedirection(const QPaintDevice *device, QPaintDevice *replacement,
7812 const QPoint& offset, int internalWidgetRedirectionIndex)
7813 : device(device), replacement(replacement), offset(offset),
7814 internalWidgetRedirectionIndex(internalWidgetRedirectionIndex) { }
7815 const QPaintDevice *device;
7816 QPaintDevice *replacement;
7818 int internalWidgetRedirectionIndex;
7819 bool operator==(const QPaintDevice *pdev) const { return device == pdev; }
7820 Q_DUMMY_COMPARISON_OPERATOR(QPaintDeviceRedirection)
7823 typedef QList<QPaintDeviceRedirection> QPaintDeviceRedirectionList;
7824 Q_GLOBAL_STATIC(QPaintDeviceRedirectionList, globalRedirections)
7825 Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex)
7826 Q_GLOBAL_STATIC(QAtomicInt, globalRedirectionAtomic)
7833 Please use QWidget::render() instead.
7835 Redirects all paint commands for the given paint \a device, to the
7836 \a replacement device. The optional point \a offset defines an
7837 offset within the source device.
7839 The redirection will not be effective until the begin() function
7840 has been called; make sure to call end() for the given \a
7841 device's painter (if any) before redirecting. Call
7842 restoreRedirected() to restore the previous redirection.
7844 \warning Making use of redirections in the QPainter API implies
7845 that QPainter::begin() and QPaintDevice destructors need to hold
7846 a mutex for a short period. This can impact performance. Use of
7847 QWidget::render is strongly encouraged.
7849 \sa redirected(), restoreRedirected()
7851 void QPainter::setRedirected(const QPaintDevice *device,
7852 QPaintDevice *replacement,
7853 const QPoint &offset)
7855 Q_ASSERT(device != 0);
7857 bool hadInternalWidgetRedirection = false;
7858 if (device->devType() == QInternal::Widget) {
7859 const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
7860 // This is the case when the widget is in a paint event.
7861 if (widgetPrivate->redirectDev) {
7862 // Remove internal redirection and put it back into the global redirection list.
7864 QPaintDevice *oldReplacement = widgetPrivate->redirected(&oldOffset);
7865 const_cast<QWidgetPrivate *>(widgetPrivate)->restoreRedirected();
7866 setRedirected(device, oldReplacement, oldOffset);
7867 hadInternalWidgetRedirection = true;
7872 QPaintDevice *rdev = redirected(replacement, &roffset);
7874 QMutexLocker locker(globalRedirectionsMutex());
7875 QPaintDeviceRedirectionList *redirections = globalRedirections();
7876 Q_ASSERT(redirections != 0);
7877 *redirections += QPaintDeviceRedirection(device, rdev ? rdev : replacement, offset + roffset,
7878 hadInternalWidgetRedirection ? redirections->size() - 1 : -1);
7879 globalRedirectionAtomic()->ref();
7887 Using QWidget::render() obsoletes the use of this function.
7889 Restores the previous redirection for the given \a device after a
7890 call to setRedirected().
7892 \warning Making use of redirections in the QPainter API implies
7893 that QPainter::begin() and QPaintDevice destructors need to hold
7894 a mutex for a short period. This can impact performance. Use of
7895 QWidget::render is strongly encouraged.
7899 void QPainter::restoreRedirected(const QPaintDevice *device)
7901 Q_ASSERT(device != 0);
7902 QMutexLocker locker(globalRedirectionsMutex());
7903 QPaintDeviceRedirectionList *redirections = globalRedirections();
7904 Q_ASSERT(redirections != 0);
7905 for (int i = redirections->size()-1; i >= 0; --i) {
7906 if (redirections->at(i) == device) {
7907 globalRedirectionAtomic()->deref();
7908 const int internalWidgetRedirectionIndex = redirections->at(i).internalWidgetRedirectionIndex;
7909 redirections->removeAt(i);
7910 // Restore the internal widget redirection, i.e. remove it from the global
7911 // redirection list and put it back into QWidgetPrivate. The index is only set when
7912 // someone call QPainter::setRedirected in a widget's paint event and we internally
7913 // have a redirection set (typically set in QWidgetPrivate::drawWidget).
7914 if (internalWidgetRedirectionIndex >= 0) {
7915 Q_ASSERT(internalWidgetRedirectionIndex < redirections->size());
7916 const QPaintDeviceRedirection &redirectionDevice = redirections->at(internalWidgetRedirectionIndex);
7917 QWidget *widget = static_cast<QWidget *>(const_cast<QPaintDevice *>(device));
7918 widget->d_func()->setRedirected(redirectionDevice.replacement, redirectionDevice.offset);
7919 redirections->removeAt(internalWidgetRedirectionIndex);
7931 Using QWidget::render() obsoletes the use of this function.
7933 Returns the replacement for given \a device. The optional out
7934 parameter \a offset returns the offset within the replaced device.
7936 \warning Making use of redirections in the QPainter API implies
7937 that QPainter::begin() and QPaintDevice destructors need to hold
7938 a mutex for a short period. This can impact performance. Use of
7939 QWidget::render is strongly encouraged.
7941 \sa setRedirected(), restoreRedirected()
7943 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7945 Q_ASSERT(device != 0);
7947 if (device->devType() == QInternal::Widget) {
7948 const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
7949 if (widgetPrivate->redirectDev)
7950 return widgetPrivate->redirected(offset);
7953 if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
7956 QMutexLocker locker(globalRedirectionsMutex());
7957 QPaintDeviceRedirectionList *redirections = globalRedirections();
7958 Q_ASSERT(redirections != 0);
7959 for (int i = redirections->size()-1; i >= 0; --i)
7960 if (redirections->at(i) == device) {
7962 *offset = redirections->at(i).offset;
7963 return redirections->at(i).replacement;
7966 *offset = QPoint(0, 0);
7971 void qt_painter_removePaintDevice(QPaintDevice *dev)
7973 if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
7978 mutex = globalRedirectionsMutex();
7980 // ignore the missing mutex, since we could be called from
7981 // a destructor, and destructors shall not throw
7983 QMutexLocker locker(mutex);
7984 QPaintDeviceRedirectionList *redirections = 0;
7986 redirections = globalRedirections();
7988 // do nothing - code below is safe with redirections being 0.
7991 for (int i = 0; i < redirections->size(); ) {
7992 if(redirections->at(i) == dev || redirections->at(i).replacement == dev)
7993 redirections->removeAt(i);
8000 void qt_format_text(const QFont &fnt, const QRectF &_r,
8001 int tf, const QString& str, QRectF *brect,
8002 int tabstops, int *ta, int tabarraylen,
8005 qt_format_text(fnt, _r,
8007 tabstops, ta, tabarraylen,
8010 void qt_format_text(const QFont &fnt, const QRectF &_r,
8011 int tf, const QTextOption *option, const QString& str, QRectF *brect,
8012 int tabstops, int *ta, int tabarraylen,
8016 Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
8019 tf |= option->alignment();
8020 if (option->wrapMode() != QTextOption::NoWrap)
8021 tf |= Qt::TextWordWrap;
8023 if (option->flags() & QTextOption::IncludeTrailingSpaces)
8024 tf |= Qt::TextIncludeTrailingSpaces;
8026 if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
8027 tf |= Qt::TextExpandTabs;
8030 // we need to copy r here to protect against the case (&r == brect).
8033 bool dontclip = (tf & Qt::TextDontClip);
8034 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
8035 bool singleline = (tf & Qt::TextSingleLine);
8036 bool showmnemonic = (tf & Qt::TextShowMnemonic);
8037 bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
8039 Qt::LayoutDirection layout_direction;
8040 if (tf & Qt::TextForceLeftToRight)
8041 layout_direction = Qt::LeftToRight;
8042 else if (tf & Qt::TextForceRightToLeft)
8043 layout_direction = Qt::RightToLeft;
8045 layout_direction = option->textDirection();
8047 layout_direction = painter->layoutDirection();
8049 layout_direction = Qt::LeftToRight;
8051 tf = QStyle::visualAlignment(layout_direction, QFlag(tf));
8053 bool isRightToLeft = layout_direction == Qt::RightToLeft;
8054 bool expandtabs = ((tf & Qt::TextExpandTabs) &&
8055 (((tf & Qt::AlignLeft) && !isRightToLeft) ||
8056 ((tf & Qt::AlignRight) && isRightToLeft)));
8059 tf |= Qt::TextDontPrint;
8061 uint maxUnderlines = 0;
8062 int numUnderlines = 0;
8063 QVarLengthArray<int, 32> underlinePositions(1);
8065 QFontMetricsF fm(fnt);
8068 start_lengthVariant:
8069 bool hasMoreLengthVariants = false;
8070 // compatible behaviour to the old implementation. Replace
8072 int old_offset = offset;
8073 for (; offset < text.length(); offset++) {
8074 QChar chr = text.at(offset);
8075 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
8076 text[offset] = QLatin1Char(' ');
8077 } else if (chr == QLatin1Char('\n')) {
8078 text[offset] = QChar::LineSeparator;
8079 } else if (chr == QLatin1Char('&')) {
8081 } else if (chr == QLatin1Char('\t')) {
8083 text[offset] = QLatin1Char(' ');
8084 } else if (!tabarraylen && !tabstops) {
8085 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
8087 } else if (chr == QChar(ushort(0x9c))) {
8088 // string with multiple length variants
8089 hasMoreLengthVariants = true;
8094 int length = offset - old_offset;
8095 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
8096 underlinePositions.resize(maxUnderlines + 1);
8098 QChar *cout = text.data() + old_offset;
8102 if (*cin == QLatin1Char('&')) {
8108 if (*cin != QLatin1Char('&') && !hidemnmemonic)
8109 underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
8118 // no need to do extra work for underlines if we don't paint
8119 if (tf & Qt::TextDontPrint)
8122 underlinePositions[numUnderlines] = -1;
8126 QString finalText = text.mid(old_offset, length);
8127 QStackTextEngine engine(finalText, fnt);
8129 engine.option = *option;
8132 if (engine.option.tabStop() < 0 && tabstops > 0)
8133 engine.option.setTabStop(tabstops);
8135 if (engine.option.tabs().isEmpty() && ta) {
8137 for (int i = 0; i < tabarraylen; i++)
8138 tabs.append(qreal(ta[i]));
8139 engine.option.setTabArray(tabs);
8142 engine.option.setTextDirection(layout_direction);
8143 if (tf & Qt::AlignJustify)
8144 engine.option.setAlignment(Qt::AlignJustify);
8146 engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
8148 if (!option && (tf & Qt::TextWrapAnywhere))
8149 engine.option.setWrapMode(QTextOption::WrapAnywhere);
8151 if (tf & Qt::TextJustificationForced)
8152 engine.forceJustification = true;
8153 QTextLayout textLayout(&engine);
8154 textLayout.setCacheEnabled(true);
8155 textLayout.engine()->underlinePositions = underlinePositions.data();
8157 if (finalText.isEmpty()) {
8158 height = fm.height();
8160 tf |= Qt::TextDontPrint;
8162 qreal lineWidth = 0x01000000;
8163 if (wordwrap || (tf & Qt::TextJustificationForced))
8164 lineWidth = qMax<qreal>(0, r.width());
8166 tf |= Qt::TextIncludeTrailingSpaces;
8167 textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
8168 textLayout.beginLayout();
8170 qreal leading = fm.leading();
8174 QTextLine l = textLayout.createLine();
8178 l.setLineWidth(lineWidth);
8180 l.setPosition(QPointF(0., height));
8181 height += l.height();
8182 width = qMax(width, l.naturalTextWidth());
8183 if (!dontclip && !brect && height >= r.height())
8186 textLayout.endLayout();
8191 if (tf & Qt::AlignBottom) {
8192 yoff = r.height() - height;
8193 } else if (tf & Qt::AlignVCenter) {
8194 yoff = (r.height() - height)/2;
8196 QTransform::TransformationType type = painter->transform().type();
8197 if (type <= QTransform::TxScale) {
8198 // do the rounding manually to work around inconsistencies
8199 // in the paint engines when drawing on floating point offsets
8200 const qreal scale = painter->transform().m22();
8202 yoff = -qRound(-yoff * scale) / scale;
8206 if (tf & Qt::AlignRight) {
8207 xoff = r.width() - width;
8208 } else if (tf & Qt::AlignHCenter) {
8209 xoff = (r.width() - width)/2;
8211 QTransform::TransformationType type = painter->transform().type();
8212 if (type <= QTransform::TxScale) {
8213 // do the rounding manually to work around inconsistencies
8214 // in the paint engines when drawing on floating point offsets
8215 const qreal scale = painter->transform().m11();
8217 xoff = qRound(xoff * scale) / scale;
8221 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
8223 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
8225 goto start_lengthVariant;
8230 if (!(tf & Qt::TextDontPrint)) {
8231 bool restore = false;
8232 if (!dontclip && !r.contains(bounds)) {
8235 painter->setClipRect(r, Qt::IntersectClip);
8238 for (int i = 0; i < textLayout.lineCount(); i++) {
8239 QTextLine line = textLayout.lineAt(i);
8241 qreal advance = line.horizontalAdvance();
8243 if (tf & Qt::AlignRight) {
8244 QTextEngine *eng = textLayout.engine();
8245 xoff = r.width() - advance -
8246 eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
8248 else if (tf & Qt::AlignHCenter)
8249 xoff = (r.width() - advance) / 2;
8251 line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
8261 Sets the layout direction used by the painter when drawing text,
8262 to the specified \a direction.
8264 The default is Qt::LayoutDirectionAuto, which will implicitly determine the
8265 direction from the text drawn.
8267 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
8269 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
8273 d->state->layoutDirection = direction;
8277 Returns the layout direction used by the painter when drawing text.
8279 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
8281 Qt::LayoutDirection QPainter::layoutDirection() const
8283 Q_D(const QPainter);
8284 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
8287 QPainterState::QPainterState(const QPainterState *s)
8288 : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
8289 pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
8290 clipRegion(s->clipRegion), clipPath(s->clipPath),
8291 clipOperation(s->clipOperation),
8292 renderHints(s->renderHints), clipInfo(s->clipInfo),
8293 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
8294 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
8295 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
8296 opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
8297 clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
8298 layoutDirection(s->layoutDirection),
8299 composition_mode(s->composition_mode),
8300 emulationSpecifier(s->emulationSpecifier), changeFlags(0)
8302 dirtyFlags = s->dirtyFlags;
8305 QPainterState::QPainterState()
8306 : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
8308 wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
8309 opacity(1), WxF(false), VxF(false), clipEnabled(true),
8310 bgMode(Qt::TransparentMode), painter(0),
8311 layoutDirection(QApplication::layoutDirection()),
8312 composition_mode(QPainter::CompositionMode_SourceOver),
8313 emulationSpecifier(0), changeFlags(0)
8318 QPainterState::~QPainterState()
8322 void QPainterState::init(QPainter *p) {
8323 bgBrush = Qt::white;
8324 bgMode = Qt::TransparentMode;
8328 wx = wy = ww = wh = 0;
8329 vx = vy = vw = vh = 0;
8332 brushOrigin = QPointF(0, 0);
8334 font = deviceFont = QFont();
8335 clipRegion = QRegion();
8336 clipPath = QPainterPath();
8337 clipOperation = Qt::NoClip;
8339 worldMatrix.reset();
8341 layoutDirection = QApplication::layoutDirection();
8342 composition_mode = QPainter::CompositionMode_SourceOver;
8343 emulationSpecifier = 0;
8351 static void bitBlt_helper(QPaintDevice *dst, const QPoint &dp,
8352 const QPaintDevice *src, const QRect &sr, bool)
8357 if (src->devType() == QInternal::Pixmap) {
8358 const QPixmap *pixmap = static_cast<const QPixmap *>(src);
8360 pt.drawPixmap(dp, *pixmap, sr);
8363 qWarning("QPainter: bitBlt only works when source is of type pixmap");
8367 void bitBlt(QPaintDevice *dst, int dx, int dy,
8368 const QPaintDevice *src, int sx, int sy, int sw, int sh,
8371 bitBlt_helper(dst, QPoint(dx, dy), src, QRect(sx, sy, sw, sh), ignoreMask);
8374 void bitBlt(QPaintDevice *dst, const QPoint &dp, const QPaintDevice *src, const QRect &sr, bool ignoreMask)
8376 bitBlt_helper(dst, dp, src, sr, ignoreMask);
8379 void bitBlt(QPaintDevice *dst, int dx, int dy,
8380 const QImage *src, int sx, int sy, int sw, int sh, int fl)
8382 Qt::ImageConversionFlags flags(fl);
8383 QPixmap srcPixmap = QPixmap::fromImage(*src, flags);
8384 bitBlt_helper(dst, QPoint(dx, dy), &srcPixmap, QRect(sx, sy, sw, sh), false);
8387 #endif // QT3_SUPPORT
8390 \fn void QPainter::setBackgroundColor(const QColor &color)
8392 Use setBackground() instead.
8396 \fn const QColor &QPainter::backgroundColor() const
8398 Use background() and QBrush::color() instead.
8401 QColor myColor = backgroundColor();
8403 QColor myColor = background().color();
8406 Note that the background can be a complex brush such as a texture
8411 \fn void QPainter::drawText(int x, int y, const QString &text, int pos, int length)
8414 Use drawText() combined with QString::mid() instead.
8417 QPainter painter(this);
8418 painter.drawText(x, y, text, pos, length);
8420 QPainter painter(this);
8421 painter.drawText(x, y, text.mid(pos, length));
8426 \fn void QPainter::drawText(const QPoint &point, const QString &text, int pos, int length)
8429 Use drawText() combined with QString::mid() instead.
8432 QPainter painter(this);
8433 painter.drawText(point, text, pos, length);
8435 QPainter painter(this);
8436 painter.drawText(point, text.mid(pos, length));
8441 \fn void QPainter::drawText(int x, int y, const QString &text, int length)
8444 Use drawText() combined with QString::left() instead.
8447 QPainter painter(this);
8448 painter.drawText(x, y, text, length);
8450 QPainter painter(this);
8451 painter.drawText(x, y, text.left(length));
8456 \fn void QPainter::drawText(const QPoint &point, const QString &text, int length)
8459 Use drawText() combined with QString::left() instead.
8462 QPainter painter(this);
8463 painter.drawText(point, text, length);
8465 QPainter painter(this);
8466 painter.drawText(point, text.left(length));
8471 \fn bool QPainter::begin(QPaintDevice *device, const QWidget *init)
8474 Use begin() instead.
8476 If the paint \a device is a QWidget, QPainter is initialized after
8477 the widget's settings automatically. Otherwise, you must call the
8478 initFrom() function to initialize the painters pen, background and
8479 font to the same as any given widget.
8482 QPainter painter(this);
8483 painter.begin(device, init);
8485 QPainter painter(this);
8486 painter.begin(device);
8487 painter.initFrom(init);
8492 \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
8493 Qt::ImageConversionFlags flags)
8495 Draws the rectangular portion \a source of the given \a image
8496 into the \a target rectangle in the paint device.
8498 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8500 If the image needs to be modified to fit in a lower-resolution
8501 result (e.g. converting from 32-bit to 8-bit), use the \a flags to
8502 specify how you would prefer this to happen.
8507 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 20
8514 \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
8515 Qt::ImageConversionFlags flags)
8518 Draws the rectangular portion \a source of the given \a image
8519 into the \a target rectangle in the paint device.
8521 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8525 \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
8529 Draws the given \a image at the given \a point.
8533 \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
8537 Draws the given \a image at the given \a point.
8541 \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
8542 Qt::ImageConversionFlags flags = 0)
8546 Draws the rectangular portion \a source of the given \a image with
8547 its origin at the given \a point.
8551 \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
8552 Qt::ImageConversionFlags flags = 0)
8555 Draws the rectangular portion \a source of the given \a image with
8556 its origin at the given \a point.
8560 \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
8564 Draws the given \a image into the given \a rectangle.
8566 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8570 \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
8574 Draws the given \a image into the given \a rectangle.
8576 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8580 \fn void QPainter::drawImage(int x, int y, const QImage &image,
8581 int sx, int sy, int sw, int sh,
8582 Qt::ImageConversionFlags flags)
8585 Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
8588 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
8589 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
8590 image that is to be drawn. The default is (0, 0).
8592 (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
8593 The default, (0, 0) (and negative) means all the way to the
8594 bottom-right of the image.
8598 \fn void QPainter::redirect(QPaintDevice *pdev, QPaintDevice *replacement)
8600 Use setRedirected() instead.
8604 \fn QPaintDevice *QPainter::redirect(QPaintDevice *pdev)
8606 Use redirected() instead.
8610 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
8611 const QString &text, int length)
8614 Returns the bounding rectangle for the given \a length of the \a
8615 text constrained by the provided \a rectangle.
8617 Use boundingRect() combined with QString::left() instead.
8620 QRect rectangle = boundingRect(rect, flags, text, length);
8622 QRect rectangle = boundingRect(rect, flags, text.left(length));
8627 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text,
8628 int length, QRect *br)
8631 Use drawText() combined with QString::left() instead.
8634 QPainter painter(this);
8635 painter.drawText(rectangle, flags, text, length, br );
8637 QPainter painter(this);
8638 painter.drawText(rectangle, flags, text.left(length), br );
8643 \fn QRect QPainter::boundingRect(int x, int y, int width, int height, int flags,
8644 const QString &text, int length);
8648 Returns the bounding rectangle for the given \a length of the \a
8649 text constrained by the rectangle that begins at point (\a{x},
8650 \a{y}) with the given \a width and \a height.
8652 Use boundingRect() combined with QString::left() instead.
8655 QRect rectangle = boundingRect(x, y, width, height, flags, text, length);
8657 QRect rectangle = boundingRect(x, y, width, height, flags, text.left(length));
8662 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
8663 const QString &text, int length, QRect *br)
8667 Use drawText() combined with QString::left() instead.
8670 QPainter painter(this);
8671 painter.drawText(x, y, width, height, flags, text, length, br );
8673 QPainter painter(this);
8674 painter.drawText(x, y, width, height, flags, text.left(length), br );
8680 \class QPaintEngineState
8683 \brief The QPaintEngineState class provides information about the
8684 active paint engine's current state.
8687 QPaintEngineState records which properties that have changed since
8688 the last time the paint engine was updated, as well as their
8691 Which properties that have changed can at any time be retrieved
8692 using the state() function. This function returns an instance of
8693 the QPaintEngine::DirtyFlags type which stores an OR combination
8694 of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
8695 enum defines whether a property has changed since the last update
8698 If a property is marked with a dirty flag, its current value can
8699 be retrieved using the corresponding get function:
8704 \header \o Property Flag \o Current Property Value
8705 \row \o QPaintEngine::DirtyBackground \o backgroundBrush()
8706 \row \o QPaintEngine::DirtyBackgroundMode \o backgroundMode()
8707 \row \o QPaintEngine::DirtyBrush \o brush()
8708 \row \o QPaintEngine::DirtyBrushOrigin \o brushOrigin()
8709 \row \o QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
8711 \row \o QPaintEngine::DirtyClipPath \o clipPath()
8712 \row \o QPaintEngine::DirtyClipRegion \o clipRegion()
8713 \row \o QPaintEngine::DirtyCompositionMode \o compositionMode()
8714 \row \o QPaintEngine::DirtyFont \o font()
8715 \row \o QPaintEngine::DirtyTransform \o transform()
8716 \row \o QPaintEngine::DirtyClipEnabled \o isClipEnabled()
8717 \row \o QPaintEngine::DirtyPen \o pen()
8718 \row \o QPaintEngine::DirtyHints \o renderHints()
8721 The QPaintEngineState class also provide the painter() function
8722 which returns a pointer to the painter that is currently updating
8725 An instance of this class, representing the current state of the
8726 active paint engine, is passed as argument to the
8727 QPaintEngine::updateState() function. The only situation in which
8728 you will have to use this class directly is when implementing your
8736 \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
8738 Returns a combination of flags identifying the set of properties
8739 that need to be updated when updating the paint engine's state
8740 (i.e. during a call to the QPaintEngine::updateState() function).
8742 \sa QPaintEngine::updateState()
8747 Returns the pen in the current paint engine state.
8749 This variable should only be used when the state() returns a
8750 combination which includes the QPaintEngine::DirtyPen flag.
8752 \sa state(), QPaintEngine::updateState()
8755 QPen QPaintEngineState::pen() const
8757 return static_cast<const QPainterState *>(this)->pen;
8761 Returns the brush in the current paint engine state.
8763 This variable should only be used when the state() returns a
8764 combination which includes the QPaintEngine::DirtyBrush flag.
8766 \sa state(), QPaintEngine::updateState()
8769 QBrush QPaintEngineState::brush() const
8771 return static_cast<const QPainterState *>(this)->brush;
8775 Returns the brush origin in the current paint engine state.
8777 This variable should only be used when the state() returns a
8778 combination which includes the QPaintEngine::DirtyBrushOrigin flag.
8780 \sa state(), QPaintEngine::updateState()
8783 QPointF QPaintEngineState::brushOrigin() const
8785 return static_cast<const QPainterState *>(this)->brushOrigin;
8789 Returns the background brush in the current paint engine state.
8791 This variable should only be used when the state() returns a
8792 combination which includes the QPaintEngine::DirtyBackground flag.
8794 \sa state(), QPaintEngine::updateState()
8797 QBrush QPaintEngineState::backgroundBrush() const
8799 return static_cast<const QPainterState *>(this)->bgBrush;
8803 Returns the background mode in the current paint engine
8806 This variable should only be used when the state() returns a
8807 combination which includes the QPaintEngine::DirtyBackgroundMode flag.
8809 \sa state(), QPaintEngine::updateState()
8812 Qt::BGMode QPaintEngineState::backgroundMode() const
8814 return static_cast<const QPainterState *>(this)->bgMode;
8818 Returns the font in the current paint engine
8821 This variable should only be used when the state() returns a
8822 combination which includes the QPaintEngine::DirtyFont flag.
8824 \sa state(), QPaintEngine::updateState()
8827 QFont QPaintEngineState::font() const
8829 return static_cast<const QPainterState *>(this)->font;
8836 Returns the matrix in the current paint engine
8839 \note It is advisable to use transform() instead of this function to
8840 preserve the properties of perspective transformations.
8842 This variable should only be used when the state() returns a
8843 combination which includes the QPaintEngine::DirtyTransform flag.
8845 \sa state(), QPaintEngine::updateState()
8848 QMatrix QPaintEngineState::matrix() const
8850 const QPainterState *st = static_cast<const QPainterState *>(this);
8852 return st->matrix.toAffine();
8858 Returns the matrix in the current paint engine state.
8860 This variable should only be used when the state() returns a
8861 combination which includes the QPaintEngine::DirtyTransform flag.
8863 \sa state(), QPaintEngine::updateState()
8867 QTransform QPaintEngineState::transform() const
8869 const QPainterState *st = static_cast<const QPainterState *>(this);
8876 Returns the clip operation in the current paint engine
8879 This variable should only be used when the state() returns a
8880 combination which includes either the QPaintEngine::DirtyClipPath
8881 or the QPaintEngine::DirtyClipRegion flag.
8883 \sa state(), QPaintEngine::updateState()
8886 Qt::ClipOperation QPaintEngineState::clipOperation() const
8888 return static_cast<const QPainterState *>(this)->clipOperation;
8894 Returns whether the coordinate of the fill have been specified
8895 as bounded by the current rendering operation and have to be
8896 resolved (about the currently rendered primitive).
8898 bool QPaintEngineState::brushNeedsResolving() const
8900 const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
8901 return needsResolving(brush);
8908 Returns whether the coordinate of the stroke have been specified
8909 as bounded by the current rendering operation and have to be
8910 resolved (about the currently rendered primitive).
8912 bool QPaintEngineState::penNeedsResolving() const
8914 const QPen &pen = static_cast<const QPainterState *>(this)->pen;
8915 return needsResolving(pen.brush());
8919 Returns the clip region in the current paint engine state.
8921 This variable should only be used when the state() returns a
8922 combination which includes the QPaintEngine::DirtyClipRegion flag.
8924 \sa state(), QPaintEngine::updateState()
8927 QRegion QPaintEngineState::clipRegion() const
8929 return static_cast<const QPainterState *>(this)->clipRegion;
8933 Returns the clip path in the current paint engine state.
8935 This variable should only be used when the state() returns a
8936 combination which includes the QPaintEngine::DirtyClipPath flag.
8938 \sa state(), QPaintEngine::updateState()
8941 QPainterPath QPaintEngineState::clipPath() const
8943 return static_cast<const QPainterState *>(this)->clipPath;
8947 Returns whether clipping is enabled or not in the current paint
8950 This variable should only be used when the state() returns a
8951 combination which includes the QPaintEngine::DirtyClipEnabled
8954 \sa state(), QPaintEngine::updateState()
8957 bool QPaintEngineState::isClipEnabled() const
8959 return static_cast<const QPainterState *>(this)->clipEnabled;
8963 Returns the render hints in the current paint engine state.
8965 This variable should only be used when the state() returns a
8966 combination which includes the QPaintEngine::DirtyHints
8969 \sa state(), QPaintEngine::updateState()
8972 QPainter::RenderHints QPaintEngineState::renderHints() const
8974 return static_cast<const QPainterState *>(this)->renderHints;
8978 Returns the composition mode in the current paint engine state.
8980 This variable should only be used when the state() returns a
8981 combination which includes the QPaintEngine::DirtyCompositionMode
8984 \sa state(), QPaintEngine::updateState()
8987 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8989 return static_cast<const QPainterState *>(this)->composition_mode;
8994 Returns a pointer to the painter currently updating the paint
8998 QPainter *QPaintEngineState::painter() const
9000 return static_cast<const QPainterState *>(this)->painter;
9007 Returns the opacity in the current paint engine state.
9010 qreal QPaintEngineState::opacity() const
9012 return static_cast<const QPainterState *>(this)->opacity;
9018 Sets the world transformation matrix.
9019 If \a combine is true, the specified \a transform is combined with
9020 the current matrix; otherwise it replaces the current matrix.
9022 \sa transform() setWorldTransform()
9025 void QPainter::setTransform(const QTransform &transform, bool combine )
9027 setWorldTransform(transform, combine);
9031 Returns the world transformation matrix.
9033 \sa worldTransform()
9036 const QTransform & QPainter::transform() const
9038 return worldTransform();
9043 Returns the matrix that transforms from logical coordinates to
9044 device coordinates of the platform dependent paint device.
9046 This function is \e only needed when using platform painting
9047 commands on the platform dependent handle (Qt::HANDLE), and the
9048 platform does not do transformations nativly.
9050 The QPaintEngine::PaintEngineFeature enum can be queried to
9051 determine whether the platform performs the transformations or
9054 \sa worldTransform(), QPaintEngine::hasFeature(),
9057 const QTransform & QPainter::deviceTransform() const
9059 Q_D(const QPainter);
9061 qWarning("QPainter::deviceTransform: Painter not active");
9062 return d->fakeState()->transform;
9064 return d->state->matrix;
9069 Resets any transformations that were made using translate(),
9070 scale(), shear(), rotate(), setWorldTransform(), setViewport()
9073 \sa {Coordinate Transformations}
9076 void QPainter::resetTransform()
9079 #ifdef QT_DEBUG_DRAW
9080 if (qt_show_painter_debug_output)
9081 printf("QPainter::resetMatrix()\n");
9084 qWarning("QPainter::resetMatrix: Painter not active");
9088 d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins
9089 d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
9090 d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
9091 d->state->worldMatrix = QTransform();
9092 setMatrixEnabled(false);
9093 setViewTransformEnabled(false);
9095 d->extended->transformChanged();
9097 d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
9101 Sets the world transformation matrix.
9102 If \a combine is true, the specified \a matrix is combined with the current matrix;
9103 otherwise it replaces the current matrix.
9105 \sa transform(), setTransform()
9108 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
9113 qWarning("QPainter::setWorldTransform: Painter not active");
9118 d->state->worldMatrix = matrix * d->state->worldMatrix; // combines
9120 d->state->worldMatrix = matrix; // set new matrix
9122 d->state->WxF = true;
9127 Returns the world transformation matrix.
9130 const QTransform & QPainter::worldTransform() const
9132 Q_D(const QPainter);
9134 qWarning("QPainter::worldTransform: Painter not active");
9135 return d->fakeState()->transform;
9137 return d->state->worldMatrix;
9141 Returns the transformation matrix combining the current
9142 window/viewport and world transformation.
9144 \sa setWorldTransform(), setWindow(), setViewport()
9147 QTransform QPainter::combinedTransform() const
9149 Q_D(const QPainter);
9151 qWarning("QPainter::combinedTransform: Painter not active");
9152 return QTransform();
9154 return d->state->worldMatrix * d->viewTransform();
9160 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
9161 at multiple positions with different scale, rotation and opacity. \a
9162 fragments is an array of \a fragmentCount elements specifying the
9163 parameters used to draw each pixmap fragment. The \a hints
9164 parameter can be used to pass in drawing hints.
9166 This function is potentially faster than multiple calls to drawPixmap(),
9167 since the backend can optimize state changes.
9169 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
9172 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
9173 const QPixmap &pixmap, PixmapFragmentHints hints)
9177 if (!d->engine || pixmap.isNull())
9181 for (int i = 0; i < fragmentCount; ++i) {
9182 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
9183 fragments[i].width, fragments[i].height);
9184 if (!(QRectF(pixmap.rect()).contains(sourceRect)))
9185 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
9189 if (d->engine->isExtended()) {
9190 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
9192 qreal oldOpacity = opacity();
9193 QTransform oldTransform = transform();
9195 for (int i = 0; i < fragmentCount; ++i) {
9196 QTransform transform = oldTransform;
9199 if (fragments[i].rotation == 0) {
9200 xOffset = fragments[i].x;
9201 yOffset = fragments[i].y;
9203 transform.translate(fragments[i].x, fragments[i].y);
9204 transform.rotate(fragments[i].rotation);
9206 setOpacity(oldOpacity * fragments[i].opacity);
9207 setTransform(transform);
9209 qreal w = fragments[i].scaleX * fragments[i].width;
9210 qreal h = fragments[i].scaleY * fragments[i].height;
9211 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
9212 fragments[i].width, fragments[i].height);
9213 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
9216 setOpacity(oldOpacity);
9217 setTransform(oldTransform);
9223 \class QPainter::PixmapFragment
9225 \brief This class is used in conjunction with the
9226 QPainter::drawPixmapFragments() function to specify how a pixmap, or
9227 sub-rect of a pixmap, is drawn.
9229 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
9230 as a source rectangle within the pixmap passed into the
9231 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
9232 width and \a height are used to calculate the target rectangle that is
9233 drawn. \a x and \a y denotes the center of the target rectangle. The \a
9234 width and \a height in the target rectangle is scaled by the \a scaleX and
9235 \a scaleY values. The resulting target rectangle is then rotated \a
9236 rotation degrees around the \a x, \a y center point.
9238 \sa QPainter::drawPixmapFragments()
9244 This is a convenience function that returns a QPainter::PixmapFragment that is
9245 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
9246 rotation, \a opacity parameters.
9249 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
9250 qreal scaleX, qreal scaleY, qreal rotation,
9253 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
9254 sourceRect.height(), scaleX, scaleY, rotation, opacity};
9259 \variable QPainter::PixmapFragment::x
9260 \brief the x coordinate of center point in the target rectangle.
9264 \variable QPainter::PixmapFragment::y
9265 \brief the y coordinate of the center point in the target rectangle.
9269 \variable QPainter::PixmapFragment::sourceLeft
9270 \brief the left coordinate of the source rectangle.
9274 \variable QPainter::PixmapFragment::sourceTop
9275 \brief the top coordinate of the source rectangle.
9279 \variable QPainter::PixmapFragment::width
9281 \brief the width of the source rectangle and is used to calculate the width
9282 of the target rectangle.
9286 \variable QPainter::PixmapFragment::height
9288 \brief the height of the source rectangle and is used to calculate the
9289 height of the target rectangle.
9293 \variable QPainter::PixmapFragment::scaleX
9294 \brief the horizontal scale of the target rectangle.
9298 \variable QPainter::PixmapFragment::scaleY
9299 \brief the vertical scale of the target rectangle.
9303 \variable QPainter::PixmapFragment::rotation
9305 \brief the rotation of the target rectangle in degrees. The target
9306 rectangle is rotated after it has been scaled.
9310 \variable QPainter::PixmapFragment::opacity
9312 \brief the opacity of the target rectangle, where 0.0 is fully transparent
9313 and 1.0 is fully opaque.
9319 \enum QPainter::PixmapFragmentHint
9321 \value OpaqueHint Indicates that the pixmap fragments to be drawn are
9322 opaque. Opaque fragments are potentially faster to draw.
9324 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
9327 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
9329 p->draw_helper(path, operation);
9332 /*! \fn Display *QPaintDevice::x11Display() const
9333 Use QX11Info::display() instead.
9336 Display *display = widget->x11Display();
9338 Display *display = QX11Info::display();
9341 \sa QWidget::x11Info(), QX11Info::display()
9344 /*! \fn int QPaintDevice::x11Screen() const
9345 Use QX11Info::screen() instead.
9348 int screen = widget->x11Screen();
9350 int screen = widget->x11Info().screen();
9353 \sa QWidget::x11Info(), QPixmap::x11Info()
9356 /*! \fn void *QPaintDevice::x11Visual() const
9357 Use QX11Info::visual() instead.
9360 void *visual = widget->x11Visual();
9362 void *visual = widget->x11Info().visual();
9365 \sa QWidget::x11Info(), QPixmap::x11Info()
9368 /*! \fn int QPaintDevice::x11Depth() const
9369 Use QX11Info::depth() instead.
9372 int depth = widget->x11Depth();
9374 int depth = widget->x11Info().depth();
9377 \sa QWidget::x11Info(), QPixmap::x11Info()
9380 /*! \fn int QPaintDevice::x11Cells() const
9381 Use QX11Info::cells() instead.
9384 int cells = widget->x11Cells();
9386 int cells = widget->x11Info().cells();
9389 \sa QWidget::x11Info(), QPixmap::x11Info()
9392 /*! \fn Qt::HANDLE QPaintDevice::x11Colormap() const
9393 Use QX11Info::colormap() instead.
9396 unsigned long screen = widget->x11Colormap();
9398 unsigned long screen = widget->x11Info().colormap();
9401 \sa QWidget::x11Info(), QPixmap::x11Info()
9404 /*! \fn bool QPaintDevice::x11DefaultColormap() const
9405 Use QX11Info::defaultColormap() instead.
9408 bool isDefault = widget->x11DefaultColormap();
9410 bool isDefault = widget->x11Info().defaultColormap();
9413 \sa QWidget::x11Info(), QPixmap::x11Info()
9416 /*! \fn bool QPaintDevice::x11DefaultVisual() const
9417 Use QX11Info::defaultVisual() instead.
9420 bool isDefault = widget->x11DefaultVisual();
9422 bool isDefault = widget->x11Info().defaultVisual();
9425 \sa QWidget::x11Info(), QPixmap::x11Info()
9428 /*! \fn void *QPaintDevice::x11AppVisual(int screen)
9429 Use QX11Info::visual() instead.
9432 void *visual = QPaintDevice::x11AppVisual(screen);
9434 void *visual = qApp->x11Info(screen).visual();
9437 \sa QWidget::x11Info(), QPixmap::x11Info()
9440 /*! \fn Qt::HANDLE QPaintDevice::x11AppColormap(int screen)
9441 Use QX11Info::colormap() instead.
9444 unsigned long colormap = QPaintDevice::x11AppColormap(screen);
9446 unsigned long colormap = qApp->x11Info(screen).colormap();
9449 \sa QWidget::x11Info(), QPixmap::x11Info()
9452 /*! \fn Display *QPaintDevice::x11AppDisplay()
9453 Use QX11Info::display() instead.
9456 Display *display = QPaintDevice::x11AppDisplay();
9458 Display *display = qApp->x11Info().display();
9461 \sa QWidget::x11Info(), QPixmap::x11Info()
9464 /*! \fn int QPaintDevice::x11AppScreen()
9465 Use QX11Info::screen() instead.
9468 int screen = QPaintDevice::x11AppScreen();
9470 int screen = qApp->x11Info().screen();
9473 \sa QWidget::x11Info(), QPixmap::x11Info()
9476 /*! \fn int QPaintDevice::x11AppDepth(int screen)
9477 Use QX11Info::depth() instead.
9480 int depth = QPaintDevice::x11AppDepth(screen);
9482 int depth = qApp->x11Info(screen).depth();
9485 \sa QWidget::x11Info(), QPixmap::x11Info()
9488 /*! \fn int QPaintDevice::x11AppCells(int screen)
9489 Use QX11Info::cells() instead.
9492 int cells = QPaintDevice::x11AppCells(screen);
9494 int cells = qApp->x11Info(screen).cells();
9497 \sa QWidget::x11Info(), QPixmap::x11Info()
9500 /*! \fn Qt::HANDLE QPaintDevice::x11AppRootWindow(int screen)
9501 Use QX11Info::appRootWindow() instead.
9504 unsigned long window = QPaintDevice::x11AppRootWindow(screen);
9506 unsigned long window = qApp->x11Info(screen).appRootWindow();
9509 \sa QWidget::x11Info(), QPixmap::x11Info()
9512 /*! \fn bool QPaintDevice::x11AppDefaultColormap(int screen)
9513 Use QX11Info::defaultColormap() instead.
9516 bool isDefault = QPaintDevice::x11AppDefaultColormap(screen);
9518 bool isDefault = qApp->x11Info(screen).defaultColormap();
9521 \sa QWidget::x11Info(), QPixmap::x11Info()
9524 /*! \fn bool QPaintDevice::x11AppDefaultVisual(int screen)
9525 Use QX11Info::defaultVisual() instead.
9528 bool isDefault = QPaintDevice::x11AppDefaultVisual(screen);
9530 bool isDefault = qApp->x11Info(screen).defaultVisual();
9533 \sa QWidget::x11Info(), QPixmap::x11Info()
9536 /*! \fn void QPaintDevice::x11SetAppDpiX(int dpi, int screen)
9537 Use QX11Info::setAppDpiX() instead.
9540 /*! \fn void QPaintDevice::x11SetAppDpiY(int dpi, int screen)
9541 Use QX11Info::setAppDpiY() instead.
9544 /*! \fn int QPaintDevice::x11AppDpiX(int screen)
9545 Use QX11Info::appDpiX() instead.
9548 bool isDefault = QPaintDevice::x11AppDpiX(screen);
9550 bool isDefault = qApp->x11Info(screen).appDpiX();
9553 \sa QWidget::x11Info(), QPixmap::x11Info()
9556 /*! \fn int QPaintDevice::x11AppDpiY(int screen)
9557 Use QX11Info::appDpiY() instead.
9560 bool isDefault = QPaintDevice::x11AppDpiY(screen);
9562 bool isDefault = qApp->x11Info(screen).appDpiY();
9565 \sa QWidget::x11Info(), QPixmap::x11Info()
9568 /*! \fn HDC QPaintDevice::getDC() const
9572 /*! \fn void QPaintDevice::releaseDC(HDC) const
9576 /*! \fn QWSDisplay *QPaintDevice::qwsDisplay()