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;
163 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
166 case QInternal::Image:
167 case QInternal::Printer:
168 case QInternal::Picture:
169 // can be drawn onto these devices safely from any thread
176 if (QApplication::testAttribute(Qt::AA_X11InitThreads))
179 if (!extraCondition && QThread::currentThread() != qApp->thread()) {
180 qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
189 void QPainterPrivate::checkEmulation()
192 if (extended->flags() & QPaintEngineEx::DoNotEmulate)
195 bool doEmulation = false;
196 if (state->bgMode == Qt::OpaqueMode)
199 const QGradient *bg = state->brush.gradient();
200 if (bg && bg->coordinateMode() > QGradient::LogicalMode)
203 const QGradient *pg = qpen_brush(state->pen).gradient();
204 if (pg && pg->coordinateMode() > QGradient::LogicalMode)
208 if (extended != emulationEngine) {
209 if (!emulationEngine)
210 emulationEngine = new QEmulationPaintEngine(extended);
211 extended = emulationEngine;
212 extended->setState(state);
214 } else if (emulationEngine == extended) {
215 extended = emulationEngine->real_engine;
220 QPainterPrivate::~QPainterPrivate()
222 delete emulationEngine;
223 for (int i=0; i<states.size(); ++i)
231 QTransform QPainterPrivate::viewTransform() const
234 qreal scaleW = qreal(state->vw)/qreal(state->ww);
235 qreal scaleH = qreal(state->vh)/qreal(state->wh);
236 return QTransform(scaleW, 0, 0, scaleH,
237 state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
245 Returns true if using a shared painter; otherwise false.
247 bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
252 if (pdev->devType() != QInternal::Widget)
255 QWidget *widget = static_cast<QWidget *>(pdev);
258 // Someone either called QPainter::setRedirected in the widget's paint event
259 // right before this painter was created (or begin was called) or
260 // sent a paint event directly to the widget.
261 if (!widget->d_func()->redirectDev)
264 QPainter *sp = widget->d_func()->sharedPainter();
265 if (!sp || !sp->isActive())
268 if (sp->paintEngine()->paintDevice() != widget->d_func()->redirectDev)
271 // Check if we're attempting to paint outside a paint event.
272 if (!sp->d_ptr->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent)
273 && !widget->testAttribute(Qt::WA_PaintOutsidePaintEvent)
274 && !widget->testAttribute(Qt::WA_WState_InPaintEvent)) {
276 qWarning("QPainter::begin: Widget painting can only begin as a result of a paintEvent");
280 // Save the current state of the shared painter and assign
281 // the current d_ptr to the shared painter's d_ptr.
283 if (!sp->d_ptr->d_ptrs) {
284 // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
285 // redirections within the same paintEvent(), which should be enough
286 // in 99% of all cases). E.g: A renders B which renders C which renders D.
287 sp->d_ptr->d_ptrs_size = 4;
288 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
289 Q_CHECK_PTR(sp->d_ptr->d_ptrs);
290 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
291 // However, to support corner cases we grow the array dynamically if needed.
292 sp->d_ptr->d_ptrs_size <<= 1;
293 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
294 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
296 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
298 q->d_ptr.reset(sp->d_ptr.data());
300 Q_ASSERT(q->d_ptr->state);
302 // Now initialize the painter with correct widget properties.
305 widget->d_func()->redirected(&offset);
306 offset += q->d_ptr->engine->coordinateOffset();
308 // Update system rect.
309 q->d_ptr->state->ww = q->d_ptr->state->vw = widget->width();
310 q->d_ptr->state->wh = q->d_ptr->state->vh = widget->height();
313 if (q->d_ptr->state->WxF) {
314 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix;
315 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
316 q->d_ptr->state->worldMatrix = QTransform();
317 q->d_ptr->state->WxF = false;
319 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
321 q->d_ptr->updateMatrix();
323 QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
324 if (enginePrivate->currentClipWidget == widget) {
325 enginePrivate->systemStateChanged();
329 // Update system transform and clip.
330 enginePrivate->currentClipWidget = widget;
331 enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
335 void QPainterPrivate::detachPainterPrivate(QPainter *q)
337 Q_ASSERT(refcount > 1);
340 QPainterPrivate *original = d_ptrs[--refcount - 1];
342 inDestructor = false;
344 original->inDestructor = true;
345 } else if (!original) {
346 original = new QPainterPrivate(q);
349 d_ptrs[refcount - 1] = 0;
352 q->d_ptr.reset(original);
354 if (emulationEngine) {
355 extended = emulationEngine->real_engine;
356 delete emulationEngine;
362 void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op)
365 if (qt_show_painter_debug_output) {
366 printf("QPainter::drawHelper\n");
370 if (originalPath.isEmpty())
373 QPaintEngine::PaintEngineFeatures gradientStretch =
374 QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
375 | QPaintEngine::ObjectBoundingModeGradients);
377 const bool mustEmulateObjectBoundingModeGradients = extended
378 || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients)
379 && !engine->hasFeature(QPaintEngine::PatternTransform));
381 if (!(state->emulationSpecifier & ~gradientStretch)
382 && !mustEmulateObjectBoundingModeGradients) {
383 drawStretchedGradient(originalPath, op);
385 } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {
386 drawOpaqueBackground(originalPath, op);
392 qreal strokeOffsetX = 0, strokeOffsetY = 0;
394 QPainterPath path = originalPath * state->matrix;
395 QRectF pathBounds = path.boundingRect();
397 bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
399 qreal penWidth = state->pen.widthF();
404 // In case of complex xform
405 if (state->matrix.type() > QTransform::TxScale) {
406 QPainterPathStroker stroker;
407 stroker.setWidth(penWidth);
408 stroker.setJoinStyle(state->pen.joinStyle());
409 stroker.setCapStyle(state->pen.capStyle());
410 QPainterPath stroke = stroker.createStroke(originalPath);
411 strokeBounds = (stroke * state->matrix).boundingRect();
413 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);
414 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);
420 if (!strokeBounds.isEmpty()) {
421 absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
423 absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
424 .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
427 if (q->hasClipping()) {
428 bool hasPerspectiveTransform = false;
429 for (int i = 0; i < state->clipInfo.size(); ++i) {
430 const QPainterClipInfo &info = state->clipInfo.at(i);
431 if (info.matrix.type() == QTransform::TxProject) {
432 hasPerspectiveTransform = true;
436 // avoid mapping QRegions with perspective transforms
437 if (!hasPerspectiveTransform) {
438 // The trick with txinv and invMatrix is done in order to
439 // avoid transforming the clip to logical coordinates, and
440 // then back to device coordinates. This is a problem with
441 // QRegion/QRect based clips, since they use integer
442 // coordinates and converting to/from logical coordinates will
444 bool old_txinv = txinv;
445 QTransform old_invMatrix = invMatrix;
447 invMatrix = QTransform();
448 QPainterPath clipPath = q->clipPath();
449 QRectF r = clipPath.boundingRect().intersected(absPathRect);
450 absPathRect = r.toAlignedRect();
452 invMatrix = old_invMatrix;
456 // qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
457 // devMinX, devMinY, device->width(), device->height());
458 // qDebug() << " - matrix" << state->matrix;
459 // qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
460 // qDebug() << " - path.bounds" << path.boundingRect();
462 if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
465 QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
470 p.d_ptr->helper_device = helper_device;
472 p.setOpacity(state->opacity);
473 p.translate(-absPathRect.x(), -absPathRect.y());
474 p.setTransform(state->matrix, true);
475 p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
476 p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
477 p.setBackground(state->bgBrush);
478 p.setBackgroundMode(state->bgMode);
479 p.setBrushOrigin(state->brushOrigin);
481 p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);
482 p.setRenderHint(QPainter::SmoothPixmapTransform,
483 state->renderHints & QPainter::SmoothPixmapTransform);
485 p.drawPath(originalPath);
488 static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0;
489 if (do_fallback_overlay) {
490 QImage block(8, 8, QImage::Format_ARGB32_Premultiplied);
492 pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
493 pt.drawLine(0, 0, 8, 8);
496 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
498 p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
505 state->matrix = QTransform();
506 state->dirtyFlags |= QPaintEngine::DirtyTransform;
508 engine->drawImage(absPathRect,
510 QRectF(0, 0, absPathRect.width(), absPathRect.height()),
511 Qt::OrderedDither | Qt::OrderedAlphaDither);
515 void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op)
519 q->setBackgroundMode(Qt::TransparentMode);
521 if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
522 q->fillPath(path, state->bgBrush.color());
523 q->fillPath(path, state->brush);
526 if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
527 q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
528 q->strokePath(path, state->pen);
531 q->setBackgroundMode(Qt::OpaqueMode);
534 static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
536 Q_ASSERT(brush.style() >= Qt::LinearGradientPattern
537 && brush.style() <= Qt::ConicalGradientPattern);
539 QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
540 boundingRect.x(), boundingRect.y());
542 QGradient g = *brush.gradient();
543 g.setCoordinateMode(QGradient::LogicalMode);
546 b.setTransform(gradientToUser * b.transform());
550 void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op)
554 const qreal sw = helper_device->width();
555 const qreal sh = helper_device->height();
557 bool changedPen = false;
558 bool changedBrush = false;
559 bool needsFill = false;
561 const QPen pen = state->pen;
562 const QBrush brush = state->brush;
564 const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
565 const QGradient::CoordinateMode brushMode = coordinateMode(brush);
569 // Draw the xformed fill if the brush is a stretch gradient.
570 if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
571 if (brushMode == QGradient::StretchToDeviceMode) {
572 q->setPen(Qt::NoPen);
573 changedPen = pen.style() != Qt::NoPen;
577 const qreal isw = 1.0 / sw;
578 const qreal ish = 1.0 / sh;
579 QTransform inv(isw, 0, 0, ish, 0, 0);
580 engine->drawPath(path * inv);
585 if (brushMode == QGradient::ObjectBoundingMode) {
586 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
587 boundingRect = path.boundingRect();
588 q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
594 if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
595 // Draw the xformed outline if the pen is a stretch gradient.
596 if (penMode == QGradient::StretchToDeviceMode) {
597 q->setPen(Qt::NoPen);
602 engine->drawPath(path);
606 q->setBrush(pen.brush());
610 QPainterPathStroker stroker;
611 stroker.setDashPattern(pen.style());
612 stroker.setWidth(pen.widthF());
613 stroker.setJoinStyle(pen.joinStyle());
614 stroker.setCapStyle(pen.capStyle());
615 stroker.setMiterLimit(pen.miterLimit());
616 QPainterPath stroke = stroker.createStroke(path);
618 const qreal isw = 1.0 / sw;
619 const qreal ish = 1.0 / sh;
620 QTransform inv(isw, 0, 0, ish, 0, 0);
621 engine->drawPath(stroke * inv);
624 if (!needsFill && brush.style() != Qt::NoBrush) {
625 q->setBrush(Qt::NoBrush);
629 if (penMode == QGradient::ObjectBoundingMode) {
630 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
632 // avoid computing the bounding rect twice
633 if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
634 boundingRect = path.boundingRect();
637 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect));
640 } else if (changedPen) {
646 engine->drawPath(path);
648 } else if (needsFill) {
649 if (pen.style() != Qt::NoPen) {
650 q->setPen(Qt::NoPen);
655 engine->drawPath(path);
665 void QPainterPrivate::updateMatrix()
667 state->matrix = state->WxF ? state->worldMatrix : QTransform();
669 state->matrix *= viewTransform();
671 txinv = false; // no inverted matrix
672 state->matrix *= state->redirectionMatrix;
674 extended->transformChanged();
676 state->dirtyFlags |= QPaintEngine::DirtyTransform;
678 // printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
679 // qDebug() << " --- using matrix" << state->matrix << redirection_offset;
683 void QPainterPrivate::updateInvMatrix()
685 Q_ASSERT(txinv == false);
686 txinv = true; // creating inverted matrix
687 invMatrix = state->matrix.inverted();
690 void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
693 bool linearGradient = false;
694 bool radialGradient = false;
695 bool conicalGradient = false;
696 bool patternBrush = false;
698 bool complexXform = false;
702 // Pen and brush properties (we have to check both if one changes because the
703 // one that's unchanged can still be in a state which requires emulation)
704 if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) {
705 // Check Brush stroke emulation
706 if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke))
707 s->emulationSpecifier |= QPaintEngine::BrushStroke;
709 s->emulationSpecifier &= ~QPaintEngine::BrushStroke;
713 QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
714 Qt::BrushStyle brushStyle = qbrush_style(s->brush);
715 Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
716 alpha = (penBrushStyle != Qt::NoBrush
717 && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
718 && !penBrush.isOpaque())
719 || (brushStyle != Qt::NoBrush
720 && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
721 && !s->brush.isOpaque());
722 linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
723 (brushStyle == Qt::LinearGradientPattern));
724 radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
725 (brushStyle == Qt::RadialGradientPattern));
726 conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
727 (brushStyle == Qt::ConicalGradientPattern));
728 patternBrush = (((penBrushStyle > Qt::SolidPattern
729 && penBrushStyle < Qt::LinearGradientPattern)
730 || penBrushStyle == Qt::TexturePattern) ||
731 ((brushStyle > Qt::SolidPattern
732 && brushStyle < Qt::LinearGradientPattern)
733 || brushStyle == Qt::TexturePattern));
735 bool penTextureAlpha = false;
736 if (penBrush.style() == Qt::TexturePattern)
737 penTextureAlpha = qHasPixmapTexture(penBrush)
738 ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
739 : penBrush.textureImage().hasAlphaChannel();
740 bool brushTextureAlpha = false;
741 if (s->brush.style() == Qt::TexturePattern) {
742 brushTextureAlpha = qHasPixmapTexture(s->brush)
743 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
744 : s->brush.textureImage().hasAlphaChannel();
746 if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
747 || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
748 && !engine->hasFeature(QPaintEngine::MaskedBrush))
749 s->emulationSpecifier |= QPaintEngine::MaskedBrush;
751 s->emulationSpecifier &= ~QPaintEngine::MaskedBrush;
754 if (s->state() & (QPaintEngine::DirtyHints
755 | QPaintEngine::DirtyOpacity
756 | QPaintEngine::DirtyBackgroundMode)) {
764 qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
766 " - linearGradient: %d\n"
767 " - radialGradient: %d\n"
768 " - conicalGradient: %d\n"
769 " - patternBrush: %d\n"
778 uint(s->renderHints),
783 if (s->state() & QPaintEngine::DirtyTransform) {
784 xform = !s->matrix.isIdentity();
785 complexXform = !s->matrix.isAffine();
786 } else if (s->matrix.type() >= QTransform::TxTranslate) {
788 complexXform = !s->matrix.isAffine();
791 const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone);
792 const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone);
794 const bool patternXform = patternBrush && (xform || brushXform || penXform);
796 // Check alphablending
797 if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend))
798 s->emulationSpecifier |= QPaintEngine::AlphaBlend;
800 s->emulationSpecifier &= ~QPaintEngine::AlphaBlend;
802 // Linear gradient emulation
803 if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill))
804 s->emulationSpecifier |= QPaintEngine::LinearGradientFill;
806 s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
808 // Radial gradient emulation
809 if (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill))
810 s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
812 s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
814 // Conical gradient emulation
815 if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
816 s->emulationSpecifier |= QPaintEngine::ConicalGradientFill;
818 s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill;
821 if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
822 s->emulationSpecifier |= QPaintEngine::PatternBrush;
824 s->emulationSpecifier &= ~QPaintEngine::PatternBrush;
827 if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform))
828 s->emulationSpecifier |= QPaintEngine::PatternTransform;
830 s->emulationSpecifier &= ~QPaintEngine::PatternTransform;
833 if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform))
834 s->emulationSpecifier |= QPaintEngine::PrimitiveTransform;
836 s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform;
838 // Perspective XForms
839 if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform))
840 s->emulationSpecifier |= QPaintEngine::PerspectiveTransform;
842 s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform;
845 if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity))
846 s->emulationSpecifier |= QPaintEngine::ConstantOpacity;
848 s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity;
850 bool gradientStretch = false;
851 bool objectBoundingMode = false;
852 if (linearGradient || conicalGradient || radialGradient) {
853 QGradient::CoordinateMode brushMode = coordinateMode(s->brush);
854 QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush());
856 gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
857 gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
859 objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
860 objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
863 s->emulationSpecifier |= QGradient_StretchToDevice;
865 s->emulationSpecifier &= ~QGradient_StretchToDevice;
867 if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
868 s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients;
870 s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients;
872 // Opaque backgrounds...
873 if (s->bgMode == Qt::OpaqueMode &&
874 (is_pen_transparent(s->pen) || is_brush_transparent(s->brush)))
875 s->emulationSpecifier |= QPaintEngine_OpaqueBackground;
877 s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground;
880 //won't be correct either way because the device can already have
881 // something rendered to it in which case subsequent emulation
882 // on a fully transparent qimage and then blitting the results
883 // won't produce correct results
885 if (state->composition_mode > QPainter::CompositionMode_Xor &&
886 !engine->hasFeature(QPaintEngine::BlendModes))
887 s->emulationSpecifier |= QPaintEngine::BlendModes;
889 s->emulationSpecifier &= ~QPaintEngine::BlendModes;
893 void QPainterPrivate::updateStateImpl(QPainterState *newState)
895 // ### we might have to call QPainter::begin() here...
896 if (!engine->state) {
897 engine->state = newState;
898 engine->setDirty(QPaintEngine::AllDirty);
901 if (engine->state->painter() != newState->painter)
902 // ### this could break with clip regions vs paths.
903 engine->setDirty(QPaintEngine::AllDirty);
905 // Upon restore, revert all changes since last save
906 else if (engine->state != newState)
907 newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
909 // We need to store all changes made so that restore can deal with them
911 newState->changeFlags |= newState->dirtyFlags;
913 updateEmulationSpecifier(newState);
915 // Unset potential dirty background mode
916 newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode
917 | QPaintEngine::DirtyBackground);
919 engine->state = newState;
920 engine->updateState(*newState);
921 engine->clearDirty(QPaintEngine::AllDirty);
925 void QPainterPrivate::updateState(QPainterState *newState)
929 engine->state = newState;
931 } else if (newState->state() || engine->state!=newState) {
932 bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
933 && newState->pen.widthF() == 0;
934 if (setNonCosmeticPen) {
935 // Override the default pen's cosmetic state if the
936 // NonCosmeticDefaultPen render hint is used.
937 QPen oldPen = newState->pen;
938 newState->pen.setWidth(1);
939 newState->pen.setCosmetic(false);
940 newState->dirtyFlags |= QPaintEngine::DirtyPen;
942 updateStateImpl(newState);
944 // Restore the state pen back to its default to preserve visible
946 newState->pen = oldPen;
948 updateStateImpl(newState);
956 \brief The QPainter class performs low-level painting on widgets and
963 QPainter provides highly optimized functions to do most of the
964 drawing GUI programs require. It can draw everything from simple
965 lines to complex shapes like pies and chords. It can also draw
966 aligned text and pixmaps. Normally, it draws in a "natural"
967 coordinate system, but it can also do view and world
968 transformation. QPainter can operate on any object that inherits
969 the QPaintDevice class.
971 The common use of QPainter is inside a widget's paint event:
972 Construct and customize (e.g. set the pen or the brush) the
973 painter. Then draw. Remember to destroy the QPainter object after
974 drawing. For example:
976 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 0
978 The core functionality of QPainter is drawing, but the class also
979 provide several functions that allows you to customize QPainter's
980 settings and its rendering quality, and others that enable
981 clipping. In addition you can control how different shapes are
982 merged together by specifying the painter's composition mode.
984 The isActive() function indicates whether the painter is active. A
985 painter is activated by the begin() function and the constructor
986 that takes a QPaintDevice argument. The end() function, and the
987 destructor, deactivates it.
989 Together with the QPaintDevice and QPaintEngine classes, QPainter
990 form the basis for Qt's paint system. QPainter is the class used
991 to perform drawing operations. QPaintDevice represents a device
992 that can be painted on using a QPainter. QPaintEngine provides the
993 interface that the painter uses to draw onto different types of
994 devices. If the painter is active, device() returns the paint
995 device on which the painter paints, and paintEngine() returns the
996 paint engine that the painter is currently operating on. For more
997 information, see the \l {Paint System}.
999 Sometimes it is desirable to make someone else paint on an unusual
1000 QPaintDevice. QPainter supports a static function to do this,
1003 \warning When the paintdevice is a widget, QPainter can only be
1004 used inside a paintEvent() function or in a function called by
1005 paintEvent(); that is unless the Qt::WA_PaintOutsidePaintEvent
1006 widget attribute is set. On Mac OS X and Windows, you can only
1007 paint in a paintEvent() function regardless of this attribute's
1014 There are several settings that you can customize to make QPainter
1015 draw according to your preferences:
1019 \o font() is the font used for drawing text. If the painter
1020 isActive(), you can retrieve information about the currently set
1021 font, and its metrics, using the fontInfo() and fontMetrics()
1022 functions respectively.
1024 \o brush() defines the color or pattern that is used for filling
1027 \o pen() defines the color or stipple that is used for drawing
1028 lines or boundaries.
1030 \o backgroundMode() defines whether there is a background() or
1031 not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
1033 \o background() only applies when backgroundMode() is \l
1034 Qt::OpaqueMode and pen() is a stipple. In that case, it
1035 describes the color of the background pixels in the stipple.
1037 \o brushOrigin() defines the origin of the tiled brushes, normally
1038 the origin of widget's background.
1040 \o viewport(), window(), worldTransform() make up the painter's coordinate
1041 transformation system. For more information, see the \l
1042 {Coordinate Transformations} section and the \l {Coordinate
1043 System} documentation.
1045 \o hasClipping() tells whether the painter clips at all. (The paint
1046 device clips, too.) If the painter clips, it clips to clipRegion().
1048 \o layoutDirection() defines the layout direction used by the
1049 painter when drawing text.
1051 \o worldMatrixEnabled() tells whether world transformation is enabled.
1053 \o viewTransformEnabled() tells whether view transformation is
1058 Note that some of these settings mirror settings in some paint
1059 devices, e.g. QWidget::font(). The QPainter::begin() function (or
1060 equivalently the QPainter constructor) copies these attributes
1061 from the paint device.
1063 You can at any time save the QPainter's state by calling the
1064 save() function which saves all the available settings on an
1065 internal stack. The restore() function pops them back.
1069 QPainter provides functions to draw most primitives: drawPoint(),
1070 drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1071 drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1072 drawPolygon(), drawConvexPolygon() and drawCubicBezier(). The two
1073 convenience functions, drawRects() and drawLines(), draw the given
1074 number of rectangles or lines in the given array of \l
1075 {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1078 The QPainter class also provides the fillRect() function which
1079 fills the given QRect, with the given QBrush, and the eraseRect()
1080 function that erases the area inside the given rectangle.
1082 All of these functions have both integer and floating point
1087 \o \inlineimage qpainter-basicdrawing.png
1089 \bold {Basic Drawing Example}
1091 The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1092 display basic graphics primitives in a variety of styles using the
1097 If you need to draw a complex shape, especially if you need to do
1098 so repeatedly, consider creating a QPainterPath and drawing it
1104 \bold {Painter Paths example}
1106 The QPainterPath class provides a container for painting
1107 operations, enabling graphical shapes to be constructed and
1110 The \l {painting/painterpaths}{Painter Paths} example shows how
1111 painter paths can be used to build complex shapes for rendering.
1113 \o \inlineimage qpainter-painterpaths.png
1116 QPainter also provides the fillPath() function which fills the
1117 given QPainterPath with the given QBrush, and the strokePath()
1118 function that draws the outline of the given path (i.e. strokes
1121 See also the \l {demos/deform}{Vector Deformation} demo which
1122 shows how to use advanced vector techniques to draw text using a
1123 QPainterPath, the \l {demos/gradients}{Gradients} demo which shows
1124 the different types of gradients that are available in Qt, and the \l
1125 {demos/pathstroke}{Path Stroking} demo which shows Qt's built-in
1126 dash patterns and shows how custom patterns can be used to extend
1127 the range of available patterns.
1131 \o \l {demos/deform}{Vector Deformation}
1132 \o \l {demos/gradients}{Gradients}
1133 \o \l {demos/pathstroke}{Path Stroking}
1135 \o \inlineimage qpainter-vectordeformation.png
1136 \o \inlineimage qpainter-gradients.png
1137 \o \inlineimage qpainter-pathstroking.png
1141 There are functions to draw pixmaps/images, namely drawPixmap(),
1142 drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1143 produce the same result, except that drawPixmap() is faster
1144 on-screen while drawImage() may be faster on a QPrinter or other
1147 Text drawing is done using drawText(). When you need
1148 fine-grained positioning, boundingRect() tells you where a given
1149 drawText() command will draw.
1151 There is a drawPicture() function that draws the contents of an
1152 entire QPicture. The drawPicture() function is the only function
1153 that disregards all the painter's settings as QPicture has its own
1156 \section1 Rendering Quality
1158 To get the optimal rendering result using QPainter, you should use
1159 the platform independent QImage as paint device; i.e. using QImage
1160 will ensure that the result has an identical pixel representation
1163 The QPainter class also provides a means of controlling the
1164 rendering quality through its RenderHint enum and the support for
1165 floating point precision: All the functions for drawing primitives
1166 has a floating point version. These are often used in combination
1167 with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1171 \o \inlineimage qpainter-concentriccircles.png
1173 \bold {Concentric Circles Example}
1175 The \l {painting/concentriccircles}{Concentric Circles} example
1176 shows the improved rendering quality that can be obtained using
1177 floating point precision and anti-aliasing when drawing custom
1180 The application's main window displays several widgets which are
1181 drawn using the various combinations of precision and
1186 The RenderHint enum specifies flags to QPainter that may or may
1187 not be respected by any given engine. \l
1188 {RenderHint}{QPainter::Antialiasing} indicates that the engine
1189 should antialias edges of primitives if possible, \l
1190 {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1191 should antialias text if possible, and the \l
1192 {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1193 engine should use a smooth pixmap transformation algorithm.
1194 \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
1195 indicating that the engine should use fragment programs and offscreen
1196 rendering for antialiasing.
1198 The renderHints() function returns a flag that specifies the
1199 rendering hints that are set for this painter. Use the
1200 setRenderHint() function to set or clear the currently set
1203 \section1 Coordinate Transformations
1205 Normally, the QPainter operates on the device's own coordinate
1206 system (usually pixels), but QPainter has good support for
1207 coordinate transformations.
1211 \o nop \o rotate() \o scale() \o translate()
1213 \o \inlineimage qpainter-clock.png
1214 \o \inlineimage qpainter-rotation.png
1215 \o \inlineimage qpainter-scale.png
1216 \o \inlineimage qpainter-translation.png
1219 The most commonly used transformations are scaling, rotation,
1220 translation and shearing. Use the scale() function to scale the
1221 coordinate system by a given offset, the rotate() function to
1222 rotate it clockwise and translate() to translate it (i.e. adding a
1223 given offset to the points). You can also twist the coordinate
1224 system around the origin using the shear() function. See the \l
1225 {demos/affine}{Affine Transformations} demo for a visualization of
1226 a sheared coordinate system.
1228 See also the \l {painting/transformations}{Transformations}
1229 example which shows how transformations influence the way that
1230 QPainter renders graphics primitives. In particular it shows how
1231 the order of transformations affects the result.
1236 \bold {Affine Transformations Demo}
1238 The \l {demos/affine}{Affine Transformations} demo show Qt's
1239 ability to perform affine transformations on painting
1240 operations. The demo also allows the user to experiment with the
1241 transformation operations and see the results immediately.
1243 \o \inlineimage qpainter-affinetransformations.png
1246 All the tranformation operations operate on the transformation
1247 worldTransform(). A matrix transforms a point in the plane to another
1248 point. For more information about the transformation matrix, see
1249 the \l {Coordinate System} and QTransform documentation.
1251 The setWorldTransform() function can replace or add to the currently
1252 set worldTransform(). The resetTransform() function resets any
1253 transformations that were made using translate(), scale(),
1254 shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1255 functions. The deviceTransform() returns the matrix that transforms
1256 from logical coordinates to device coordinates of the platform
1257 dependent paint device. The latter function is only needed when
1258 using platform painting commands on the platform dependent handle,
1259 and the platform does not do transformations nativly.
1261 When drawing with QPainter, we specify points using logical
1262 coordinates which then are converted into the physical coordinates
1263 of the paint device. The mapping of the logical coordinates to the
1264 physical coordinates are handled by QPainter's combinedTransform(), a
1265 combination of viewport() and window() and worldTransform(). The
1266 viewport() represents the physical coordinates specifying an
1267 arbitrary rectangle, the window() describes the same rectangle in
1268 logical coordinates, and the worldTransform() is identical with the
1269 transformation matrix.
1271 See also \l {Coordinate System}
1275 QPainter can clip any drawing operation to a rectangle, a region,
1276 or a vector path. The current clip is available using the
1277 functions clipRegion() and clipPath(). Whether paths or regions are
1278 preferred (faster) depends on the underlying paintEngine(). For
1279 example, the QImage paint engine prefers paths while the X11 paint
1280 engine prefers regions. Setting a clip is done in the painters
1281 logical coordinates.
1283 After QPainter's clipping, the paint device may also clip. For
1284 example, most widgets clip away the pixels used by child widgets,
1285 and most printers clip away an area near the edges of the paper.
1286 This additional clipping is not reflected by the return value of
1287 clipRegion() or hasClipping().
1289 \section1 Composition Modes
1290 \target Composition Modes
1292 QPainter provides the CompositionMode enum which defines the
1293 Porter-Duff rules for digital image compositing; it describes a
1294 model for combining the pixels in one image, the source, with the
1295 pixels in another image, the destination.
1297 The two most common forms of composition are \l
1298 {QPainter::CompositionMode}{Source} and \l
1299 {QPainter::CompositionMode}{SourceOver}. \l
1300 {QPainter::CompositionMode}{Source} is used to draw opaque objects
1301 onto a paint device. In this mode, each pixel in the source
1302 replaces the corresponding pixel in the destination. In \l
1303 {QPainter::CompositionMode}{SourceOver} composition mode, the
1304 source object is transparent and is drawn on top of the
1307 Note that composition transformation operates pixelwise. For that
1308 reason, there is a difference between using the graphic primitive
1309 itself and its bounding rectangle: The bounding rect contains
1310 pixels with alpha == 0 (i.e the pixels surrounding the
1311 primitive). These pixels will overwrite the other image's pixels,
1312 affectively clearing those, while the primitive only overwrites
1317 \o \inlineimage qpainter-compositiondemo.png
1320 \bold {Composition Modes Demo}
1322 The \l {demos/composition}{Composition Modes} demo, available in
1323 Qt's demo directory, allows you to experiment with the various
1324 composition modes and see the results immediately.
1328 \section1 Limitations
1331 If you are using coordinates with Qt's raster-based paint engine, it is
1332 important to note that, while coordinates greater than +/- 2\sup 15 can
1333 be used, any painting performed with coordinates outside this range is not
1334 guaranteed to be shown; the drawing may be clipped. This is due to the
1335 use of \c{short int} in the implementation.
1337 The outlines generated by Qt's stroker are only an approximation when dealing
1338 with curved shapes. It is in most cases impossible to represent the outline of
1339 a bezier curve segment using another bezier curve segment, and so Qt approximates
1340 the curve outlines by using several smaller curves. For performance reasons there
1341 is a limit to how many curves Qt uses for these outlines, and thus when using
1342 large pen widths or scales the outline error increases. To generate outlines with
1343 smaller errors it is possible to use the QPainterPathStroker class, which has the
1344 setCurveThreshold member function which let's the user specify the error tolerance.
1345 Another workaround is to convert the paths to polygons first and then draw the
1348 \section1 Performance
1350 QPainter is a rich framework that allows developers to do a great
1351 variety of graphical operations, such as gradients, composition
1352 modes and vector graphics. And QPainter can do this across a
1353 variety of different hardware and software stacks. Naturally the
1354 underlying combination of hardware and software has some
1355 implications for performance, and ensuring that every single
1356 operation is fast in combination with all the various combinations
1357 of composition modes, brushes, clipping, transformation, etc, is
1358 close to an impossible task because of the number of
1359 permutations. As a compromise we have selected a subset of the
1360 QPainter API and backends, where performance is guaranteed to be as
1361 good as we can sensibly get it for the given combination of
1362 hardware and software.
1364 The backends we focus on as high-performance engines are:
1368 \o Raster - This backend implements all rendering in pure software
1369 and is always used to render into QImages. For optimal performance
1370 only use the format types QImage::Format_ARGB32_Premultiplied,
1371 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1372 including QImage::Format_ARGB32, has significantly worse
1373 performance. This engine is also used by default on Windows and on
1374 QWS. It can be used as default graphics system on any
1375 OS/hardware/software combination by passing \c {-graphicssystem
1376 raster} on the command line
1378 \o OpenGL 2.0 (ES) - This backend is the primary backend for
1379 hardware accelerated graphics. It can be run on desktop machines
1380 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1381 specification. This includes most graphics chips produced in the
1382 last couple of years. The engine can be enabled by using QPainter
1383 onto a QGLWidget or by passing \c {-graphicssystem opengl} on the
1384 command line when the underlying system supports it.
1386 \o OpenVG - This backend implements the Khronos standard for 2D
1387 and Vector Graphics. It is primarily for embedded devices with
1388 hardware support for OpenVG. The engine can be enabled by
1389 passing \c {-graphicssystem openvg} on the command line when
1390 the underlying system supports it.
1394 These operations are:
1398 \o Simple transformations, meaning translation and scaling, pluss
1399 0, 90, 180, 270 degree rotations.
1401 \o \c drawPixmap() in combination with simple transformations and
1402 opacity with non-smooth transformation mode
1403 (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1405 \o Rectangle fills with solid color, two-color linear gradients
1406 and simple transforms.
1408 \o Rectangular clipping with simple transformations and intersect
1411 \o Composition Modes \c QPainter::CompositionMode_Source and
1412 QPainter::CompositionMode_SourceOver
1414 \o Rounded rectangle filling using solid color and two-color
1415 linear gradients fills.
1417 \o 3x3 patched pixmaps, via qDrawBorderPixmap.
1421 This list gives an indication of which features to safely use in
1422 an application where performance is critical. For certain setups,
1423 other operations may be fast too, but before making extensive use
1424 of them, it is recommended to benchmark and verify them on the
1425 system where the software will run in the end. There are also
1426 cases where expensive operations are ok to use, for instance when
1427 the result is cached in a QPixmap.
1429 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
1430 {Drawing Utility Functions}
1434 \enum QPainter::RenderHint
1436 Renderhints are used to specify flags to QPainter that may or
1437 may not be respected by any given engine.
1439 \value Antialiasing Indicates that the engine should antialias
1440 edges of primitives if possible.
1442 \value TextAntialiasing Indicates that the engine should antialias
1443 text if possible. To forcibly disable antialiasing for text, do not
1444 use this hint. Instead, set QFont::NoAntialias on your font's style
1447 \value SmoothPixmapTransform Indicates that the engine should use
1448 a smooth pixmap transformation algorithm (such as bilinear) rather
1449 than nearest neighbor.
1451 \value HighQualityAntialiasing An OpenGL-specific rendering hint
1452 indicating that the engine should use fragment programs and offscreen
1453 rendering for antialiasing.
1455 \value NonCosmeticDefaultPen The engine should interpret pens with a width
1456 of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
1457 pen with a width of 1.
1459 \sa renderHints(), setRenderHint(), {QPainter#Rendering
1460 Quality}{Rendering Quality}, {Concentric Circles Example}
1465 Constructs a painter.
1470 QPainter::QPainter()
1471 : d_ptr(new QPainterPrivate(this))
1476 \fn QPainter::QPainter(QPaintDevice *device)
1478 Constructs a painter that begins painting the paint \a device
1481 This constructor is convenient for short-lived painters, e.g. in a
1482 QWidget::paintEvent() and should be used only once. The
1483 constructor calls begin() for you and the QPainter destructor
1484 automatically calls end().
1486 Here's an example using begin() and end():
1487 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 1
1489 The same example using this constructor:
1490 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 2
1492 Since the constructor cannot provide feedback when the initialization
1493 of the painter failed you should rather use begin() and end() to paint
1494 on external devices, e.g. printers.
1499 QPainter::QPainter(QPaintDevice *pd)
1503 if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1504 d_ptr.reset(new QPainterPrivate(this));
1511 Destroys the painter.
1513 QPainter::~QPainter()
1515 d_ptr->inDestructor = true;
1519 else if (d_ptr->refcount > 1)
1520 d_ptr->detachPainterPrivate(this);
1522 // don't throw anything in the destructor.
1525 // Make sure we haven't messed things up.
1526 Q_ASSERT(d_ptr->inDestructor);
1527 d_ptr->inDestructor = false;
1528 Q_ASSERT(d_ptr->refcount == 1);
1530 free(d_ptr->d_ptrs);
1535 Returns the paint device on which this painter is currently
1536 painting, or 0 if the painter is not active.
1541 QPaintDevice *QPainter::device() const
1543 Q_D(const QPainter);
1544 if (isActive() && d->engine->d_func()->currentClipWidget)
1545 return d->engine->d_func()->currentClipWidget;
1546 return d->original_device;
1550 Returns true if begin() has been called and end() has not yet been
1551 called; otherwise returns false.
1553 \sa begin(), QPaintDevice::paintingActive()
1556 bool QPainter::isActive() const
1558 Q_D(const QPainter);
1563 Initializes the painters pen, background and font to the same as
1564 the given \a widget. This function is called automatically when the
1565 painter is opened on a QWidget.
1567 \sa begin(), {QPainter#Settings}{Settings}
1569 void QPainter::initFrom(const QWidget *widget)
1571 Q_ASSERT_X(widget, "QPainter::initFrom(const QWidget *widget)", "Widget cannot be 0");
1574 qWarning("QPainter::initFrom: Painter not active, aborted");
1578 const QPalette &pal = widget->palette();
1579 d->state->pen = QPen(pal.brush(widget->foregroundRole()), 0);
1580 d->state->bgBrush = pal.brush(widget->backgroundRole());
1581 d->state->deviceFont = QFont(widget->font(), const_cast<QWidget*> (widget));
1582 d->state->font = d->state->deviceFont;
1584 d->extended->penChanged();
1585 } else if (d->engine) {
1586 d->engine->setDirty(QPaintEngine::DirtyPen);
1587 d->engine->setDirty(QPaintEngine::DirtyBrush);
1588 d->engine->setDirty(QPaintEngine::DirtyFont);
1594 Saves the current painter state (pushes the state onto a stack). A
1595 save() must be followed by a corresponding restore(); the end()
1596 function unwinds the stack.
1601 void QPainter::save()
1603 #ifdef QT_DEBUG_DRAW
1604 if (qt_show_painter_debug_output)
1605 printf("QPainter::save()\n");
1609 qWarning("QPainter::save: Painter not active");
1614 d->state = d->extended->createState(d->states.back());
1615 d->extended->setState(d->state);
1617 d->updateState(d->state);
1618 d->state = new QPainterState(d->states.back());
1619 d->engine->state = d->state;
1621 d->states.push_back(d->state);
1625 Restores the current painter state (pops a saved state off the
1631 void QPainter::restore()
1633 #ifdef QT_DEBUG_DRAW
1634 if (qt_show_painter_debug_output)
1635 printf("QPainter::restore()\n");
1638 if (d->states.size()<=1) {
1639 qWarning("QPainter::restore: Unbalanced save/restore");
1641 } else if (!d->engine) {
1642 qWarning("QPainter::restore: Painter not active");
1646 QPainterState *tmp = d->state;
1647 d->states.pop_back();
1648 d->state = d->states.back();
1652 d->checkEmulation();
1653 d->extended->setState(d->state);
1658 // trigger clip update if the clip path/region has changed since
1660 if (!d->state->clipInfo.isEmpty()
1661 && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1662 // reuse the tmp state to avoid any extra allocs...
1663 tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1664 tmp->clipOperation = Qt::NoClip;
1665 tmp->clipPath = QPainterPath();
1666 d->engine->updateState(*tmp);
1667 // replay the list of clip states,
1668 for (int i=0; i<d->state->clipInfo.size(); ++i) {
1669 const QPainterClipInfo &info = d->state->clipInfo.at(i);
1670 tmp->matrix = info.matrix;
1671 tmp->matrix *= d->state->redirectionMatrix;
1672 tmp->clipOperation = info.operation;
1673 if (info.clipType == QPainterClipInfo::RectClip) {
1674 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1675 tmp->clipRegion = info.rect;
1676 } else if (info.clipType == QPainterClipInfo::RegionClip) {
1677 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1678 tmp->clipRegion = info.region;
1679 } else { // clipType == QPainterClipInfo::PathClip
1680 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1681 tmp->clipPath = info.path;
1683 d->engine->updateState(*tmp);
1687 //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1688 d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1689 tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1690 tmp->changeFlags |= QPaintEngine::DirtyTransform;
1693 d->updateState(d->state);
1700 \fn bool QPainter::begin(QPaintDevice *device)
1702 Begins painting the paint \a device and returns true if
1703 successful; otherwise returns false.
1705 Notice that all painter settings (setPen(), setBrush() etc.) are reset
1706 to default values when begin() is called.
1708 The errors that can occur are serious problems, such as these:
1710 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 3
1712 Note that most of the time, you can use one of the constructors
1713 instead of begin(), and that end() is automatically done at
1716 \warning A paint device can only be painted by one painter at a
1719 \warning Painting on a QImage with the format
1720 QImage::Format_Indexed8 is not supported.
1722 \sa end(), QPainter()
1725 static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1734 bool QPainter::begin(QPaintDevice *pd)
1738 if (pd->painters > 0) {
1739 qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1743 if (d_ptr->engine) {
1744 qWarning("QPainter::begin: Painter already active");
1748 if (QPainterPrivate::attachPainterPrivate(this, pd))
1753 d->helper_device = pd;
1754 d->original_device = pd;
1755 QPaintDevice *rpd = 0;
1757 QPoint redirectionOffset;
1758 // We know for sure that redirection is broken when the widget is inside
1759 // its paint event, so it's safe to use our hard-coded redirection. However,
1760 // there IS one particular case we still need to support, and that's
1761 // when people call QPainter::setRedirected in the widget's paint event right
1762 // before any painter is created (or QPainter::begin is called). In that
1763 // particular case our hard-coded redirection is restored and the redirection
1764 // is retrieved from QPainter::redirected (as before).
1765 if (pd->devType() == QInternal::Widget)
1766 rpd = static_cast<QWidget *>(pd)->d_func()->redirected(&redirectionOffset);
1769 rpd = redirected(pd, &redirectionOffset);
1774 #ifdef QT_DEBUG_DRAW
1775 if (qt_show_painter_debug_output)
1776 printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1779 if (pd->devType() == QInternal::Pixmap)
1780 static_cast<QPixmap *>(pd)->detach();
1781 else if (pd->devType() == QInternal::Image)
1782 static_cast<QImage *>(pd)->detach();
1784 d->engine = pd->paintEngine();
1787 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1793 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1794 if (d->emulationEngine)
1795 d->emulationEngine->real_engine = d->extended;
1797 // Setup new state...
1798 Q_ASSERT(!d->state);
1799 d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1800 d->state->painter = this;
1801 d->states.push_back(d->state);
1803 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1804 d->state->brushOrigin = QPointF();
1806 // Slip a painter state into the engine before we do any other operations
1808 d->extended->setState(d->state);
1810 d->engine->state = d->state;
1812 switch (pd->devType()) {
1813 case QInternal::Widget:
1815 const QWidget *widget = static_cast<const QWidget *>(pd);
1818 const bool paintOutsidePaintEvent = widget->testAttribute(Qt::WA_PaintOutsidePaintEvent);
1819 const bool inPaintEvent = widget->testAttribute(Qt::WA_WState_InPaintEvent);
1820 if(!d->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent)
1821 && !paintOutsidePaintEvent && !inPaintEvent) {
1822 qWarning("QPainter::begin: Widget painting can only begin as a "
1823 "result of a paintEvent");
1824 qt_cleanup_painter_state(d);
1828 // Adjust offset for alien widgets painting outside the paint event.
1829 if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
1830 && widget->testAttribute(Qt::WA_WState_Created)) {
1831 const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
1832 d->state->redirectionMatrix.translate(offset.x(), offset.y());
1836 case QInternal::Pixmap:
1838 QPixmap *pm = static_cast<QPixmap *>(pd);
1841 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1842 qt_cleanup_painter_state(d);
1846 if (pm->depth() == 1) {
1847 d->state->pen = QPen(Qt::color1);
1848 d->state->brush = QBrush(Qt::color0);
1852 case QInternal::Image:
1854 QImage *img = static_cast<QImage *>(pd);
1856 if (img->isNull()) {
1857 qWarning("QPainter::begin: Cannot paint on a null image");
1858 qt_cleanup_painter_state(d);
1860 } else if (img->format() == QImage::Format_Indexed8) {
1861 // Painting on indexed8 images is not supported.
1862 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1863 qt_cleanup_painter_state(d);
1866 if (img->depth() == 1) {
1867 d->state->pen = QPen(Qt::color1);
1868 d->state->brush = QBrush(Qt::color0);
1875 if (d->state->ww == 0) // For compat with 3.x painter defaults
1876 d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1878 d->engine->setPaintDevice(pd);
1880 bool begun = d->engine->begin(pd);
1882 qWarning("QPainter::begin(): Returned false");
1883 if (d->engine->isActive()) {
1886 qt_cleanup_painter_state(d);
1890 d->engine->setActive(begun);
1893 // Copy painter properties from original paint device,
1894 // required for QPixmap::grabWidget()
1895 if (d->original_device->devType() == QInternal::Widget) {
1896 QWidget *widget = static_cast<QWidget *>(d->original_device);
1899 d->state->layoutDirection = Qt::LayoutDirectionAuto;
1900 // make sure we have a font compatible with the paintdevice
1901 d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1904 QRect systemRect = d->engine->systemRect();
1905 if (!systemRect.isEmpty()) {
1906 d->state->ww = d->state->vw = systemRect.width();
1907 d->state->wh = d->state->vh = systemRect.height();
1909 d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1910 d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1913 const QPoint coordinateOffset = d->engine->coordinateOffset();
1914 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1916 Q_ASSERT(d->engine->isActive());
1918 if (!d->state->redirectionMatrix.isIdentity())
1921 Q_ASSERT(d->engine->isActive());
1922 d->state->renderHints = QPainter::TextAntialiasing;
1923 ++d->device->painters;
1925 d->state->emulationSpecifier = 0;
1931 Ends painting. Any resources used while painting are released. You
1932 don't normally need to call this since it is called by the
1935 Returns true if the painter is no longer active; otherwise returns false.
1937 \sa begin(), isActive()
1940 bool QPainter::end()
1942 #ifdef QT_DEBUG_DRAW
1943 if (qt_show_painter_debug_output)
1944 printf("QPainter::end()\n");
1949 qWarning("QPainter::end: Painter not active, aborted");
1950 qt_cleanup_painter_state(d);
1954 if (d->refcount > 1) {
1955 d->detachPainterPrivate(this);
1961 if (d->engine->isActive()) {
1962 ended = d->engine->end();
1965 --d->device->painters;
1966 if (d->device->painters == 0) {
1967 d->engine->setPaintDevice(0);
1968 d->engine->setActive(false);
1972 if (d->states.size() > 1) {
1973 qWarning("QPainter::end: Painter ended with %d saved states",
1977 if (d->engine->autoDestruct()) {
1981 if (d->emulationEngine) {
1982 delete d->emulationEngine;
1983 d->emulationEngine = 0;
1990 qt_cleanup_painter_state(d);
1997 Returns the paint engine that the painter is currently operating
1998 on if the painter is active; otherwise 0.
2002 QPaintEngine *QPainter::paintEngine() const
2004 Q_D(const QPainter);
2011 Flushes the painting pipeline and prepares for the user issuing commands
2012 directly to the underlying graphics context. Must be followed by a call to
2013 endNativePainting().
2015 Note that only the states the underlying paint engine changes will be reset
2016 to their respective default states. The states we reset may change from
2017 release to release. The following states are currently reset in the OpenGL
2021 \i blending is disabled
2022 \i the depth, stencil and scissor tests are disabled
2023 \i the active texture unit is reset to 0
2024 \i the depth mask, depth function and the clear depth are reset to their
2026 \i the stencil mask, stencil operation and stencil function are reset to
2027 their default values
2028 \i the current color is reset to solid white
2031 If, for example, the OpenGL polygon mode is changed by the user inside a
2032 beginNativePaint()/endNativePainting() block, it will not be reset to the
2033 default state by endNativePainting(). Here is an example that shows
2034 intermixing of painter commands and raw OpenGL commands:
2036 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
2038 \sa endNativePainting()
2040 void QPainter::beginNativePainting()
2044 qWarning("QPainter::beginNativePainting: Painter not active");
2049 d->extended->beginNativePainting();
2055 Restores the painter after manually issuing native painting commands. Lets
2056 the painter restore any native state that it relies on before calling any
2057 other painter commands.
2059 \sa beginNativePainting()
2061 void QPainter::endNativePainting()
2063 Q_D(const QPainter);
2065 qWarning("QPainter::beginNativePainting: Painter not active");
2070 d->extended->endNativePainting();
2072 d->engine->syncState();
2076 Returns the font metrics for the painter if the painter is
2077 active. Otherwise, the return value is undefined.
2079 \sa font(), isActive(), {QPainter#Settings}{Settings}
2082 QFontMetrics QPainter::fontMetrics() const
2084 Q_D(const QPainter);
2086 qWarning("QPainter::fontMetrics: Painter not active");
2087 return QFontMetrics(QFont());
2089 return QFontMetrics(d->state->font);
2094 Returns the font info for the painter if the painter is
2095 active. Otherwise, the return value is undefined.
2097 \sa font(), isActive(), {QPainter#Settings}{Settings}
2100 QFontInfo QPainter::fontInfo() const
2102 Q_D(const QPainter);
2104 qWarning("QPainter::fontInfo: Painter not active");
2105 return QFontInfo(QFont());
2107 return QFontInfo(d->state->font);
2113 Returns the opacity of the painter. The default value is
2117 qreal QPainter::opacity() const
2119 Q_D(const QPainter);
2121 qWarning("QPainter::opacity: Painter not active");
2124 return d->state->opacity;
2130 Sets the opacity of the painter to \a opacity. The value should
2131 be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2132 1.0 is fully opaque.
2134 Opacity set on the painter will apply to all drawing operations
2138 void QPainter::setOpacity(qreal opacity)
2143 qWarning("QPainter::setOpacity: Painter not active");
2147 opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2149 if (opacity == d->state->opacity)
2152 d->state->opacity = opacity;
2155 d->extended->opacityChanged();
2157 d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2162 Returns the currently set brush origin.
2164 \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2167 QPoint QPainter::brushOrigin() const
2169 Q_D(const QPainter);
2171 qWarning("QPainter::brushOrigin: Painter not active");
2174 return QPointF(d->state->brushOrigin).toPoint();
2178 \fn void QPainter::setBrushOrigin(const QPointF &position)
2180 Sets the brush origin to \a position.
2182 The brush origin specifies the (0, 0) coordinate of the painter's
2185 Note that while the brushOrigin() was necessary to adopt the
2186 parent's background for a widget in Qt 3, this is no longer the
2187 case since the Qt 4 painter doesn't paint the background unless
2188 you explicitly tell it to do so by setting the widget's \l
2189 {QWidget::autoFillBackground}{autoFillBackground} property to
2192 \sa brushOrigin(), {QPainter#Settings}{Settings}
2195 void QPainter::setBrushOrigin(const QPointF &p)
2198 #ifdef QT_DEBUG_DRAW
2199 if (qt_show_painter_debug_output)
2200 printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2204 qWarning("QPainter::setBrushOrigin: Painter not active");
2208 d->state->brushOrigin = p;
2211 d->extended->brushOriginChanged();
2215 d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2219 \fn void QPainter::setBrushOrigin(const QPoint &position)
2222 Sets the brush's origin to the given \a position.
2226 \fn void QPainter::setBrushOrigin(int x, int y)
2230 Sets the brush's origin to point (\a x, \a y).
2234 \enum QPainter::CompositionMode
2236 Defines the modes supported for digital image compositing.
2237 Composition modes are used to specify how the pixels in one image,
2238 the source, are merged with the pixel in another image, the
2241 Please note that the bitwise raster operation modes, denoted with
2242 a RasterOp prefix, are only natively supported in the X11 and
2243 raster paint engines. This means that the only way to utilize
2244 these modes on the Mac is via a QImage. The RasterOp denoted blend
2245 modes are \e not supported for pens and brushes with alpha
2246 components. Also, turning on the QPainter::Antialiasing render
2247 hint will effectively disable the RasterOp modes.
2250 \image qpainter-compositionmode1.png
2251 \image qpainter-compositionmode2.png
2253 The most common type is SourceOver (often referred to as just
2254 alpha blending) where the source pixel is blended on top of the
2255 destination pixel in such a way that the alpha component of the
2256 source defines the translucency of the pixel.
2258 When the paint device is a QImage, the image format must be set to
2259 \l {QImage::Format}{Format_ARGB32Premultiplied} or
2260 \l {QImage::Format}{Format_ARGB32} for the composition modes to have
2261 any effect. For performance the premultiplied version is the preferred
2264 When a composition mode is set it applies to all painting
2265 operator, pens, brushes, gradients and pixmap/image drawing.
2267 \value CompositionMode_SourceOver This is the default mode. The
2268 alpha of the source is used to blend the pixel on top of the
2271 \value CompositionMode_DestinationOver The alpha of the
2272 destination is used to blend it on top of the source pixels. This
2273 mode is the inverse of CompositionMode_SourceOver.
2275 \value CompositionMode_Clear The pixels in the destination are
2276 cleared (set to fully transparent) independent of the source.
2278 \value CompositionMode_Source The output is the source
2279 pixel. (This means a basic copy operation and is identical to
2280 SourceOver when the source pixel is opaque).
2282 \value CompositionMode_Destination The output is the destination
2283 pixel. This means that the blending has no effect. This mode is
2284 the inverse of CompositionMode_Source.
2286 \value CompositionMode_SourceIn The output is the source, where
2287 the alpha is reduced by that of the destination.
2289 \value CompositionMode_DestinationIn The output is the
2290 destination, where the alpha is reduced by that of the
2291 source. This mode is the inverse of CompositionMode_SourceIn.
2293 \value CompositionMode_SourceOut The output is the source, where
2294 the alpha is reduced by the inverse of destination.
2296 \value CompositionMode_DestinationOut The output is the
2297 destination, where the alpha is reduced by the inverse of the
2298 source. This mode is the inverse of CompositionMode_SourceOut.
2300 \value CompositionMode_SourceAtop The source pixel is blended on
2301 top of the destination, with the alpha of the source pixel reduced
2302 by the alpha of the destination pixel.
2304 \value CompositionMode_DestinationAtop The destination pixel is
2305 blended on top of the source, with the alpha of the destination
2306 pixel is reduced by the alpha of the destination pixel. This mode
2307 is the inverse of CompositionMode_SourceAtop.
2309 \value CompositionMode_Xor The source, whose alpha is reduced with
2310 the inverse of the destination alpha, is merged with the
2311 destination, whose alpha is reduced by the inverse of the source
2312 alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2314 \value CompositionMode_Plus Both the alpha and color of the source
2315 and destination pixels are added together.
2317 \value CompositionMode_Multiply The output is the source color
2318 multiplied by the destination. Multiplying a color with white
2319 leaves the color unchanged, while multiplying a color
2320 with black produces black.
2322 \value CompositionMode_Screen The source and destination colors
2323 are inverted and then multiplied. Screening a color with white
2324 produces white, whereas screening a color with black leaves the
2327 \value CompositionMode_Overlay Multiplies or screens the colors
2328 depending on the destination color. The destination color is mixed
2329 with the source color to reflect the lightness or darkness of the
2332 \value CompositionMode_Darken The darker of the source and
2333 destination colors is selected.
2335 \value CompositionMode_Lighten The lighter of the source and
2336 destination colors is selected.
2338 \value CompositionMode_ColorDodge The destination color is
2339 brightened to reflect the source color. A black source color
2340 leaves the destination color unchanged.
2342 \value CompositionMode_ColorBurn The destination color is darkened
2343 to reflect the source color. A white source color leaves the
2344 destination color unchanged.
2346 \value CompositionMode_HardLight Multiplies or screens the colors
2347 depending on the source color. A light source color will lighten
2348 the destination color, whereas a dark source color will darken the
2351 \value CompositionMode_SoftLight Darkens or lightens the colors
2352 depending on the source color. Similar to
2353 CompositionMode_HardLight.
2355 \value CompositionMode_Difference Subtracts the darker of the
2356 colors from the lighter. Painting with white inverts the
2357 destination color, whereas painting with black leaves the
2358 destination color unchanged.
2360 \value CompositionMode_Exclusion Similar to
2361 CompositionMode_Difference, but with a lower contrast. Painting
2362 with white inverts the destination color, whereas painting with
2363 black leaves the destination color unchanged.
2365 \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2366 the source and destination pixels (src OR dst).
2368 \value RasterOp_SourceAndDestination Does a bitwise AND operation
2369 on the source and destination pixels (src AND dst).
2371 \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2372 on the source and destination pixels (src XOR dst).
2374 \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2375 operation on the source and destination pixels ((NOT src) AND (NOT
2378 \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2379 operation on the source and destination pixels ((NOT src) OR (NOT
2382 \value RasterOp_NotSourceXorDestination Does a bitwise operation
2383 where the source pixels are inverted and then XOR'ed with the
2384 destination ((NOT src) XOR dst).
2386 \value RasterOp_NotSource Does a bitwise operation where the
2387 source pixels are inverted (NOT src).
2389 \value RasterOp_NotSourceAndDestination Does a bitwise operation
2390 where the source is inverted and then AND'ed with the destination
2391 ((NOT src) AND dst).
2393 \value RasterOp_SourceAndNotDestination Does a bitwise operation
2394 where the source is AND'ed with the inverted destination pixels
2395 (src AND (NOT dst)).
2397 \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2398 Modes}{Composition Modes}, {Image Composition Example}
2402 Sets the composition mode to the given \a mode.
2404 \warning Only a QPainter operating on a QImage fully supports all
2405 composition modes. The RasterOp modes are supported for X11 as
2406 described in compositionMode().
2408 \sa compositionMode()
2410 void QPainter::setCompositionMode(CompositionMode mode)
2414 qWarning("QPainter::setCompositionMode: Painter not active");
2417 if (d->state->composition_mode == mode)
2420 d->state->composition_mode = mode;
2421 d->extended->compositionModeChanged();
2425 if (mode >= QPainter::RasterOp_SourceOrDestination) {
2426 if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2427 qWarning("QPainter::setCompositionMode: "
2428 "Raster operation modes not supported on device");
2431 } else if (mode >= QPainter::CompositionMode_Plus) {
2432 if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2433 qWarning("QPainter::setCompositionMode: "
2434 "Blend modes not supported on device");
2437 } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2438 if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2439 qWarning("QPainter::setCompositionMode: "
2440 "PorterDuff modes not supported on device");
2445 d->state->composition_mode = mode;
2446 d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2450 Returns the current composition mode.
2452 \sa CompositionMode, setCompositionMode()
2454 QPainter::CompositionMode QPainter::compositionMode() const
2456 Q_D(const QPainter);
2458 qWarning("QPainter::compositionMode: Painter not active");
2459 return QPainter::CompositionMode_SourceOver;
2461 return d->state->composition_mode;
2465 Returns the current background brush.
2467 \sa setBackground(), {QPainter#Settings}{Settings}
2470 const QBrush &QPainter::background() const
2472 Q_D(const QPainter);
2474 qWarning("QPainter::background: Painter not active");
2475 return d->fakeState()->brush;
2477 return d->state->bgBrush;
2482 Returns true if clipping has been set; otherwise returns false.
2484 \sa setClipping(), {QPainter#Clipping}{Clipping}
2487 bool QPainter::hasClipping() const
2489 Q_D(const QPainter);
2491 qWarning("QPainter::hasClipping: Painter not active");
2494 return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2499 Enables clipping if \a enable is true, or disables clipping if \a
2502 \sa hasClipping(), {QPainter#Clipping}{Clipping}
2505 void QPainter::setClipping(bool enable)
2508 #ifdef QT_DEBUG_DRAW
2509 if (qt_show_painter_debug_output)
2510 printf("QPainter::setClipping(), enable=%s, was=%s\n",
2511 enable ? "on" : "off",
2512 hasClipping() ? "on" : "off");
2515 qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2519 if (hasClipping() == enable)
2522 // we can't enable clipping if we don't have a clip
2524 && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2526 d->state->clipEnabled = enable;
2529 d->extended->clipEnabledChanged();
2533 d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2534 d->updateState(d->state);
2539 Returns the currently set clip region. Note that the clip region
2540 is given in logical coordinates.
2542 \warning QPainter does not store the combined clip explicitly as
2543 this is handled by the underlying QPaintEngine, so the path is
2544 recreated on demand and transformed to the current logical
2545 coordinate system. This is potentially an expensive operation.
2547 \sa setClipRegion(), clipPath(), setClipping()
2550 QRegion QPainter::clipRegion() const
2552 Q_D(const QPainter);
2554 qWarning("QPainter::clipRegion: Painter not active");
2559 bool lastWasNothing = true;
2562 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2564 // ### Falcon: Use QPainterPath
2565 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2566 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2567 switch (info.clipType) {
2569 case QPainterClipInfo::RegionClip: {
2570 QTransform matrix = (info.matrix * d->invMatrix);
2571 if (lastWasNothing) {
2572 region = info.region * matrix;
2573 lastWasNothing = false;
2576 if (info.operation == Qt::IntersectClip)
2577 region &= info.region * matrix;
2578 else if (info.operation == Qt::UniteClip)
2579 region |= info.region * matrix;
2580 else if (info.operation == Qt::NoClip) {
2581 lastWasNothing = true;
2584 region = info.region * matrix;
2588 case QPainterClipInfo::PathClip: {
2589 QTransform matrix = (info.matrix * d->invMatrix);
2590 if (lastWasNothing) {
2591 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2592 info.path.fillRule());
2593 lastWasNothing = false;
2596 if (info.operation == Qt::IntersectClip) {
2597 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2598 info.path.fillRule());
2599 } else if (info.operation == Qt::UniteClip) {
2600 region |= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2601 info.path.fillRule());
2602 } else if (info.operation == Qt::NoClip) {
2603 lastWasNothing = true;
2606 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2607 info.path.fillRule());
2612 case QPainterClipInfo::RectClip: {
2613 QTransform matrix = (info.matrix * d->invMatrix);
2614 if (lastWasNothing) {
2615 region = QRegion(info.rect) * matrix;
2616 lastWasNothing = false;
2619 if (info.operation == Qt::IntersectClip) {
2620 // Use rect intersection if possible.
2621 if (matrix.type() <= QTransform::TxScale)
2622 region &= matrix.mapRect(info.rect);
2624 region &= matrix.map(QRegion(info.rect));
2625 } else if (info.operation == Qt::UniteClip) {
2626 region |= QRegion(info.rect) * matrix;
2627 } else if (info.operation == Qt::NoClip) {
2628 lastWasNothing = true;
2631 region = QRegion(info.rect) * matrix;
2636 case QPainterClipInfo::RectFClip: {
2637 QTransform matrix = (info.matrix * d->invMatrix);
2638 if (lastWasNothing) {
2639 region = QRegion(info.rectf.toRect()) * matrix;
2640 lastWasNothing = false;
2643 if (info.operation == Qt::IntersectClip) {
2644 // Use rect intersection if possible.
2645 if (matrix.type() <= QTransform::TxScale)
2646 region &= matrix.mapRect(info.rectf.toRect());
2648 region &= matrix.map(QRegion(info.rectf.toRect()));
2649 } else if (info.operation == Qt::UniteClip) {
2650 region |= QRegion(info.rectf.toRect()) * matrix;
2651 } else if (info.operation == Qt::NoClip) {
2652 lastWasNothing = true;
2655 region = QRegion(info.rectf.toRect()) * matrix;
2665 extern QPainterPath qt_regionToPath(const QRegion ®ion);
2668 Returns the currently clip as a path. Note that the clip path is
2669 given in logical coordinates.
2671 \warning QPainter does not store the combined clip explicitly as
2672 this is handled by the underlying QPaintEngine, so the path is
2673 recreated on demand and transformed to the current logical
2674 coordinate system. This is potentially an expensive operation.
2676 \sa setClipPath(), clipRegion(), setClipping()
2678 QPainterPath QPainter::clipPath() const
2680 Q_D(const QPainter);
2682 // ### Since we do not support path intersections and path unions yet,
2683 // we just use clipRegion() here...
2685 qWarning("QPainter::clipPath: Painter not active");
2686 return QPainterPath();
2689 // No clip, return empty
2690 if (d->state->clipInfo.size() == 0) {
2691 return QPainterPath();
2694 // Update inverse matrix, used below.
2696 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2698 // For the simple case avoid conversion.
2699 if (d->state->clipInfo.size() == 1
2700 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2701 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2702 return d->state->clipInfo.at(0).path * matrix;
2704 } else if (d->state->clipInfo.size() == 1
2705 && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2706 QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2708 path.addRect(d->state->clipInfo.at(0).rect);
2709 return path * matrix;
2711 // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2712 return qt_regionToPath(clipRegion());
2718 Returns the bounding rectangle of the current clip if there is a clip;
2719 otherwise returns an empty rectangle. Note that the clip region is
2720 given in logical coordinates.
2722 The bounding rectangle is not guaranteed to be tight.
2724 \sa setClipRect(), setClipPath(), setClipRegion()
2729 QRectF QPainter::clipBoundingRect() const
2731 Q_D(const QPainter);
2734 qWarning("QPainter::clipBoundingRect: Painter not active");
2738 // Accumulate the bounding box in device space. This is not 100%
2739 // precise, but it fits within the guarantee and it is resonably
2742 for (int i=0; i<d->state->clipInfo.size(); ++i) {
2744 const QPainterClipInfo &info = d->state->clipInfo.at(i);
2746 if (info.clipType == QPainterClipInfo::RectClip)
2748 else if (info.clipType == QPainterClipInfo::RectFClip)
2750 else if (info.clipType == QPainterClipInfo::RegionClip)
2751 r = info.region.boundingRect();
2753 r = info.path.boundingRect();
2755 r = info.matrix.mapRect(r);
2759 else if (info.operation == Qt::IntersectClip)
2761 else if (info.operation == Qt::UniteClip)
2766 // Map the rectangle back into logical space using the inverse
2769 const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2771 return d->invMatrix.mapRect(bounds);
2775 \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2777 Enables clipping, and sets the clip region to the given \a
2778 rectangle using the given clip \a operation. The default operation
2779 is to replace the current clip rectangle.
2781 Note that the clip rectangle is specified in logical (painter)
2784 \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2786 void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2791 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2792 op = Qt::ReplaceClip;
2795 qWarning("QPainter::setClipRect: Painter not active");
2798 qreal right = rect.x() + rect.width();
2799 qreal bottom = rect.y() + rect.height();
2800 qreal pts[] = { rect.x(), rect.y(),
2804 QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2805 d->state->clipEnabled = true;
2806 d->extended->clip(vp, op);
2807 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2808 d->state->clipInfo.clear();
2809 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2810 d->state->clipOperation = op;
2814 if (qreal(int(rect.top())) == rect.top()
2815 && qreal(int(rect.bottom())) == rect.bottom()
2816 && qreal(int(rect.left())) == rect.left()
2817 && qreal(int(rect.right())) == rect.right())
2819 setClipRect(rect.toRect(), op);
2823 if (rect.isEmpty()) {
2824 setClipRegion(QRegion(), op);
2830 setClipPath(path, op);
2834 \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2837 Enables clipping, and sets the clip region to the given \a rectangle using the given
2840 void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2845 qWarning("QPainter::setClipRect: Painter not active");
2849 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2850 op = Qt::ReplaceClip;
2853 d->state->clipEnabled = true;
2854 d->extended->clip(rect, op);
2855 if (op == Qt::ReplaceClip || op == Qt::NoClip)
2856 d->state->clipInfo.clear();
2857 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2858 d->state->clipOperation = op;
2862 d->state->clipRegion = rect;
2863 d->state->clipOperation = op;
2864 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2865 d->state->clipInfo.clear();
2866 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2867 d->state->clipEnabled = true;
2868 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2869 d->updateState(d->state);
2873 \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2875 Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2876 with the given \a width and \a height.
2880 \fn void QPainter::setClipRegion(const QRegion ®ion, Qt::ClipOperation operation)
2882 Sets the clip region to the given \a region using the specified clip
2883 \a operation. The default clip operation is to replace the current
2886 Note that the clip region is given in logical coordinates.
2888 \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2890 void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2893 #ifdef QT_DEBUG_DRAW
2894 QRect rect = r.boundingRect();
2895 if (qt_show_painter_debug_output)
2896 printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2897 r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2900 qWarning("QPainter::setClipRegion: Painter not active");
2904 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
2905 op = Qt::ReplaceClip;
2908 d->state->clipEnabled = true;
2909 d->extended->clip(r, op);
2910 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2911 d->state->clipInfo.clear();
2912 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2913 d->state->clipOperation = op;
2917 d->state->clipRegion = r;
2918 d->state->clipOperation = op;
2919 if (op == Qt::NoClip || op == Qt::ReplaceClip)
2920 d->state->clipInfo.clear();
2921 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2922 d->state->clipEnabled = true;
2923 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2924 d->updateState(d->state);
2931 Sets the transformation matrix to \a matrix and enables transformations.
2933 \note It is advisable to use setWorldTransform() instead of this function to
2934 preserve the properties of perspective transformations.
2936 If \a combine is true, then \a matrix is combined with the current
2937 transformation matrix; otherwise \a matrix replaces the current
2938 transformation matrix.
2940 If \a matrix is the identity matrix and \a combine is false, this
2941 function calls setWorldMatrixEnabled(false). (The identity matrix is the
2942 matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2945 The following functions can transform the coordinate system without using
2954 They operate on the painter's worldMatrix() and are implemented like this:
2956 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 4
2958 Note that when using setWorldMatrix() function you should always have
2959 \a combine be true when you are drawing into a QPicture. Otherwise
2960 it may not be possible to replay the picture with additional
2961 transformations; using the translate(), scale(), etc. convenience
2964 For more information about the coordinate system, transformations
2965 and window-viewport conversion, see \l {Coordinate System}.
2967 \sa setWorldTransform(), QTransform
2970 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2972 setWorldTransform(QTransform(matrix), combine);
2979 Returns the world transformation matrix.
2981 It is advisable to use worldTransform() because worldMatrix() does not
2982 preserve the properties of perspective transformations.
2984 \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2988 const QMatrix &QPainter::worldMatrix() const
2990 Q_D(const QPainter);
2992 qWarning("QPainter::worldMatrix: Painter not active");
2993 return d->fakeState()->transform.toAffine();
2995 return d->state->worldMatrix.toAffine();
3001 Use setWorldTransform() instead.
3003 \sa setWorldTransform()
3006 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
3008 setWorldTransform(QTransform(matrix), combine);
3014 Use worldTransform() instead.
3016 \sa worldTransform()
3019 const QMatrix &QPainter::matrix() const
3021 return worldMatrix();
3029 Returns the transformation matrix combining the current
3030 window/viewport and world transformation.
3032 It is advisable to use combinedTransform() instead of this
3033 function to preserve the properties of perspective transformations.
3035 \sa setWorldTransform(), setWindow(), setViewport()
3037 QMatrix QPainter::combinedMatrix() const
3039 return combinedTransform().toAffine();
3046 Returns the matrix that transforms from logical coordinates to
3047 device coordinates of the platform dependent paint device.
3049 \note It is advisable to use deviceTransform() instead of this
3050 function to preserve the properties of perspective transformations.
3052 This function is \e only needed when using platform painting
3053 commands on the platform dependent handle (Qt::HANDLE), and the
3054 platform does not do transformations nativly.
3056 The QPaintEngine::PaintEngineFeature enum can be queried to
3057 determine whether the platform performs the transformations or
3060 \sa worldMatrix(), QPaintEngine::hasFeature(),
3062 const QMatrix &QPainter::deviceMatrix() const
3064 Q_D(const QPainter);
3066 qWarning("QPainter::deviceMatrix: Painter not active");
3067 return d->fakeState()->transform.toAffine();
3069 return d->state->matrix.toAffine();
3075 Resets any transformations that were made using translate(), scale(),
3076 shear(), rotate(), setWorldMatrix(), setViewport() and
3079 It is advisable to use resetTransform() instead of this function
3080 to preserve the properties of perspective transformations.
3082 \sa {QPainter#Coordinate Transformations}{Coordinate
3086 void QPainter::resetMatrix()
3095 Enables transformations if \a enable is true, or disables
3096 transformations if \a enable is false. The world transformation
3097 matrix is not changed.
3099 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3100 Transformations}{Coordinate Transformations}
3103 void QPainter::setWorldMatrixEnabled(bool enable)
3106 #ifdef QT_DEBUG_DRAW
3107 if (qt_show_painter_debug_output)
3108 printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3112 qWarning("QPainter::setMatrixEnabled: Painter not active");
3115 if (enable == d->state->WxF)
3118 d->state->WxF = enable;
3125 Returns true if world transformation is enabled; otherwise returns
3128 \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3131 bool QPainter::worldMatrixEnabled() const
3133 Q_D(const QPainter);
3135 qWarning("QPainter::worldMatrixEnabled: Painter not active");
3138 return d->state->WxF;
3144 Use setWorldMatrixEnabled() instead.
3146 \sa setWorldMatrixEnabled()
3149 void QPainter::setMatrixEnabled(bool enable)
3151 setWorldMatrixEnabled(enable);
3157 Use worldMatrixEnabled() instead
3159 \sa worldMatrixEnabled()
3162 bool QPainter::matrixEnabled() const
3164 return worldMatrixEnabled();
3168 Scales the coordinate system by (\a{sx}, \a{sy}).
3170 \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate
3174 void QPainter::scale(qreal sx, qreal sy)
3176 #ifdef QT_DEBUG_DRAW
3177 if (qt_show_painter_debug_output)
3178 printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3182 qWarning("QPainter::scale: Painter not active");
3186 d->state->worldMatrix.scale(sx,sy);
3187 d->state->WxF = true;
3192 Shears the coordinate system by (\a{sh}, \a{sv}).
3194 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3198 void QPainter::shear(qreal sh, qreal sv)
3200 #ifdef QT_DEBUG_DRAW
3201 if (qt_show_painter_debug_output)
3202 printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3206 qWarning("QPainter::shear: Painter not active");
3210 d->state->worldMatrix.shear(sh, sv);
3211 d->state->WxF = true;
3216 \fn void QPainter::rotate(qreal angle)
3218 Rotates the coordinate system the given \a angle clockwise.
3220 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3224 void QPainter::rotate(qreal a)
3226 #ifdef QT_DEBUG_DRAW
3227 if (qt_show_painter_debug_output)
3228 printf("QPainter::rotate(), angle=%f\n", a);
3232 qWarning("QPainter::rotate: Painter not active");
3236 d->state->worldMatrix.rotate(a);
3237 d->state->WxF = true;
3242 Translates the coordinate system by the given \a offset; i.e. the
3243 given \a offset is added to points.
3245 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3248 void QPainter::translate(const QPointF &offset)
3250 qreal dx = offset.x();
3251 qreal dy = offset.y();
3252 #ifdef QT_DEBUG_DRAW
3253 if (qt_show_painter_debug_output)
3254 printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3258 qWarning("QPainter::translate: Painter not active");
3262 d->state->worldMatrix.translate(dx, dy);
3263 d->state->WxF = true;
3268 \fn void QPainter::translate(const QPoint &offset)
3271 Translates the coordinate system by the given \a offset.
3275 \fn void QPainter::translate(qreal dx, qreal dy)
3278 Translates the coordinate system by the vector (\a dx, \a dy).
3282 \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3284 Enables clipping, and sets the clip path for the painter to the
3285 given \a path, with the clip \a operation.
3287 Note that the clip path is specified in logical (painter)
3290 \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3293 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3295 #ifdef QT_DEBUG_DRAW
3296 if (qt_show_painter_debug_output) {
3297 QRectF b = path.boundingRect();
3298 printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3299 path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3305 qWarning("QPainter::setClipPath: Painter not active");
3309 if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
3310 op = Qt::ReplaceClip;
3313 d->state->clipEnabled = true;
3314 d->extended->clip(path, op);
3315 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3316 d->state->clipInfo.clear();
3317 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3318 d->state->clipOperation = op;
3322 d->state->clipPath = path;
3323 d->state->clipOperation = op;
3324 if (op == Qt::NoClip || op == Qt::ReplaceClip)
3325 d->state->clipInfo.clear();
3326 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3327 d->state->clipEnabled = true;
3328 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3329 d->updateState(d->state);
3333 Draws the outline (strokes) the path \a path with the pen specified
3336 \sa fillPath(), {QPainter#Drawing}{Drawing}
3338 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3343 qWarning("QPainter::strokePath: Painter not active");
3351 const QGradient *g = qpen_brush(pen).gradient();
3352 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3353 d->extended->stroke(qtVectorPathForPath(path), pen);
3358 QBrush oldBrush = d->state->brush;
3359 QPen oldPen = d->state->pen;
3362 setBrush(Qt::NoBrush);
3372 Fills the given \a path using the given \a brush. The outline is
3375 Alternatively, you can specify a QColor instead of a QBrush; the
3376 QBrush constructor (taking a QColor argument) will automatically
3377 create a solid pattern brush.
3381 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3386 qWarning("QPainter::fillPath: Painter not active");
3394 const QGradient *g = brush.gradient();
3395 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3396 d->extended->fill(qtVectorPathForPath(path), brush);
3401 QBrush oldBrush = d->state->brush;
3402 QPen oldPen = d->state->pen;
3415 Draws the given painter \a path using the current pen for outline
3416 and the current brush for filling.
3420 \o \inlineimage qpainter-path.png
3422 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 5
3425 \sa {painting/painterpaths}{the Painter Paths
3426 example},{demos/deform}{the Vector Deformation demo}
3428 void QPainter::drawPath(const QPainterPath &path)
3430 #ifdef QT_DEBUG_DRAW
3431 QRectF pathBounds = path.boundingRect();
3432 if (qt_show_painter_debug_output)
3433 printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3434 path.elementCount(),
3435 pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3441 qWarning("QPainter::drawPath: Painter not active");
3446 d->extended->drawPath(path);
3449 d->updateState(d->state);
3451 if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3452 d->engine->drawPath(path);
3454 d->draw_helper(path);
3459 \fn void QPainter::drawLine(const QLineF &line)
3461 Draws a line defined by \a line.
3465 \o \inlineimage qpainter-line.png
3467 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 6
3470 \sa drawLines(), drawPolyline(), {Coordinate System}
3474 \fn void QPainter::drawLine(const QLine &line)
3477 Draws a line defined by \a line.
3481 \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3484 Draws a line from \a p1 to \a p2.
3488 \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3491 Draws a line from \a p1 to \a p2.
3495 \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3498 Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3499 current pen position to (\a x2, \a y2).
3503 \fn void QPainter::drawRect(const QRectF &rectangle)
3505 Draws the current \a rectangle with the current pen and brush.
3507 A filled rectangle has a size of \a{rectangle}.size(). A stroked
3508 rectangle has a size of \a{rectangle}.size() plus the pen width.
3512 \o \inlineimage qpainter-rectangle.png
3514 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 7
3517 \sa drawRects(), drawPolygon(), {Coordinate System}
3521 \fn void QPainter::drawRect(const QRect &rectangle)
3525 Draws the current \a rectangle with the current pen and brush.
3529 \fn void QPainter::drawRect(int x, int y, int width, int height)
3533 Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3534 with the given \a width and \a height.
3538 \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3540 Draws the first \a rectCount of the given \a rectangles using the
3541 current pen and brush.
3545 void QPainter::drawRects(const QRectF *rects, int rectCount)
3547 #ifdef QT_DEBUG_DRAW
3548 if (qt_show_painter_debug_output)
3549 printf("QPainter::drawRects(), count=%d\n", rectCount);
3554 qWarning("QPainter::drawRects: Painter not active");
3562 d->extended->drawRects(rects, rectCount);
3566 d->updateState(d->state);
3568 if (!d->state->emulationSpecifier) {
3569 d->engine->drawRects(rects, rectCount);
3573 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3574 && d->state->matrix.type() == QTransform::TxTranslate) {
3575 for (int i=0; i<rectCount; ++i) {
3576 QRectF r(rects[i].x() + d->state->matrix.dx(),
3577 rects[i].y() + d->state->matrix.dy(),
3580 d->engine->drawRects(&r, 1);
3583 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3584 for (int i=0; i<rectCount; ++i) {
3585 QPainterPath rectPath;
3586 rectPath.addRect(rects[i]);
3587 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3590 QPainterPath rectPath;
3591 for (int i=0; i<rectCount; ++i)
3592 rectPath.addRect(rects[i]);
3593 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3599 \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3602 Draws the first \a rectCount of the given \a rectangles using the
3603 current pen and brush.
3605 void QPainter::drawRects(const QRect *rects, int rectCount)
3607 #ifdef QT_DEBUG_DRAW
3608 if (qt_show_painter_debug_output)
3609 printf("QPainter::drawRects(), count=%d\n", rectCount);
3614 qWarning("QPainter::drawRects: Painter not active");
3622 d->extended->drawRects(rects, rectCount);
3626 d->updateState(d->state);
3628 if (!d->state->emulationSpecifier) {
3629 d->engine->drawRects(rects, rectCount);
3633 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3634 && d->state->matrix.type() == QTransform::TxTranslate) {
3635 for (int i=0; i<rectCount; ++i) {
3636 QRectF r(rects[i].x() + d->state->matrix.dx(),
3637 rects[i].y() + d->state->matrix.dy(),
3641 d->engine->drawRects(&r, 1);
3644 if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3645 for (int i=0; i<rectCount; ++i) {
3646 QPainterPath rectPath;
3647 rectPath.addRect(rects[i]);
3648 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3651 QPainterPath rectPath;
3652 for (int i=0; i<rectCount; ++i)
3653 rectPath.addRect(rects[i]);
3655 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3661 \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3664 Draws the given \a rectangles using the current pen and brush.
3668 \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3672 Draws the given \a rectangles using the current pen and brush.
3676 \fn void QPainter::drawPoint(const QPointF &position)
3678 Draws a single point at the given \a position using the current
3681 \sa {Coordinate System}
3685 \fn void QPainter::drawPoint(const QPoint &position)
3688 Draws a single point at the given \a position using the current
3692 /*! \fn void QPainter::drawPoint(int x, int y)
3696 Draws a single point at position (\a x, \a y).
3700 Draws the first \a pointCount points in the array \a points using
3701 the current pen's color.
3703 \sa {Coordinate System}
3705 void QPainter::drawPoints(const QPointF *points, int pointCount)
3707 #ifdef QT_DEBUG_DRAW
3708 if (qt_show_painter_debug_output)
3709 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3714 qWarning("QPainter::drawPoints: Painter not active");
3718 if (pointCount <= 0)
3722 d->extended->drawPoints(points, pointCount);
3726 d->updateState(d->state);
3728 if (!d->state->emulationSpecifier) {
3729 d->engine->drawPoints(points, pointCount);
3733 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3734 && d->state->matrix.type() == QTransform::TxTranslate) {
3735 // ### use drawPoints function
3736 for (int i=0; i<pointCount; ++i) {
3737 QPointF pt(points[i].x() + d->state->matrix.dx(),
3738 points[i].y() + d->state->matrix.dy());
3739 d->engine->drawPoints(&pt, 1);
3742 QPen pen = d->state->pen;
3743 bool flat_pen = pen.capStyle() == Qt::FlatCap;
3746 pen.setCapStyle(Qt::SquareCap);
3750 for (int i=0; i<pointCount; ++i) {
3751 path.moveTo(points[i].x(), points[i].y());
3752 path.lineTo(points[i].x() + 0.0001, points[i].y());
3754 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3763 Draws the first \a pointCount points in the array \a points using
3764 the current pen's color.
3767 void QPainter::drawPoints(const QPoint *points, int pointCount)
3769 #ifdef QT_DEBUG_DRAW
3770 if (qt_show_painter_debug_output)
3771 printf("QPainter::drawPoints(), count=%d\n", pointCount);
3776 qWarning("QPainter::drawPoints: Painter not active");
3780 if (pointCount <= 0)
3784 d->extended->drawPoints(points, pointCount);
3788 d->updateState(d->state);
3790 if (!d->state->emulationSpecifier) {
3791 d->engine->drawPoints(points, pointCount);
3795 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3796 && d->state->matrix.type() == QTransform::TxTranslate) {
3797 // ### use drawPoints function
3798 for (int i=0; i<pointCount; ++i) {
3799 QPointF pt(points[i].x() + d->state->matrix.dx(),
3800 points[i].y() + d->state->matrix.dy());
3801 d->engine->drawPoints(&pt, 1);
3804 QPen pen = d->state->pen;
3805 bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3808 pen.setCapStyle(Qt::SquareCap);
3812 for (int i=0; i<pointCount; ++i) {
3813 path.moveTo(points[i].x(), points[i].y());
3814 path.lineTo(points[i].x() + 0.0001, points[i].y());
3816 d->draw_helper(path, QPainterPrivate::StrokeDraw);
3823 \fn void QPainter::drawPoints(const QPolygonF &points)
3827 Draws the points in the vector \a points.
3831 \fn void QPainter::drawPoints(const QPolygon &points)
3835 Draws the points in the vector \a points.
3839 \fn void QPainter::drawPoints(const QPolygon &polygon, int index,
3845 Draws \a count points in the vector \a polygon starting on \a index
3846 using the current pen.
3848 Use drawPoints() combined with QPolygon::constData() instead.
3851 QPainter painter(this);
3852 painter.drawPoints(polygon, index, count);
3854 int pointCount = (count == -1) ? polygon.size() - index : count;
3856 QPainter painter(this);
3857 painter.drawPoints(polygon.constData() + index, pointCount);
3862 Sets the background mode of the painter to the given \a mode
3864 Qt::TransparentMode (the default) draws stippled lines and text
3865 without setting the background pixels. Qt::OpaqueMode fills these
3866 space with the current background color.
3868 Note that in order to draw a bitmap or pixmap transparently, you
3869 must use QPixmap::setMask().
3871 \sa backgroundMode(), setBackground(),
3872 {QPainter#Settings}{Settings}
3875 void QPainter::setBackgroundMode(Qt::BGMode mode)
3877 #ifdef QT_DEBUG_DRAW
3878 if (qt_show_painter_debug_output)
3879 printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3884 qWarning("QPainter::setBackgroundMode: Painter not active");
3887 if (d->state->bgMode == mode)
3890 d->state->bgMode = mode;
3892 d->checkEmulation();
3894 d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3899 Returns the current background mode.
3901 \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3903 Qt::BGMode QPainter::backgroundMode() const
3905 Q_D(const QPainter);
3907 qWarning("QPainter::backgroundMode: Painter not active");
3908 return Qt::TransparentMode;
3910 return d->state->bgMode;
3917 Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3921 void QPainter::setPen(const QColor &color)
3923 #ifdef QT_DEBUG_DRAW
3924 if (qt_show_painter_debug_output)
3925 printf("QPainter::setPen(), color=%04x\n", color.rgb());
3929 qWarning("QPainter::setPen: Painter not active");
3933 if (d->state->pen.style() == Qt::SolidLine
3934 && d->state->pen.widthF() == 0
3935 && d->state->pen.isSolid()
3936 && d->state->pen.color() == color)
3939 QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
3941 d->state->pen = pen;
3943 d->extended->penChanged();
3945 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3949 Sets the painter's pen to be the given \a pen.
3951 The \a pen defines how to draw lines and outlines, and it also
3952 defines the text color.
3954 \sa pen(), {QPainter#Settings}{Settings}
3957 void QPainter::setPen(const QPen &pen)
3960 #ifdef QT_DEBUG_DRAW
3961 if (qt_show_painter_debug_output)
3962 printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3963 pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3967 qWarning("QPainter::setPen: Painter not active");
3971 if (d->state->pen == pen)
3974 d->state->pen = pen;
3977 d->checkEmulation();
3978 d->extended->penChanged();
3982 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3988 Sets the painter's pen to have the given \a style, width 0 and
3992 void QPainter::setPen(Qt::PenStyle style)
3996 qWarning("QPainter::setPen: Painter not active");
4000 if (d->state->pen.style() == style
4001 && (style == Qt::NoPen || (d->state->pen.widthF() == 0
4002 && d->state->pen.isSolid()
4003 && d->state->pen.color() == QColor(Qt::black))))
4006 // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
4007 // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
4008 d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
4011 d->extended->penChanged();
4013 d->state->dirtyFlags |= QPaintEngine::DirtyPen;
4018 Returns the painter's current pen.
4020 \sa setPen(), {QPainter#Settings}{Settings}
4023 const QPen &QPainter::pen() const
4025 Q_D(const QPainter);
4027 qWarning("QPainter::pen: Painter not active");
4028 return d->fakeState()->pen;
4030 return d->state->pen;
4035 Sets the painter's brush to the given \a brush.
4037 The painter's brush defines how shapes are filled.
4039 \sa brush(), {QPainter#Settings}{Settings}
4042 void QPainter::setBrush(const QBrush &brush)
4044 #ifdef QT_DEBUG_DRAW
4045 if (qt_show_painter_debug_output)
4046 printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
4050 qWarning("QPainter::setBrush: Painter not active");
4054 if (d->state->brush.d == brush.d)
4058 d->state->brush = brush;
4059 d->checkEmulation();
4060 d->extended->brushChanged();
4064 d->state->brush = brush;
4065 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4072 Sets the painter's brush to black color and the specified \a
4076 void QPainter::setBrush(Qt::BrushStyle style)
4080 qWarning("QPainter::setBrush: Painter not active");
4083 if (d->state->brush.style() == style &&
4084 (style == Qt::NoBrush
4085 || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
4087 d->state->brush = QBrush(Qt::black, style);
4089 d->extended->brushChanged();
4091 d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4095 Returns the painter's current brush.
4097 \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
4100 const QBrush &QPainter::brush() const
4102 Q_D(const QPainter);
4104 qWarning("QPainter::brush: Painter not active");
4105 return d->fakeState()->brush;
4107 return d->state->brush;
4111 \fn void QPainter::setBackground(const QBrush &brush)
4113 Sets the background brush of the painter to the given \a brush.
4115 The background brush is the brush that is filled in when drawing
4116 opaque text, stippled lines and bitmaps. The background brush has
4117 no effect in transparent background mode (which is the default).
4119 \sa background(), setBackgroundMode(),
4120 {QPainter#Settings}{Settings}
4123 void QPainter::setBackground(const QBrush &bg)
4125 #ifdef QT_DEBUG_DRAW
4126 if (qt_show_painter_debug_output)
4127 printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4132 qWarning("QPainter::setBackground: Painter not active");
4135 d->state->bgBrush = bg;
4137 d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4141 Sets the painter's font to the given \a font.
4143 This font is used by subsequent drawText() functions. The text
4144 color is the same as the pen color.
4146 If you set a font that isn't available, Qt finds a close match.
4147 font() will return what you set using setFont() and fontInfo() returns the
4148 font actually being used (which may be the same).
4150 \sa font(), drawText(), {QPainter#Settings}{Settings}
4153 void QPainter::setFont(const QFont &font)
4157 #ifdef QT_DEBUG_DRAW
4158 if (qt_show_painter_debug_output)
4159 printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4163 qWarning("QPainter::setFont: Painter not active");
4167 d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4169 d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4173 Returns the currently set font used for drawing text.
4175 \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4177 const QFont &QPainter::font() const
4179 Q_D(const QPainter);
4181 qWarning("QPainter::font: Painter not active");
4182 return d->fakeState()->font;
4184 return d->state->font;
4190 Draws the given rectangle \a rect with rounded corners.
4192 The \a xRadius and \a yRadius arguments specify the radii
4193 of the ellipses defining the corners of the rounded rectangle.
4194 When \a mode is Qt::RelativeSize, \a xRadius and
4195 \a yRadius are specified in percentage of half the rectangle's
4196 width and height respectively, and should be in the range
4199 A filled rectangle has a size of rect.size(). A stroked rectangle
4200 has a size of rect.size() plus the pen width.
4204 \o \inlineimage qpainter-roundrect.png
4206 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 8
4209 \sa drawRect(), QPen
4211 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4213 #ifdef QT_DEBUG_DRAW
4214 if (qt_show_painter_debug_output)
4215 printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4222 if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
4228 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4233 path.addRoundedRect(rect, xRadius, yRadius, mode);
4238 \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4239 Qt::SizeMode mode = Qt::AbsoluteSize);
4243 Draws the given rectangle \a rect with rounded corners.
4247 \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4248 Qt::SizeMode mode = Qt::AbsoluteSize);
4252 Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4258 Draws a rectangle \a r with rounded corners.
4260 The \a xRnd and \a yRnd arguments specify how rounded the corners
4261 should be. 0 is angled corners, 99 is maximum roundedness.
4263 A filled rectangle has a size of r.size(). A stroked rectangle
4264 has a size of r.size() plus the pen width.
4266 \sa drawRoundedRect()
4268 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4270 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4275 \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4280 Draws the rectangle \a r with rounded corners.
4286 \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4290 Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4294 \fn void QPainter::drawEllipse(const QRectF &rectangle)
4296 Draws the ellipse defined by the given \a rectangle.
4298 A filled ellipse has a size of \a{rectangle}.\l
4299 {QRect::size()}{size()}. A stroked ellipse has a size of
4300 \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4304 \o \inlineimage qpainter-ellipse.png
4306 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 9
4309 \sa drawPie(), {Coordinate System}
4311 void QPainter::drawEllipse(const QRectF &r)
4313 #ifdef QT_DEBUG_DRAW
4314 if (qt_show_painter_debug_output)
4315 printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4322 QRectF rect(r.normalized());
4325 d->extended->drawEllipse(rect);
4329 d->updateState(d->state);
4330 if (d->state->emulationSpecifier) {
4331 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4332 && d->state->matrix.type() == QTransform::TxTranslate) {
4333 rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4336 path.addEllipse(rect);
4337 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4342 d->engine->drawEllipse(rect);
4346 \fn QPainter::drawEllipse(const QRect &rectangle)
4350 Draws the ellipse defined by the given \a rectangle.
4352 void QPainter::drawEllipse(const QRect &r)
4354 #ifdef QT_DEBUG_DRAW
4355 if (qt_show_painter_debug_output)
4356 printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4363 QRect rect(r.normalized());
4366 d->extended->drawEllipse(rect);
4370 d->updateState(d->state);
4372 if (d->state->emulationSpecifier) {
4373 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4374 && d->state->matrix.type() == QTransform::TxTranslate) {
4375 rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4378 path.addEllipse(rect);
4379 d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4384 d->engine->drawEllipse(rect);
4388 \fn QPainter::drawEllipse(int x, int y, int width, int height)
4392 Draws the ellipse defined by the rectangle beginning at (\a{x},
4393 \a{y}) with the given \a width and \a height.
4399 \fn QPainter::drawEllipse(const QPointF ¢er, qreal rx, qreal ry)
4403 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4409 \fn QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)
4413 Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4417 \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4419 Draws the arc defined by the given \a rectangle, \a startAngle and
4422 The \a startAngle and \a spanAngle must be specified in 1/16th of
4423 a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4424 values for the angles mean counter-clockwise while negative values
4425 mean the clockwise direction. Zero degrees is at the 3 o'clock
4430 \o \inlineimage qpainter-arc.png
4432 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 10
4435 \sa drawPie(), drawChord(), {Coordinate System}
4438 void QPainter::drawArc(const QRectF &r, int a, int alen)
4440 #ifdef QT_DEBUG_DRAW
4441 if (qt_show_painter_debug_output)
4442 printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4443 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4450 QRectF rect = r.normalized();
4453 path.arcMoveTo(rect, a/16.0);
4454 path.arcTo(rect, a/16.0, alen/16.0);
4455 strokePath(path, d->state->pen);
4458 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4463 Draws the arc defined by the given \a rectangle, \a startAngle and
4468 \fn void QPainter::drawArc(int x, int y, int width, int height,
4469 int startAngle, int spanAngle)
4473 Draws the arc defined by the rectangle beginning at (\a x, \a y)
4474 with the specified \a width and \a height, and the given \a
4475 startAngle and \a spanAngle.
4479 \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4481 Draws a pie defined by the given \a rectangle, \a startAngle and
4484 The pie is filled with the current brush().
4486 The startAngle and spanAngle must be specified in 1/16th of a
4487 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4488 for the angles mean counter-clockwise while negative values mean
4489 the clockwise direction. Zero degrees is at the 3 o'clock
4494 \o \inlineimage qpainter-pie.png
4496 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 11
4499 \sa drawEllipse(), drawChord(), {Coordinate System}
4501 void QPainter::drawPie(const QRectF &r, int a, int alen)
4503 #ifdef QT_DEBUG_DRAW
4504 if (qt_show_painter_debug_output)
4505 printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4506 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4517 if (a < 0) a += (360*16);
4520 QRectF rect = r.normalized();
4523 path.moveTo(rect.center());
4524 path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4525 path.closeSubpath();
4531 \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4534 Draws a pie defined by the given \a rectangle, \a startAngle and
4539 \fn void QPainter::drawPie(int x, int y, int width, int height, int
4540 startAngle, int spanAngle)
4544 Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4545 the specified \a width and \a height, and the given \a startAngle and
4550 \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4552 Draws the chord defined by the given \a rectangle, \a startAngle and
4553 \a spanAngle. The chord is filled with the current brush().
4555 The startAngle and spanAngle must be specified in 1/16th of a
4556 degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4557 for the angles mean counter-clockwise while negative values mean
4558 the clockwise direction. Zero degrees is at the 3 o'clock
4563 \o \inlineimage qpainter-chord.png
4565 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 12
4568 \sa drawArc(), drawPie(), {Coordinate System}
4570 void QPainter::drawChord(const QRectF &r, int a, int alen)
4572 #ifdef QT_DEBUG_DRAW
4573 if (qt_show_painter_debug_output)
4574 printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4575 r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4582 QRectF rect = r.normalized();
4585 path.arcMoveTo(rect, a/16.0);
4586 path.arcTo(rect, a/16.0, alen/16.0);
4587 path.closeSubpath();
4591 \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4595 Draws the chord defined by the given \a rectangle, \a startAngle and
4600 \fn void QPainter::drawChord(int x, int y, int width, int height, int
4601 startAngle, int spanAngle)
4605 Draws the chord defined by the rectangle beginning at (\a x, \a y)
4606 with the specified \a width and \a height, and the given \a
4607 startAngle and \a spanAngle.
4612 \fn void QPainter::drawLineSegments(const QPolygon &polygon, int
4615 Draws \a count separate lines from points defined by the \a
4616 polygon, starting at \a{polygon}\e{[index]} (\a index defaults to
4617 0). If \a count is -1 (the default) all points until the end of
4620 Use drawLines() combined with QPolygon::constData() instead.
4623 QPainter painter(this);
4624 painter.drawLineSegments(polygon, index, count);
4626 int lineCount = (count == -1) ? (polygon.size() - index) / 2 : count;
4628 QPainter painter(this);
4629 painter.drawLines(polygon.constData() + index * 2, lineCount);
4633 void QPainter::drawLineSegments(const QPolygon &a, int index, int nlines)
4635 #ifdef QT_DEBUG_DRAW
4636 if (qt_show_painter_debug_output)
4637 printf("QPainter::drawLineSegments(), count=%d\n", a.size()/2);
4645 nlines = a.size()/2 - index/2;
4646 if (index + nlines*2 > (int)a.size())
4647 nlines = (a.size() - index)/2;
4648 if (nlines < 1 || index < 0)
4652 // FALCON: Use QVectorPath
4653 QVector<QLineF> lines;
4654 for (int i=index; i<index + nlines*2; i+=2)
4655 lines << QLineF(a.at(i), a.at(i+1));
4656 d->extended->drawLines(lines.data(), lines.size());
4660 d->updateState(d->state);
4662 QVector<QLineF> lines;
4663 if (d->state->emulationSpecifier) {
4664 if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4665 && d->state->matrix.type() == QTransform::TxTranslate) {
4666 QPointF offset(d->state->matrix.dx(), d->state->matrix.dy());
4667 for (int i=index; i<index + nlines*2; i+=2)
4668 lines << QLineF(a.at(i) + offset, a.at(i+1) + offset);
4670 QPainterPath linesPath;
4671 for (int i=index; i<index + nlines*2; i+=2) {
4672 linesPath.moveTo(a.at(i));
4673 linesPath.lineTo(a.at(i+1));
4675 d->draw_helper(linesPath, QPainterPrivate::StrokeDraw);
4679 for (int i=index; i<index + nlines*2; i+=2)
4680 lines << QLineF(a.at(i), a.at(i+1));
4683 d->engine->drawLines(lines.data(), lines.size());
4685 #endif // QT3_SUPPORT
4688 Draws the first \a lineCount lines in the array \a lines
4689 using the current pen.
4691 \sa drawLine(), drawPolyline()
4693 void QPainter::drawLines(const QLineF *lines, int lineCount)
4695 #ifdef QT_DEBUG_DRAW
4696 if (qt_show_painter_debug_output)
4697 printf("QPainter::drawLines(), line count=%d\n", lineCount);
4702 if (!d->engine || lineCount < 1)
4706 d->extended->drawLines(lines, lineCount);
4710 d->updateState(d->state);
4712 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4714 if (lineEmulation) {
4715 if (lineEmulation == QPaintEngine::PrimitiveTransform
4716 && d->state->matrix.type() == QTransform::TxTranslate) {
4717 for (int i = 0; i < lineCount; ++i) {
4718 QLineF line = lines[i];
4719 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4720 d->engine->drawLines(&line, 1);
4723 QPainterPath linePath;
4724 for (int i = 0; i < lineCount; ++i) {
4725 linePath.moveTo(lines[i].p1());
4726 linePath.lineTo(lines[i].p2());
4728 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4732 d->engine->drawLines(lines, lineCount);
4736 \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4739 Draws the first \a lineCount lines in the array \a lines
4740 using the current pen.
4742 void QPainter::drawLines(const QLine *lines, int lineCount)
4744 #ifdef QT_DEBUG_DRAW
4745 if (qt_show_painter_debug_output)
4746 printf("QPainter::drawLine(), line count=%d\n", lineCount);
4751 if (!d->engine || lineCount < 1)
4755 d->extended->drawLines(lines, lineCount);
4759 d->updateState(d->state);
4761 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4763 if (lineEmulation) {
4764 if (lineEmulation == QPaintEngine::PrimitiveTransform
4765 && d->state->matrix.type() == QTransform::TxTranslate) {
4766 for (int i = 0; i < lineCount; ++i) {
4767 QLineF line = lines[i];
4768 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4769 d->engine->drawLines(&line, 1);
4772 QPainterPath linePath;
4773 for (int i = 0; i < lineCount; ++i) {
4774 linePath.moveTo(lines[i].p1());
4775 linePath.lineTo(lines[i].p2());
4777 d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4781 d->engine->drawLines(lines, lineCount);
4787 Draws the first \a lineCount lines in the array \a pointPairs
4788 using the current pen. The lines are specified as pairs of points
4789 so the number of entries in \a pointPairs must be at least \a
4792 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4794 Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4796 drawLines((QLineF*)pointPairs, lineCount);
4802 Draws the first \a lineCount lines in the array \a pointPairs
4803 using the current pen.
4805 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4807 Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4809 drawLines((QLine*)pointPairs, lineCount);
4814 \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4817 Draws a line for each pair of points in the vector \a pointPairs
4818 using the current pen. If there is an odd number of points in the
4819 array, the last point will be ignored.
4823 \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4826 Draws a line for each pair of points in the vector \a pointPairs
4827 using the current pen.
4831 \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4834 Draws the set of lines defined by the list \a lines using the
4835 current pen and brush.
4839 \fn void QPainter::drawLines(const QVector<QLine> &lines)
4842 Draws the set of lines defined by the list \a lines using the
4843 current pen and brush.
4847 Draws the polyline defined by the first \a pointCount points in \a
4848 points using the current pen.
4850 Note that unlike the drawPolygon() function the last point is \e
4851 not connected to the first, neither is the polyline filled.
4856 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 13
4859 \sa drawLines(), drawPolygon(), {Coordinate System}
4861 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4863 #ifdef QT_DEBUG_DRAW
4864 if (qt_show_painter_debug_output)
4865 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4869 if (!d->engine || pointCount < 2)
4873 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4877 d->updateState(d->state);
4879 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4881 if (lineEmulation) {
4883 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4884 // && d->state->matrix.type() == QTransform::TxTranslate) {
4886 QPainterPath polylinePath(points[0]);
4887 for (int i=1; i<pointCount; ++i)
4888 polylinePath.lineTo(points[i]);
4889 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4892 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4899 Draws the polyline defined by the first \a pointCount points in \a
4900 points using the current pen.
4902 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4904 #ifdef QT_DEBUG_DRAW
4905 if (qt_show_painter_debug_output)
4906 printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4910 if (!d->engine || pointCount < 2)
4914 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4918 d->updateState(d->state);
4920 uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4922 if (lineEmulation) {
4924 // if (lineEmulation == QPaintEngine::PrimitiveTransform
4925 // && d->state->matrix.type() == QTransform::TxTranslate) {
4927 QPainterPath polylinePath(points[0]);
4928 for (int i=1; i<pointCount; ++i)
4929 polylinePath.lineTo(points[i]);
4930 d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4933 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4938 \fn void QPainter::drawPolyline(const QPolygon &polygon, int index, int
4944 Draws the polyline defined by the \a count lines of the given \a
4945 polygon starting at \a index (\a index defaults to 0).
4947 Use drawPolyline() combined with QPolygon::constData() instead.
4950 QPainter painter(this);
4951 painter.drawPolyline(polygon, index, count);
4953 int pointCount = (count == -1) ? polygon.size() - index : count;
4955 QPainter painter(this);
4956 painter.drawPolyline(polygon.constData() + index, pointCount);
4961 \fn void QPainter::drawPolyline(const QPolygonF &points)
4965 Draws the polyline defined by the given \a points using the
4970 \fn void QPainter::drawPolyline(const QPolygon &points)
4974 Draws the polyline defined by the given \a points using the
4979 Draws the polygon defined by the first \a pointCount points in the
4980 array \a points using the current pen and brush.
4984 \o \inlineimage qpainter-polygon.png
4986 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 14
4989 The first point is implicitly connected to the last point, and the
4990 polygon is filled with the current brush().
4992 If \a fillRule is Qt::WindingFill, the polygon is filled using the
4993 winding fill algorithm. If \a fillRule is Qt::OddEvenFill, the
4994 polygon is filled using the odd-even fill algorithm. See
4995 \l{Qt::FillRule} for a more detailed description of these fill
4998 \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
5000 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
5002 #ifdef QT_DEBUG_DRAW
5003 if (qt_show_painter_debug_output)
5004 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
5009 if (!d->engine || pointCount < 2)
5013 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5017 d->updateState(d->state);
5019 uint emulationSpecifier = d->state->emulationSpecifier;
5021 if (emulationSpecifier) {
5022 QPainterPath polygonPath(points[0]);
5023 for (int i=1; i<pointCount; ++i)
5024 polygonPath.lineTo(points[i]);
5025 polygonPath.closeSubpath();
5026 polygonPath.setFillRule(fillRule);
5027 d->draw_helper(polygonPath);
5031 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5036 Draws the polygon defined by the first \a pointCount points in the
5039 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
5041 #ifdef QT_DEBUG_DRAW
5042 if (qt_show_painter_debug_output)
5043 printf("QPainter::drawPolygon(), count=%d\n", pointCount);
5048 if (!d->engine || pointCount < 2)
5052 d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5056 d->updateState(d->state);
5058 uint emulationSpecifier = d->state->emulationSpecifier;
5060 if (emulationSpecifier) {
5061 QPainterPath polygonPath(points[0]);
5062 for (int i=1; i<pointCount; ++i)
5063 polygonPath.lineTo(points[i]);
5064 polygonPath.closeSubpath();
5065 polygonPath.setFillRule(fillRule);
5066 d->draw_helper(polygonPath);
5070 d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
5073 /*! \fn void QPainter::drawPolygon(const QPolygonF &polygon, bool winding, int index = 0,
5078 Use drawPolygon() combined with QPolygonF::constData() instead.
5081 QPainter painter(this);
5082 painter.drawPolygon(polygon, winding, index, count);
5084 int pointCount = (count == -1) ? polygon.size() - index : count;
5085 int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
5087 QPainter painter(this);
5088 painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
5092 /*! \fn void QPainter::drawPolygon(const QPolygon &polygon, bool winding,
5093 int index = 0, int count = -1)
5098 Use drawPolygon() combined with QPolygon::constData() instead.
5101 QPainter painter(this);
5102 painter.drawPolygon(polygon, winding, index, count);
5104 int pointCount = (count == -1) ? polygon.size() - index : count;
5105 int fillRule = winding ? Qt::WindingFill : Qt::OddEvenFill;
5107 QPainter painter(this);
5108 painter.drawPolygon( polygon.constData() + index, pointCount, fillRule);
5112 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
5116 Draws the polygon defined by the given \a points using the fill
5120 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
5124 Draws the polygon defined by the given \a points using the fill
5129 \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
5131 Draws the convex polygon defined by the first \a pointCount points
5132 in the array \a points using the current pen.
5136 \o \inlineimage qpainter-polygon.png
5138 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 15
5141 The first point is implicitly connected to the last point, and the
5142 polygon is filled with the current brush(). If the supplied
5143 polygon is not convex, i.e. it contains at least one angle larger
5144 than 180 degrees, the results are undefined.
5146 On some platforms (e.g. X11), the drawConvexPolygon() function can
5147 be faster than the drawPolygon() function.
5149 \sa drawPolygon(), drawPolyline(), {Coordinate System}
5153 \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
5156 Draws the convex polygon defined by the first \a pointCount points
5157 in the array \a points using the current pen.
5161 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
5165 Draws the convex polygon defined by \a polygon using the current
5170 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
5173 Draws the convex polygon defined by \a polygon using the current
5178 \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon, int
5184 Use drawConvexPolygon() combined with QPolygonF::constData()
5188 QPainter painter(this);
5189 painter.drawConvexPolygon(polygon, index, count);
5191 int pointCount = (count == -1) ? polygon.size() - index : count;
5193 QPainter painter(this);
5194 painter.drawConvexPolygon(polygon.constData() + index, pointCount);
5199 \fn void QPainter::drawConvexPolygon(const QPolygon &polygon, int
5205 Use drawConvexPolygon() combined with QPolygon::constData()
5209 QPainter painter(this);
5210 painter.drawConvexPolygon(polygon, index, count);
5212 int pointCount = (count == -1) ? polygon.size() - index : count;
5214 QPainter painter(this);
5215 painter.drawConvexPolygon(polygon.constData() + index, pointCount);
5219 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
5221 #ifdef QT_DEBUG_DRAW
5222 if (qt_show_painter_debug_output)
5223 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5228 if (!d->engine || pointCount < 2)
5232 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5236 d->updateState(d->state);
5238 uint emulationSpecifier = d->state->emulationSpecifier;
5240 if (emulationSpecifier) {
5241 QPainterPath polygonPath(points[0]);
5242 for (int i=1; i<pointCount; ++i)
5243 polygonPath.lineTo(points[i]);
5244 polygonPath.closeSubpath();
5245 polygonPath.setFillRule(Qt::WindingFill);
5246 d->draw_helper(polygonPath);
5250 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5253 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
5255 #ifdef QT_DEBUG_DRAW
5256 if (qt_show_painter_debug_output)
5257 printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
5262 if (!d->engine || pointCount < 2)
5266 d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5270 d->updateState(d->state);
5272 uint emulationSpecifier = d->state->emulationSpecifier;
5274 if (emulationSpecifier) {
5275 QPainterPath polygonPath(points[0]);
5276 for (int i=1; i<pointCount; ++i)
5277 polygonPath.lineTo(points[i]);
5278 polygonPath.closeSubpath();
5279 polygonPath.setFillRule(Qt::WindingFill);
5280 d->draw_helper(polygonPath);
5284 d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5287 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5289 return m.inverted().map(QPointF(m.map(p).toPoint()));
5293 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5295 Draws the rectangular portion \a source of the given \a pixmap
5296 into the given \a target in the paint device.
5298 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5303 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 16
5306 If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5307 using the pens color. If backgroundMode is Qt::OpaqueMode, the
5308 "unset" bits are drawn using the color of the background brush; if
5309 backgroundMode is Qt::TransparentMode, the "unset" bits are
5310 transparent. Drawing bitmaps with gradient or texture colors is
5315 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5317 #if defined QT_DEBUG_DRAW
5318 if (qt_show_painter_debug_output)
5319 printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5321 pm.width(), pm.height());
5326 if (!d->engine || pm.isNull())
5330 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5334 d->extended->drawPixmap(p, pm);
5342 int h = pm.height();
5347 // Emulate opaque background for bitmaps
5348 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5349 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5352 d->updateState(d->state);
5354 if ((d->state->matrix.type() > QTransform::TxTranslate
5355 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5356 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5357 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5360 // If there is no rotation involved we have to make sure we use the
5361 // antialiased and not the aliased coordinate system by rounding the coordinates.
5362 if (d->state->matrix.type() <= QTransform::TxScale) {
5363 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5368 setBackgroundMode(Qt::TransparentMode);
5369 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5370 QBrush brush(d->state->pen.color(), pm);
5373 setBrushOrigin(QPointF(0, 0));
5375 drawRect(pm.rect());
5378 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5379 x += d->state->matrix.dx();
5380 y += d->state->matrix.dy();
5382 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5386 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5388 #if defined QT_DEBUG_DRAW
5389 if (qt_show_painter_debug_output)
5390 printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5391 r.x(), r.y(), r.width(), r.height(),
5392 pm.width(), pm.height(),
5393 sr.x(), sr.y(), sr.width(), sr.height());
5397 if (!d->engine || pm.isNull())
5400 qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5405 qreal w = r.width();
5406 qreal h = r.height();
5409 qreal sw = sr.width();
5410 qreal sh = sr.height();
5412 // Sanity-check clipping
5414 sw = pm.width() - sx;
5417 sh = pm.height() - sy;
5425 qreal w_ratio = sx * w/sw;
5433 qreal h_ratio = sy * h/sh;
5440 if (sw + sx > pm.width()) {
5441 qreal delta = sw - (pm.width() - sx);
5442 qreal w_ratio = delta * w/sw;
5447 if (sh + sy > pm.height()) {
5448 qreal delta = sh - (pm.height() - sy);
5449 qreal h_ratio = delta * h/sh;
5454 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5458 d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5462 // Emulate opaque background for bitmaps
5463 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5464 fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5466 d->updateState(d->state);
5468 if ((d->state->matrix.type() > QTransform::TxTranslate
5469 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5470 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5471 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5472 || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5475 // If there is no rotation involved we have to make sure we use the
5476 // antialiased and not the aliased coordinate system by rounding the coordinates.
5477 if (d->state->matrix.type() <= QTransform::TxScale) {
5478 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5483 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5491 scale(w / sw, h / sh);
5492 setBackgroundMode(Qt::TransparentMode);
5493 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5496 if (sw == pm.width() && sh == pm.height())
5497 brush = QBrush(d->state->pen.color(), pm);
5499 brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5504 drawRect(QRectF(0, 0, sw, sh));
5507 if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5508 x += d->state->matrix.dx();
5509 y += d->state->matrix.dy();
5511 d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5517 \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5518 const QRect &source)
5521 Draws the rectangular portion \a source of the given \a pixmap
5522 into the given \a target in the paint device.
5524 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5528 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5529 const QRectF &source)
5532 Draws the rectangular portion \a source of the given \a pixmap
5533 with its origin at the given \a point.
5537 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5538 const QRect &source)
5542 Draws the rectangular portion \a source of the given \a pixmap
5543 with its origin at the given \a point.
5547 \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5550 Draws the given \a pixmap with its origin at the given \a point.
5554 \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5557 Draws the given \a pixmap with its origin at the given \a point.
5561 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5565 Draws the given \a pixmap at position (\a{x}, \a{y}).
5569 \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5572 Draws the given \a pixmap into the given \a rectangle.
5574 \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5578 \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5579 const QPixmap &pixmap)
5583 Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5584 with the given \a width and \a height.
5588 \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5589 int sx, int sy, int sw, int sh)
5593 Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5594 width \a sw and height \a sh, of the given \a pixmap , at the
5595 point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5596 If sw or sh are equal to zero the width/height of the pixmap
5597 is used and adjusted by the offset sx/sy;
5601 \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5602 int sx, int sy, int sw, int sh)
5606 Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5607 pixmap into the paint device.
5609 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5610 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5611 pixmap that is to be drawn. The default is (0, 0).
5613 (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5614 The default, (0, 0) (and negative) means all the way to the
5615 bottom-right of the pixmap.
5618 void QPainter::drawImage(const QPointF &p, const QImage &image)
5622 if (!d->engine || image.isNull())
5626 d->extended->drawImage(p, image);
5633 int w = image.width();
5634 int h = image.height();
5636 d->updateState(d->state);
5638 if (((d->state->matrix.type() > QTransform::TxTranslate)
5639 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5640 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5641 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5644 // If there is no rotation involved we have to make sure we use the
5645 // antialiased and not the aliased coordinate system by rounding the coordinates.
5646 if (d->state->matrix.type() <= QTransform::TxScale) {
5647 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5652 setBackgroundMode(Qt::TransparentMode);
5653 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5654 QBrush brush(image);
5657 setBrushOrigin(QPointF(0, 0));
5659 drawRect(image.rect());
5664 if (d->state->matrix.type() == QTransform::TxTranslate
5665 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5666 x += d->state->matrix.dx();
5667 y += d->state->matrix.dy();
5670 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5673 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5674 Qt::ImageConversionFlags flags)
5678 if (!d->engine || image.isNull())
5681 qreal x = targetRect.x();
5682 qreal y = targetRect.y();
5683 qreal w = targetRect.width();
5684 qreal h = targetRect.height();
5685 qreal sx = sourceRect.x();
5686 qreal sy = sourceRect.y();
5687 qreal sw = sourceRect.width();
5688 qreal sh = sourceRect.height();
5690 // Sanity-check clipping
5692 sw = image.width() - sx;
5695 sh = image.height() - sy;
5703 qreal w_ratio = sx * w/sw;
5711 qreal h_ratio = sy * h/sh;
5718 if (sw + sx > image.width()) {
5719 qreal delta = sw - (image.width() - sx);
5720 qreal w_ratio = delta * w/sw;
5725 if (sh + sy > image.height()) {
5726 qreal delta = sh - (image.height() - sy);
5727 qreal h_ratio = delta * h/sh;
5732 if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5736 d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5740 d->updateState(d->state);
5742 if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5743 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5744 || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5745 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5748 // If there is no rotation involved we have to make sure we use the
5749 // antialiased and not the aliased coordinate system by rounding the coordinates.
5750 if (d->state->matrix.type() <= QTransform::TxScale) {
5751 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5756 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5763 scale(w / sw, h / sh);
5764 setBackgroundMode(Qt::TransparentMode);
5765 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5766 QBrush brush(image);
5769 setBrushOrigin(QPointF(-sx, -sy));
5771 drawRect(QRectF(0, 0, sw, sh));
5776 if (d->state->matrix.type() == QTransform::TxTranslate
5777 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5778 x += d->state->matrix.dx();
5779 y += d->state->matrix.dy();
5782 d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5786 Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5787 edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5788 selected on \a glyphs and at offsets given by the positions in \a glyphs.
5792 \sa QGlyphs::setFont(), QGlyphs::setPositions(), QGlyphs::setGlyphIndexes()
5794 #if !defined(QT_NO_RAWFONT)
5795 void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs)
5799 QRawFont font = glyphs.font();
5800 if (!font.isValid())
5803 QVector<quint32> glyphIndexes = glyphs.glyphIndexes();
5804 QVector<QPointF> glyphPositions = glyphs.positions();
5806 int count = qMin(glyphIndexes.size(), glyphPositions.size());
5807 QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5809 bool paintEngineSupportsTransformations =
5811 ? qt_paintengine_supports_transformations(d->extended->type())
5813 for (int i=0; i<count; ++i) {
5814 QPointF processedPosition = position + glyphPositions.at(i);
5815 if (!paintEngineSupportsTransformations)
5816 processedPosition = d->state->transform().map(processedPosition);
5817 fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5820 d->drawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count, font, glyphs.overline(),
5821 glyphs.underline(), glyphs.strikeOut());
5824 void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, int glyphCount,
5825 const QRawFont &font, bool overline, bool underline,
5832 QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5833 QFontEngine *fontEngine = fontD->fontEngine;
5838 for (int i=0; i<glyphCount; ++i) {
5839 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5840 if (i == 0 || leftMost > positions[i].x)
5841 leftMost = positions[i].x;
5843 // We don't support glyphs that do not share a common baseline. If this turns out to
5844 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5845 // and do a drawTextItemDecorations call per cluster.
5846 if (i == 0 || baseLine < positions[i].y)
5847 baseLine = positions[i].y;
5849 // We use the advance rather than the actual bounds to match the algorithm in drawText()
5850 if (i == 0 || rightMost < positions[i].x + gm.xoff)
5851 rightMost = positions[i].x + gm.xoff;
5854 QFixed width = rightMost - leftMost;
5856 if (extended != 0) {
5857 QStaticTextItem staticTextItem;
5858 staticTextItem.color = state->pen.color();
5859 staticTextItem.font = state->font;
5860 staticTextItem.setFontEngine(fontEngine);
5861 staticTextItem.numGlyphs = glyphCount;
5862 staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5863 staticTextItem.glyphPositions = positions;
5865 extended->drawStaticTextItem(&staticTextItem);
5867 QTextItemInt textItem;
5868 textItem.fontEngine = fontEngine;
5870 QVarLengthArray<QFixed, 128> advances(glyphCount);
5871 QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5872 QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5873 qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5874 qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
5875 qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5877 textItem.glyphs.numGlyphs = glyphCount;
5878 textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5879 textItem.glyphs.offsets = positions;
5880 textItem.glyphs.advances_x = advances.data();
5881 textItem.glyphs.advances_y = advances.data();
5882 textItem.glyphs.justifications = glyphJustifications.data();
5883 textItem.glyphs.attributes = glyphAttributes.data();
5885 engine->drawTextItem(QPointF(0, 0), textItem);
5888 QTextItemInt::RenderFlags flags;
5890 flags |= QTextItemInt::Underline;
5892 flags |= QTextItemInt::Overline;
5894 flags |= QTextItemInt::StrikeOut;
5896 drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5899 ? QTextCharFormat::SingleUnderline
5900 : QTextCharFormat::NoUnderline),
5901 flags, width.toReal(), QTextCharFormat());
5903 #endif // QT_NO_RAWFONT
5907 \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5911 Draws the \a staticText at the \a topLeftPosition.
5913 \note The y-position is used as the top of the font.
5918 \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5922 Draws the \a staticText at coordinates \a left and \a top.
5924 \note The y-position is used as the top of the font.
5928 \fn void QPainter::drawText(const QPointF &position, const QString &text)
5930 Draws the given \a text with the currently defined text direction,
5931 beginning at the given \a position.
5933 This function does not handle the newline character (\n), as it cannot
5934 break text into multiple lines, and it cannot display the newline character.
5935 Use the QPainter::drawText() overload that takes a rectangle instead
5936 if you want to draw multiple lines of text with the newline character, or
5937 if you want the text to be wrapped.
5939 By default, QPainter draws text anti-aliased.
5941 \note The y-position is used as the baseline of the font.
5944 void QPainter::drawText(const QPointF &p, const QString &str)
5946 drawText(p, str, 0, 0);
5952 Draws the given \a staticText at the given \a topLeftPosition.
5954 The text will be drawn using the font and the transformation set on the painter. If the
5955 font and/or transformation set on the painter are different from the ones used to initialize
5956 the layout of the QStaticText, then the layout will have to be recalculated. Use
5957 QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5958 it will later be drawn.
5960 If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5961 last drawn, then there will be a slight overhead when translating the text to its new position.
5963 \note If the painter's transformation is not affine, then \a staticText will be drawn using
5964 regular calls to drawText(), losing any potential for performance improvement.
5966 \note The y-position is used as the top of the font.
5970 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5973 if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5976 QStaticTextPrivate *staticText_d =
5977 const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5979 if (font() != staticText_d->font) {
5980 staticText_d->font = font();
5981 staticText_d->needsRelayout = true;
5984 // If we don't have an extended paint engine, or if the painter is projected,
5985 // we go through standard code path
5986 if (d->extended == 0 || !d->state->matrix.isAffine()) {
5987 staticText_d->paintText(topLeftPosition, this);
5991 bool paintEngineSupportsTransformations = qt_paintengine_supports_transformations(d->extended->type());
5992 if (paintEngineSupportsTransformations && !staticText_d->untransformedCoordinates) {
5993 staticText_d->untransformedCoordinates = true;
5994 staticText_d->needsRelayout = true;
5995 } else if (!paintEngineSupportsTransformations && staticText_d->untransformedCoordinates) {
5996 staticText_d->untransformedCoordinates = false;
5997 staticText_d->needsRelayout = true;
6000 // Don't recalculate entire layout because of translation, rather add the dx and dy
6001 // into the position to move each text item the correct distance.
6002 QPointF transformedPosition = topLeftPosition;
6003 if (!staticText_d->untransformedCoordinates)
6004 transformedPosition = transformedPosition * d->state->matrix;
6005 QTransform oldMatrix;
6007 // The translation has been applied to transformedPosition. Remove translation
6008 // component from matrix.
6009 if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
6010 qreal m11 = d->state->matrix.m11();
6011 qreal m12 = d->state->matrix.m12();
6012 qreal m13 = d->state->matrix.m13();
6013 qreal m21 = d->state->matrix.m21();
6014 qreal m22 = d->state->matrix.m22();
6015 qreal m23 = d->state->matrix.m23();
6016 qreal m33 = d->state->matrix.m33();
6018 oldMatrix = d->state->matrix;
6019 d->state->matrix.setMatrix(m11, m12, m13,
6024 // If the transform is not identical to the text transform,
6025 // we have to relayout the text (for other transformations than plain translation)
6026 bool staticTextNeedsReinit = staticText_d->needsRelayout;
6027 if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
6028 staticText_d->matrix = d->state->matrix;
6029 staticTextNeedsReinit = true;
6032 // Recreate the layout of the static text because the matrix or font has changed
6033 if (staticTextNeedsReinit)
6034 staticText_d->init();
6036 if (transformedPosition != staticText_d->position) { // Translate to actual position
6037 QFixed fx = QFixed::fromReal(transformedPosition.x());
6038 QFixed fy = QFixed::fromReal(transformedPosition.y());
6039 QFixed oldX = QFixed::fromReal(staticText_d->position.x());
6040 QFixed oldY = QFixed::fromReal(staticText_d->position.y());
6041 for (int item=0; item<staticText_d->itemCount;++item) {
6042 QStaticTextItem *textItem = staticText_d->items + item;
6043 for (int i=0; i<textItem->numGlyphs; ++i) {
6044 textItem->glyphPositions[i].x += fx - oldX;
6045 textItem->glyphPositions[i].y += fy - oldY;
6047 textItem->userDataNeedsUpdate = true;
6050 staticText_d->position = transformedPosition;
6053 QPen oldPen = d->state->pen;
6054 QColor currentColor = oldPen.color();
6055 for (int i=0; i<staticText_d->itemCount; ++i) {
6056 QStaticTextItem *item = staticText_d->items + i;
6057 if (item->color.isValid() && currentColor != item->color) {
6058 setPen(item->color);
6059 currentColor = item->color;
6061 d->extended->drawStaticTextItem(item);
6063 qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
6064 item->numGlyphs, item->fontEngine(), staticText_d->font,
6067 if (currentColor != oldPen.color())
6070 if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
6071 d->state->matrix = oldMatrix;
6077 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
6079 #ifdef QT_DEBUG_DRAW
6080 if (qt_show_painter_debug_output)
6081 printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
6086 if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
6089 if (tf & Qt::TextBypassShaping) {
6090 // Skip harfbuzz complex shaping, shape using glyph advances only
6091 int len = str.length();
6092 int numGlyphs = len;
6093 QVarLengthGlyphLayoutArray glyphs(len);
6094 QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
6095 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
6096 glyphs.resize(numGlyphs);
6097 if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
6098 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
6101 QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
6102 drawTextItem(p, gf);
6106 QStackTextEngine engine(str, d->state->font);
6107 engine.option.setTextDirection(d->state->layoutDirection);
6108 if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
6109 engine.ignoreBidi = true;
6110 engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
6114 line.length = str.length();
6115 engine.shapeLine(line);
6117 int nItems = engine.layoutData->items.size();
6118 QVarLengthArray<int> visualOrder(nItems);
6119 QVarLengthArray<uchar> levels(nItems);
6120 for (int i = 0; i < nItems; ++i)
6121 levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
6122 QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
6124 if (justificationPadding > 0) {
6125 engine.option.setAlignment(Qt::AlignJustify);
6126 engine.forceJustification = true;
6127 // this works because justify() is only interested in the difference between width and textWidth
6128 line.width = justificationPadding;
6129 engine.justify(line);
6131 QFixed x = QFixed::fromReal(p.x());
6133 for (int i = 0; i < nItems; ++i) {
6134 int item = visualOrder[i];
6135 const QScriptItem &si = engine.layoutData->items.at(item);
6136 if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
6140 QFont f = engine.font(si);
6141 QTextItemInt gf(si, &f);
6142 gf.glyphs = engine.shapedGlyphs(&si);
6143 gf.chars = engine.layoutData->string.unicode() + si.position;
6144 gf.num_chars = engine.length(item);
6145 if (engine.forceJustification) {
6146 for (int j=0; j<gf.glyphs.numGlyphs; ++j)
6147 gf.width += gf.glyphs.effectiveAdvance(j);
6149 gf.width = si.width;
6151 gf.logClusters = engine.logClusters(&si);
6153 drawTextItem(QPointF(x.toReal(), p.y()), gf);
6159 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
6161 #ifdef QT_DEBUG_DRAW
6162 if (qt_show_painter_debug_output)
6163 printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
6164 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6169 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6173 d->updateState(d->state);
6176 qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
6178 *br = bounds.toAlignedRect();
6182 \fn void QPainter::drawText(const QPoint &position, const QString &text)
6186 Draws the given \a text with the currently defined text direction,
6187 beginning at the given \a position.
6189 By default, QPainter draws text anti-aliased.
6191 \note The y-position is used as the baseline of the font.
6196 \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
6199 Draws the given \a text within the provided \a rectangle.
6203 \o \inlineimage qpainter-text.png
6205 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 17
6208 The \a boundingRect (if not null) is set to the what the bounding rectangle
6209 should be in order to enclose the whole text. The \a flags argument is a bitwise
6210 OR of the following flags:
6222 \o Qt::TextSingleLine
6223 \o Qt::TextExpandTabs
6224 \o Qt::TextShowMnemonic
6226 \o Qt::TextIncludeTrailingSpaces
6229 \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
6231 By default, QPainter draws text anti-aliased.
6233 \note The y-coordinate of \a rectangle is used as the top of the font.
6235 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
6237 #ifdef QT_DEBUG_DRAW
6238 if (qt_show_painter_debug_output)
6239 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
6240 r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
6245 if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
6249 d->updateState(d->state);
6251 qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
6255 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
6258 Draws the given \a text within the provided \a rectangle according
6259 to the specified \a flags. The \a boundingRect (if not null) is set to
6260 the what the bounding rectangle should be in order to enclose the whole text.
6262 By default, QPainter draws text anti-aliased.
6264 \note The y-coordinate of \a rectangle is used as the top of the font.
6268 \fn void QPainter::drawText(int x, int y, const QString &text)
6272 Draws the given \a text at position (\a{x}, \a{y}), using the painter's
6273 currently defined text direction.
6275 By default, QPainter draws text anti-aliased.
6277 \note The y-position is used as the baseline of the font.
6282 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6283 const QString &text, QRect *boundingRect)
6287 Draws the given \a text within the rectangle with origin (\a{x},
6288 \a{y}), \a width and \a height.
6290 The \a boundingRect (if not null) is set to the actual bounding
6291 rectangle of the output. The \a flags argument is a bitwise OR of
6292 the following flags:
6303 \o Qt::TextSingleLine
6304 \o Qt::TextExpandTabs
6305 \o Qt::TextShowMnemonic
6309 By default, QPainter draws text anti-aliased.
6311 \note The y-position is used as the top of the font.
6313 \sa Qt::AlignmentFlag, Qt::TextFlag
6317 \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6318 const QTextOption &option)
6321 Draws the given \a text in the \a rectangle specified using the \a option
6322 to control its positioning and orientation.
6324 By default, QPainter draws text anti-aliased.
6326 \note The y-coordinate of \a rectangle is used as the top of the font.
6328 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6330 #ifdef QT_DEBUG_DRAW
6331 if (qt_show_painter_debug_output)
6332 printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6333 r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6338 if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6342 d->updateState(d->state);
6344 qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6348 \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6355 \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6360 Draws the text item \a ti at position \a p.
6364 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6369 Draws the text item \a ti at position \a p.
6371 This method ignores the painters background mode and
6372 color. drawText and qt_format_text have to do it themselves, as
6373 only they know the extents of the complete string.
6375 It ignores the font set on the painter as the text item has one of its own.
6377 The underline and strikeout parameters of the text items font are
6378 ignored aswell. You'll need to pass in the correct flags to get
6379 underlining and strikeout.
6382 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6384 const qreal radiusBase = qMax(qreal(1), maxRadius);
6386 QString key = QLatin1Literal("WaveUnderline-")
6387 % pen.color().name()
6388 % HexString<qreal>(radiusBase);
6391 if (QPixmapCache::find(key, pixmap))
6394 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6395 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6396 const int radius = qFloor(radiusBase);
6403 while (xs < width) {
6406 path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6409 pixmap = QPixmap(width, radius * 2);
6410 pixmap.fill(Qt::transparent);
6413 wavePen.setCapStyle(Qt::SquareCap);
6415 // This is to protect against making the line too fat, as happens on Mac OS X
6416 // due to it having a rather thick width for the regular underline.
6417 const qreal maxPenWidth = .8 * radius;
6418 if (wavePen.widthF() > maxPenWidth)
6419 wavePen.setWidth(maxPenWidth);
6421 QPainter imgPainter(&pixmap);
6422 imgPainter.setPen(wavePen);
6423 imgPainter.setRenderHint(QPainter::Antialiasing);
6424 imgPainter.translate(0, radius);
6425 imgPainter.drawPath(path);
6428 QPixmapCache::insert(key, pixmap);
6433 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
6434 QTextCharFormat::UnderlineStyle underlineStyle,
6435 QTextItem::RenderFlags flags, qreal width,
6436 const QTextCharFormat &charFormat)
6438 if (underlineStyle == QTextCharFormat::NoUnderline
6439 && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6442 const QPen oldPen = painter->pen();
6443 const QBrush oldBrush = painter->brush();
6444 painter->setBrush(Qt::NoBrush);
6446 pen.setStyle(Qt::SolidLine);
6447 pen.setWidthF(fe->lineThickness().toReal());
6448 pen.setCapStyle(Qt::FlatCap);
6450 QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6452 const qreal underlineOffset = fe->underlinePosition().toReal();
6453 // deliberately ceil the offset to avoid the underline coming too close to
6454 // the text above it.
6455 const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
6456 const qreal underlinePos = pos.y() + qCeil(underlineOffset) - aliasedCoordinateDelta;
6458 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6459 underlineStyle = QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle));
6462 if (underlineStyle == QTextCharFormat::WaveUnderline) {
6464 painter->translate(0, pos.y() + 1);
6466 QColor uc = charFormat.underlineColor();
6470 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6471 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6472 const int descent = (int) fe->descent().toReal();
6474 painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6475 painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6477 } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6478 QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos);
6480 QColor uc = charFormat.underlineColor();
6484 pen.setStyle((Qt::PenStyle)(underlineStyle));
6485 painter->setPen(pen);
6486 painter->drawLine(underLine);
6489 pen.setStyle(Qt::SolidLine);
6490 pen.setColor(oldPen.color());
6492 if (flags & QTextItem::StrikeOut) {
6493 QLineF strikeOutLine = line;
6494 strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6495 painter->setPen(pen);
6496 painter->drawLine(strikeOutLine);
6499 if (flags & QTextItem::Overline) {
6500 QLineF overLine = line;
6501 overLine.translate(0., - fe->ascent().toReal());
6502 painter->setPen(pen);
6503 painter->drawLine(overLine);
6506 painter->setPen(oldPen);
6507 painter->setBrush(oldBrush);
6510 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6511 const QFixedPoint *positions, int glyphCount,
6512 QFontEngine *fontEngine, const QFont &font,
6513 const QTextCharFormat &charFormat)
6515 if (!(font.underline() || font.strikeOut() || font.overline()))
6521 for (int i=0; i<glyphCount; ++i) {
6522 glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6523 if (i == 0 || leftMost > positions[i].x)
6524 leftMost = positions[i].x;
6526 // We don't support glyphs that do not share a common baseline. If this turns out to
6527 // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6528 // and do a drawTextItemDecorations call per cluster.
6529 if (i == 0 || baseLine < positions[i].y)
6530 baseLine = positions[i].y;
6532 // We use the advance rather than the actual bounds to match the algorithm in drawText()
6533 if (i == 0 || rightMost < positions[i].x + gm.xoff)
6534 rightMost = positions[i].x + gm.xoff;
6537 QFixed width = rightMost - leftMost;
6538 QTextItem::RenderFlags flags = 0;
6540 if (font.underline())
6541 flags |= QTextItem::Underline;
6542 if (font.overline())
6543 flags |= QTextItem::Overline;
6544 if (font.strikeOut())
6545 flags |= QTextItem::StrikeOut;
6547 drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6549 font.underline() ? QTextCharFormat::SingleUnderline
6550 : QTextCharFormat::NoUnderline, flags,
6551 width.toReal(), charFormat);
6554 void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
6556 #ifdef QT_DEBUG_DRAW
6557 if (qt_show_painter_debug_output)
6558 printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6559 p.x(), p.y(), qPrintable(_ti.text()));
6568 qt_painter_thread_test(d->device->devType(),
6570 QFontDatabase::supportsThreadedFontRendering());
6573 QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6575 if (!d->extended && d->state->bgMode == Qt::OpaqueMode) {
6576 QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6577 fillRect(rect, d->state->bgBrush);
6580 if (pen().style() == Qt::NoPen)
6583 const RenderHints oldRenderHints = d->state->renderHints;
6584 if (!d->state->renderHints & QPainter::Antialiasing && d->state->matrix.type() >= QTransform::TxScale) {
6585 // draw antialias decoration (underline/overline/strikeout) with
6589 const QTransform &m = d->state->matrix;
6590 if (d->state->matrix.type() < QTransform::TxShear) {
6591 bool isPlain90DegreeRotation =
6592 (qFuzzyIsNull(m.m11())
6593 && qFuzzyIsNull(m.m12() - qreal(1))
6594 && qFuzzyIsNull(m.m21() + qreal(1))
6595 && qFuzzyIsNull(m.m22())
6598 (qFuzzyIsNull(m.m11() + qreal(1))
6599 && qFuzzyIsNull(m.m12())
6600 && qFuzzyIsNull(m.m21())
6601 && qFuzzyIsNull(m.m22() + qreal(1))
6604 (qFuzzyIsNull(m.m11())
6605 && qFuzzyIsNull(m.m12() + qreal(1))
6606 && qFuzzyIsNull(m.m21() - qreal(1))
6607 && qFuzzyIsNull(m.m22())
6610 aa = !isPlain90DegreeRotation;
6613 setRenderHint(QPainter::Antialiasing, true);
6617 d->updateState(d->state);
6619 if (!ti.glyphs.numGlyphs) {
6621 } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6622 QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6624 const QGlyphLayout &glyphs = ti.glyphs;
6625 int which = glyphs.glyphs[0] >> 24;
6632 for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6633 const int e = glyphs.glyphs[end] >> 24;
6638 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6640 // set the high byte to zero and calc the width
6641 for (i = start; i < end; ++i) {
6642 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6643 ti2.width += ti.glyphs.effectiveAdvance(i);
6646 d->engine->drawTextItem(QPointF(x, y), ti2);
6648 // reset the high byte for all glyphs and advance to the next sub-string
6649 const int hi = which << 24;
6650 for (i = start; i < end; ++i) {
6651 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6653 x += ti2.width.toReal();
6660 QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6662 // set the high byte to zero and calc the width
6663 for (i = start; i < end; ++i) {
6664 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6665 ti2.width += ti.glyphs.effectiveAdvance(i);
6669 d->extended->drawTextItem(QPointF(x, y), ti2);
6671 d->engine->drawTextItem(QPointF(x,y), ti2);
6673 // reset the high byte for all glyphs
6674 const int hi = which << 24;
6675 for (i = start; i < end; ++i)
6676 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6680 d->extended->drawTextItem(p, ti);
6682 d->engine->drawTextItem(p, ti);
6684 drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(),
6687 if (d->state->renderHints != oldRenderHints) {
6688 d->state->renderHints = oldRenderHints;
6690 d->extended->renderHintsChanged();
6692 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
6697 \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6699 Returns the bounding rectangle of the \a text as it will appear
6700 when drawn inside the given \a rectangle with the specified \a
6701 flags using the currently set font(); i.e the function tells you
6702 where the drawText() function will draw when given the same
6705 If the \a text does not fit within the given \a rectangle using
6706 the specified \a flags, the function returns the required
6709 The \a flags argument is a bitwise OR of the following flags:
6718 \o Qt::TextSingleLine
6719 \o Qt::TextExpandTabs
6720 \o Qt::TextShowMnemonic
6722 \o Qt::TextIncludeTrailingSpaces
6724 If several of the horizontal or several of the vertical alignment
6725 flags are set, the resulting alignment is undefined.
6727 \sa drawText(), Qt::Alignment, Qt::TextFlag
6731 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6732 const QString &text)
6736 Returns the bounding rectangle of the \a text as it will appear
6737 when drawn inside the given \a rectangle with the specified \a
6738 flags using the currently set font().
6742 \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6743 const QString &text);
6747 Returns the bounding rectangle of the given \a text as it will
6748 appear when drawn inside the rectangle beginning at the point
6749 (\a{x}, \a{y}) with width \a w and height \a h.
6751 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6754 return QRect(rect.x(),rect.y(), 0,0);
6756 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6762 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6765 return QRectF(rect.x(),rect.y(), 0,0);
6767 drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6772 \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6773 const QString &text, const QTextOption &option)
6777 Instead of specifying flags as a bitwise OR of the
6778 Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6779 an \a option argument. The QTextOption class provides a
6780 description of general rich text properties.
6784 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6788 if (!d->engine || text.length() == 0)
6789 return QRectF(r.x(),r.y(), 0,0);
6792 qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6797 \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6799 Draws a tiled \a pixmap, inside the given \a rectangle with its
6800 origin at the given \a position.
6802 Calling drawTiledPixmap() is similar to calling drawPixmap()
6803 several times to fill (tile) an area with a pixmap, but is
6804 potentially much more efficient depending on the underlying window
6809 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6811 #ifdef QT_DEBUG_DRAW
6812 if (qt_show_painter_debug_output)
6813 printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6814 r.x(), r.y(), r.width(), r.height(),
6815 pixmap.width(), pixmap.height(),
6820 if (!d->engine || pixmap.isNull() || r.isEmpty())
6824 qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6827 qreal sw = pixmap.width();
6828 qreal sh = pixmap.height();
6832 sx = qRound(sw) - qRound(-sx) % qRound(sw);
6834 sx = qRound(sx) % qRound(sw);
6836 sy = qRound(sh) - -qRound(sy) % qRound(sh);
6838 sy = qRound(sy) % qRound(sh);
6842 d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6846 if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6847 fillRect(r, d->state->bgBrush);
6849 d->updateState(d->state);
6850 if ((d->state->matrix.type() > QTransform::TxTranslate
6851 && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6852 || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6855 setBackgroundMode(Qt::TransparentMode);
6856 setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6857 setBrush(QBrush(d->state->pen.color(), pixmap));
6860 // If there is no rotation involved we have to make sure we use the
6861 // antialiased and not the aliased coordinate system by rounding the coordinates.
6862 if (d->state->matrix.type() <= QTransform::TxScale) {
6863 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6865 if (d->state->matrix.type() <= QTransform::TxTranslate) {
6870 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6871 drawRect(QRectF(p, r.size()));
6873 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6882 if (d->state->matrix.type() == QTransform::TxTranslate
6883 && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6884 x += d->state->matrix.dx();
6885 y += d->state->matrix.dy();
6888 d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6892 \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6893 const QPoint &position = QPoint())
6896 Draws a tiled \a pixmap, inside the given \a rectangle with its
6897 origin at the given \a position.
6901 \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6902 QPixmap &pixmap, int sx, int sy);
6905 Draws a tiled \a pixmap in the specified rectangle.
6907 (\a{x}, \a{y}) specifies the top-left point in the paint device
6908 that is to be drawn onto; with the given \a width and \a
6909 height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6910 pixmap that is to be drawn; this defaults to (0, 0).
6913 #ifndef QT_NO_PICTURE
6916 \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6918 Replays the given \a picture at the given \a point.
6920 The QPicture class is a paint device that records and replays
6921 QPainter commands. A picture serializes the painter commands to an
6922 IO device in a platform-independent format. Everything that can be
6923 painted on a widget or pixmap can also be stored in a picture.
6925 This function does exactly the same as QPicture::play() when
6926 called with \a point = QPoint(0, 0).
6931 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 18
6934 \sa QPicture::play()
6937 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6945 d->updateState(d->state);
6949 const_cast<QPicture *>(&picture)->play(this);
6954 \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6957 Replays the given \a picture at the given \a point.
6961 \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6964 Draws the given \a picture at point (\a x, \a y).
6967 #endif // QT_NO_PICTURE
6970 \fn void QPainter::eraseRect(const QRectF &rectangle)
6972 Erases the area inside the given \a rectangle. Equivalent to
6974 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 19
6978 void QPainter::eraseRect(const QRectF &r)
6982 fillRect(r, d->state->bgBrush);
6985 static inline bool needsResolving(const QBrush &brush)
6987 Qt::BrushStyle s = brush.style();
6988 return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
6989 s == Qt::ConicalGradientPattern) &&
6990 brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
6994 \fn void QPainter::eraseRect(const QRect &rectangle)
6997 Erases the area inside the given \a rectangle.
7001 \fn void QPainter::eraseRect(int x, int y, int width, int height)
7004 Erases the area inside the rectangle beginning at (\a x, \a y)
7005 with the given \a width and \a height.
7010 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
7013 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7014 width and \a height, using the brush \a style specified.
7020 \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
7023 Fills the given \a rectangle with the brush \a style specified.
7029 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
7032 Fills the given \a rectangle with the brush \a style specified.
7038 \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
7040 Fills the given \a rectangle with the \a brush specified.
7042 Alternatively, you can specify a QColor instead of a QBrush; the
7043 QBrush constructor (taking a QColor argument) will automatically
7044 create a solid pattern brush.
7048 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
7056 const QGradient *g = brush.gradient();
7057 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
7058 d->extended->fillRect(r, brush);
7063 QPen oldPen = pen();
7064 QBrush oldBrush = this->brush();
7066 if (brush.style() == Qt::SolidPattern) {
7067 d->colorBrush.setStyle(Qt::SolidPattern);
7068 d->colorBrush.setColor(brush.color());
7069 setBrush(d->colorBrush);
7080 \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
7083 Fills the given \a rectangle with the specified \a brush.
7086 void QPainter::fillRect(const QRect &r, const QBrush &brush)
7094 const QGradient *g = brush.gradient();
7095 if (!g || g->coordinateMode() == QGradient::LogicalMode) {
7096 d->extended->fillRect(r, brush);
7101 QPen oldPen = pen();
7102 QBrush oldBrush = this->brush();
7104 if (brush.style() == Qt::SolidPattern) {
7105 d->colorBrush.setStyle(Qt::SolidPattern);
7106 d->colorBrush.setColor(brush.color());
7107 setBrush(d->colorBrush);
7120 \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
7123 Fills the given \a rectangle with the \a color specified.
7127 void QPainter::fillRect(const QRect &r, const QColor &color)
7135 d->extended->fillRect(r, color);
7139 fillRect(r, QBrush(color));
7144 \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
7147 Fills the given \a rectangle with the \a color specified.
7151 void QPainter::fillRect(const QRectF &r, const QColor &color)
7159 d->extended->fillRect(r, color);
7163 fillRect(r, QBrush(color));
7167 \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
7171 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7172 width and \a height, using the given \a brush.
7176 \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
7180 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7181 width and \a height, using the given \a color.
7187 \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
7191 Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
7192 width and \a height, using the given \a color.
7198 \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
7202 Fills the given \a rectangle with the specified \a color.
7208 \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
7212 Fills the given \a rectangle with the specified \a color.
7218 Sets the given render \a hint on the painter if \a on is true;
7219 otherwise clears the render hint.
7221 \sa setRenderHints(), renderHints(), {QPainter#Rendering
7222 Quality}{Rendering Quality}
7224 void QPainter::setRenderHint(RenderHint hint, bool on)
7226 #ifdef QT_DEBUG_DRAW
7227 if (qt_show_painter_debug_output)
7228 printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
7232 static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
7233 if (hint == QPainter::Antialiasing && antialiasingDisabled)
7237 setRenderHints(hint, on);
7243 Sets the given render \a hints on the painter if \a on is true;
7244 otherwise clears the render hints.
7246 \sa setRenderHint(), renderHints(), {QPainter#Rendering
7247 Quality}{Rendering Quality}
7250 void QPainter::setRenderHints(RenderHints hints, bool on)
7255 qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7260 d->state->renderHints |= hints;
7262 d->state->renderHints &= ~hints;
7265 d->extended->renderHintsChanged();
7267 d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7271 Returns a flag that specifies the rendering hints that are set for
7274 \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7276 QPainter::RenderHints QPainter::renderHints() const
7278 Q_D(const QPainter);
7283 return d->state->renderHints;
7287 \fn bool QPainter::testRenderHint(RenderHint hint) const
7290 Returns true if \a hint is set; otherwise returns false.
7292 \sa renderHints(), setRenderHint()
7296 Returns true if view transformation is enabled; otherwise returns
7299 \sa setViewTransformEnabled(), worldTransform()
7302 bool QPainter::viewTransformEnabled() const
7304 Q_D(const QPainter);
7306 qWarning("QPainter::viewTransformEnabled: Painter not active");
7309 return d->state->VxF;
7313 \fn void QPainter::setWindow(const QRect &rectangle)
7315 Sets the painter's window to the given \a rectangle, and enables
7316 view transformations.
7318 The window rectangle is part of the view transformation. The
7319 window specifies the logical coordinate system. Its sister, the
7320 viewport(), specifies the device coordinate system.
7322 The default window rectangle is the same as the device's
7325 \sa window(), viewTransformEnabled(), {Coordinate
7326 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7330 \fn void QPainter::setWindow(int x, int y, int width, int height)
7333 Sets the painter's window to the rectangle beginning at (\a x, \a
7334 y) and the given \a width and \a height.
7337 void QPainter::setWindow(const QRect &r)
7339 #ifdef QT_DEBUG_DRAW
7340 if (qt_show_painter_debug_output)
7341 printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7347 qWarning("QPainter::setWindow: Painter not active");
7351 d->state->wx = r.x();
7352 d->state->wy = r.y();
7353 d->state->ww = r.width();
7354 d->state->wh = r.height();
7356 d->state->VxF = true;
7361 Returns the window rectangle.
7363 \sa setWindow(), setViewTransformEnabled()
7366 QRect QPainter::window() const
7368 Q_D(const QPainter);
7370 qWarning("QPainter::window: Painter not active");
7373 return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7377 \fn void QPainter::setViewport(const QRect &rectangle)
7379 Sets the painter's viewport rectangle to the given \a rectangle,
7380 and enables view transformations.
7382 The viewport rectangle is part of the view transformation. The
7383 viewport specifies the device coordinate system. Its sister, the
7384 window(), specifies the logical coordinate system.
7386 The default viewport rectangle is the same as the device's
7389 \sa viewport(), viewTransformEnabled() {Coordinate
7390 System#Window-Viewport Conversion}{Window-Viewport Conversion}
7394 \fn void QPainter::setViewport(int x, int y, int width, int height)
7397 Sets the painter's viewport rectangle to be the rectangle
7398 beginning at (\a x, \a y) with the given \a width and \a height.
7401 void QPainter::setViewport(const QRect &r)
7403 #ifdef QT_DEBUG_DRAW
7404 if (qt_show_painter_debug_output)
7405 printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7411 qWarning("QPainter::setViewport: Painter not active");
7415 d->state->vx = r.x();
7416 d->state->vy = r.y();
7417 d->state->vw = r.width();
7418 d->state->vh = r.height();
7420 d->state->VxF = true;
7425 Returns the viewport rectangle.
7427 \sa setViewport(), setViewTransformEnabled()
7430 QRect QPainter::viewport() const
7432 Q_D(const QPainter);
7434 qWarning("QPainter::viewport: Painter not active");
7437 return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7440 /*! \fn bool QPainter::hasViewXForm() const
7443 Use viewTransformEnabled() instead.
7446 /*! \fn bool QPainter::hasWorldXForm() const
7449 Use worldMatrixEnabled() instead.
7452 /*! \fn void QPainter::resetXForm()
7455 Use resetTransform() instead.
7458 /*! \fn void QPainter::setViewXForm(bool enabled)
7461 Use setViewTransformEnabled() instead.
7464 /*! \fn void QPainter::setWorldXForm(bool enabled)
7467 Use setWorldMatrixEnabled() instead.
7470 Enables view transformations if \a enable is true, or disables
7471 view transformations if \a enable is false.
7473 \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7474 Conversion}{Window-Viewport Conversion}
7477 void QPainter::setViewTransformEnabled(bool enable)
7479 #ifdef QT_DEBUG_DRAW
7480 if (qt_show_painter_debug_output)
7481 printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7487 qWarning("QPainter::setViewTransformEnabled: Painter not active");
7491 if (enable == d->state->VxF)
7494 d->state->VxF = enable;
7503 Use the worldTransform() combined with QTransform::dx() instead.
7506 QPainter painter(this);
7507 qreal x = painter.translationX();
7509 QPainter painter(this);
7510 qreal x = painter.worldTransform().dx();
7513 qreal QPainter::translationX() const
7515 Q_D(const QPainter);
7517 qWarning("QPainter::translationX: Painter not active");
7520 return d->state->worldMatrix.dx();
7526 Use the worldTransform() combined with QTransform::dy() instead.
7529 QPainter painter(this);
7530 qreal y = painter.translationY();
7532 QPainter painter(this);
7533 qreal y = painter.worldTransform().dy();
7536 qreal QPainter::translationY() const
7538 Q_D(const QPainter);
7540 qWarning("QPainter::translationY: Painter not active");
7543 return d->state->worldMatrix.dy();
7547 \fn void QPainter::map(int x, int y, int *rx, int *ry) const
7551 Sets (\a{rx}, \a{ry}) to the point that results from applying the
7552 painter's current transformation on the point (\a{x}, \a{y}).
7554 void QPainter::map(int x, int y, int *rx, int *ry) const
7557 p = p * combinedMatrix();
7563 \fn QPoint QPainter::xForm(const QPoint &point) const
7565 Use combinedTransform() instead.
7568 QPoint QPainter::xForm(const QPoint &p) const
7570 Q_D(const QPainter);
7572 qWarning("QPainter::xForm: Painter not active");
7575 if (d->state->matrix.type() == QTransform::TxNone)
7577 return p * combinedMatrix();
7582 \fn QRect QPainter::xForm(const QRect &rectangle) const
7585 Use combinedTransform() instead of this function and call
7586 mapRect() on the result to obtain a QRect.
7589 QRect QPainter::xForm(const QRect &r) const
7591 Q_D(const QPainter);
7593 qWarning("QPainter::xForm: Painter not active");
7596 if (d->state->matrix.type() == QTransform::TxNone)
7598 return combinedMatrix().mapRect(r);
7602 \fn QPolygon QPainter::xForm(const QPolygon &polygon) const
7605 Use combinedTransform() instead.
7608 QPolygon QPainter::xForm(const QPolygon &a) const
7610 Q_D(const QPainter);
7612 qWarning("QPainter::xForm: Painter not active");
7615 if (d->state->matrix.type() == QTransform::TxNone)
7617 return a * combinedMatrix();
7621 \fn QPolygon QPainter::xForm(const QPolygon &polygon, int index, int count) const
7624 Use combinedTransform() combined with QPolygon::mid() instead.
7627 QPainter painter(this);
7628 QPolygon transformed = painter.xForm(polygon, index, count)
7630 QPainter painter(this);
7631 QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform();
7635 QPolygon QPainter::xForm(const QPolygon &av, int index, int npoints) const
7637 int lastPoint = npoints < 0 ? av.size() : index+npoints;
7638 QPolygon a(lastPoint-index);
7639 memcpy(a.data(), av.data()+index, (lastPoint-index)*sizeof(QPoint));
7640 return a * combinedMatrix();
7644 \fn QPoint QPainter::xFormDev(const QPoint &point) const
7648 Use combinedTransform() combined with QTransform::inverted() instead.
7651 QPainter painter(this);
7652 QPoint transformed = painter.xFormDev(point);
7654 QPainter painter(this);
7655 QPoint transformed = point * painter.combinedTransform().inverted();
7659 QPoint QPainter::xFormDev(const QPoint &p) const
7661 Q_D(const QPainter);
7663 qWarning("QPainter::xFormDev: Painter not active");
7666 if(d->state->matrix.type() == QTransform::TxNone)
7668 return p * combinedMatrix().inverted();
7672 \fn QRect QPainter::xFormDev(const QRect &rectangle) const
7676 Use combinedTransform() combined with QTransform::inverted() instead.
7679 QPainter painter(this);
7680 QRect transformed = painter.xFormDev(rectangle);
7682 QPainter painter(this);
7683 QRegion region = QRegion(rectangle) * painter.combinedTransform().inverted();
7684 QRect transformed = region.boundingRect();
7688 QRect QPainter::xFormDev(const QRect &r) const
7690 Q_D(const QPainter);
7692 qWarning("QPainter::xFormDev: Painter not active");
7695 if (d->state->matrix.type() == QTransform::TxNone)
7697 return combinedMatrix().inverted().mapRect(r);
7703 \fn QPoint QPainter::xFormDev(const QPolygon &polygon) const
7706 Use combinedTransform() combined with QTransform::inverted() instead.
7709 QPainter painter(this);
7710 QPolygon transformed = painter.xFormDev(rectangle);
7712 QPainter painter(this);
7713 QPolygon transformed = polygon * painter.combinedTransform().inverted();
7717 QPolygon QPainter::xFormDev(const QPolygon &a) const
7719 Q_D(const QPainter);
7721 qWarning("QPainter::xFormDev: Painter not active");
7724 if (d->state->matrix.type() == QTransform::TxNone)
7726 return a * combinedMatrix().inverted();
7730 \fn QPolygon QPainter::xFormDev(const QPolygon &polygon, int index, int count) const
7734 Use combinedTransform() combined with QPolygon::mid() and QTransform::inverted() instead.
7737 QPainter painter(this);
7738 QPolygon transformed = painter.xFormDev(polygon, index, count);
7740 QPainter painter(this);
7741 QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform().inverted();
7745 QPolygon QPainter::xFormDev(const QPolygon &ad, int index, int npoints) const
7747 Q_D(const QPainter);
7748 int lastPoint = npoints < 0 ? ad.size() : index+npoints;
7749 QPolygon a(lastPoint-index);
7750 memcpy(a.data(), ad.data()+index, (lastPoint-index)*sizeof(QPoint));
7751 if (d->state->matrix.type() == QTransform::TxNone)
7753 return a * combinedMatrix().inverted();
7757 \fn void QPainter::drawCubicBezier(const QPolygon &controlPoints, int index)
7759 Draws a cubic Bezier curve defined by the \a controlPoints,
7760 starting at \a{controlPoints}\e{[index]} (\a index defaults to 0).
7761 Points after \a{controlPoints}\e{[index + 3]} are ignored. Nothing
7762 happens if there aren't enough control points.
7764 Use strokePath() instead.
7767 QPainter painter(this);
7768 painter.drawCubicBezier(controlPoints, index)
7771 path.moveTo(controlPoints.at(index));
7772 path.cubicTo(controlPoints.at(index+1),
7773 controlPoints.at(index+2),
7774 controlPoints.at(index+3));
7776 QPainter painter(this);
7777 painter.strokePath(path, painter.pen());
7780 void QPainter::drawCubicBezier(const QPolygon &a, int index)
7787 if ((int)a.size() - index < 4) {
7788 qWarning("QPainter::drawCubicBezier: Cubic Bezier needs 4 control "
7794 path.moveTo(a.at(index));
7795 path.cubicTo(a.at(index+1), a.at(index+2), a.at(index+3));
7796 strokePath(path, d->state->pen);
7800 struct QPaintDeviceRedirection
7802 QPaintDeviceRedirection() : device(0), replacement(0), internalWidgetRedirectionIndex(-1) {}
7803 QPaintDeviceRedirection(const QPaintDevice *device, QPaintDevice *replacement,
7804 const QPoint& offset, int internalWidgetRedirectionIndex)
7805 : device(device), replacement(replacement), offset(offset),
7806 internalWidgetRedirectionIndex(internalWidgetRedirectionIndex) { }
7807 const QPaintDevice *device;
7808 QPaintDevice *replacement;
7810 int internalWidgetRedirectionIndex;
7811 bool operator==(const QPaintDevice *pdev) const { return device == pdev; }
7812 Q_DUMMY_COMPARISON_OPERATOR(QPaintDeviceRedirection)
7815 typedef QList<QPaintDeviceRedirection> QPaintDeviceRedirectionList;
7816 Q_GLOBAL_STATIC(QPaintDeviceRedirectionList, globalRedirections)
7817 Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex)
7818 Q_GLOBAL_STATIC(QAtomicInt, globalRedirectionAtomic)
7825 Please use QWidget::render() instead.
7827 Redirects all paint commands for the given paint \a device, to the
7828 \a replacement device. The optional point \a offset defines an
7829 offset within the source device.
7831 The redirection will not be effective until the begin() function
7832 has been called; make sure to call end() for the given \a
7833 device's painter (if any) before redirecting. Call
7834 restoreRedirected() to restore the previous redirection.
7836 \warning Making use of redirections in the QPainter API implies
7837 that QPainter::begin() and QPaintDevice destructors need to hold
7838 a mutex for a short period. This can impact performance. Use of
7839 QWidget::render is strongly encouraged.
7841 \sa redirected(), restoreRedirected()
7843 void QPainter::setRedirected(const QPaintDevice *device,
7844 QPaintDevice *replacement,
7845 const QPoint &offset)
7847 Q_ASSERT(device != 0);
7849 bool hadInternalWidgetRedirection = false;
7850 if (device->devType() == QInternal::Widget) {
7851 const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
7852 // This is the case when the widget is in a paint event.
7853 if (widgetPrivate->redirectDev) {
7854 // Remove internal redirection and put it back into the global redirection list.
7856 QPaintDevice *oldReplacement = widgetPrivate->redirected(&oldOffset);
7857 const_cast<QWidgetPrivate *>(widgetPrivate)->restoreRedirected();
7858 setRedirected(device, oldReplacement, oldOffset);
7859 hadInternalWidgetRedirection = true;
7864 QPaintDevice *rdev = redirected(replacement, &roffset);
7866 QMutexLocker locker(globalRedirectionsMutex());
7867 QPaintDeviceRedirectionList *redirections = globalRedirections();
7868 Q_ASSERT(redirections != 0);
7869 *redirections += QPaintDeviceRedirection(device, rdev ? rdev : replacement, offset + roffset,
7870 hadInternalWidgetRedirection ? redirections->size() - 1 : -1);
7871 globalRedirectionAtomic()->ref();
7879 Using QWidget::render() obsoletes the use of this function.
7881 Restores the previous redirection for the given \a device after a
7882 call to setRedirected().
7884 \warning Making use of redirections in the QPainter API implies
7885 that QPainter::begin() and QPaintDevice destructors need to hold
7886 a mutex for a short period. This can impact performance. Use of
7887 QWidget::render is strongly encouraged.
7891 void QPainter::restoreRedirected(const QPaintDevice *device)
7893 Q_ASSERT(device != 0);
7894 QMutexLocker locker(globalRedirectionsMutex());
7895 QPaintDeviceRedirectionList *redirections = globalRedirections();
7896 Q_ASSERT(redirections != 0);
7897 for (int i = redirections->size()-1; i >= 0; --i) {
7898 if (redirections->at(i) == device) {
7899 globalRedirectionAtomic()->deref();
7900 const int internalWidgetRedirectionIndex = redirections->at(i).internalWidgetRedirectionIndex;
7901 redirections->removeAt(i);
7902 // Restore the internal widget redirection, i.e. remove it from the global
7903 // redirection list and put it back into QWidgetPrivate. The index is only set when
7904 // someone call QPainter::setRedirected in a widget's paint event and we internally
7905 // have a redirection set (typically set in QWidgetPrivate::drawWidget).
7906 if (internalWidgetRedirectionIndex >= 0) {
7907 Q_ASSERT(internalWidgetRedirectionIndex < redirections->size());
7908 const QPaintDeviceRedirection &redirectionDevice = redirections->at(internalWidgetRedirectionIndex);
7909 QWidget *widget = static_cast<QWidget *>(const_cast<QPaintDevice *>(device));
7910 widget->d_func()->setRedirected(redirectionDevice.replacement, redirectionDevice.offset);
7911 redirections->removeAt(internalWidgetRedirectionIndex);
7923 Using QWidget::render() obsoletes the use of this function.
7925 Returns the replacement for given \a device. The optional out
7926 parameter \a offset returns the offset within the replaced device.
7928 \warning Making use of redirections in the QPainter API implies
7929 that QPainter::begin() and QPaintDevice destructors need to hold
7930 a mutex for a short period. This can impact performance. Use of
7931 QWidget::render is strongly encouraged.
7933 \sa setRedirected(), restoreRedirected()
7935 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7937 Q_ASSERT(device != 0);
7939 if (device->devType() == QInternal::Widget) {
7940 const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
7941 if (widgetPrivate->redirectDev)
7942 return widgetPrivate->redirected(offset);
7945 if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
7948 QMutexLocker locker(globalRedirectionsMutex());
7949 QPaintDeviceRedirectionList *redirections = globalRedirections();
7950 Q_ASSERT(redirections != 0);
7951 for (int i = redirections->size()-1; i >= 0; --i)
7952 if (redirections->at(i) == device) {
7954 *offset = redirections->at(i).offset;
7955 return redirections->at(i).replacement;
7958 *offset = QPoint(0, 0);
7963 void qt_painter_removePaintDevice(QPaintDevice *dev)
7965 if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
7970 mutex = globalRedirectionsMutex();
7972 // ignore the missing mutex, since we could be called from
7973 // a destructor, and destructors shall not throw
7975 QMutexLocker locker(mutex);
7976 QPaintDeviceRedirectionList *redirections = 0;
7978 redirections = globalRedirections();
7980 // do nothing - code below is safe with redirections being 0.
7983 for (int i = 0; i < redirections->size(); ) {
7984 if(redirections->at(i) == dev || redirections->at(i).replacement == dev)
7985 redirections->removeAt(i);
7992 void qt_format_text(const QFont &fnt, const QRectF &_r,
7993 int tf, const QString& str, QRectF *brect,
7994 int tabstops, int *ta, int tabarraylen,
7997 qt_format_text(fnt, _r,
7999 tabstops, ta, tabarraylen,
8002 void qt_format_text(const QFont &fnt, const QRectF &_r,
8003 int tf, const QTextOption *option, const QString& str, QRectF *brect,
8004 int tabstops, int *ta, int tabarraylen,
8008 Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
8011 tf |= option->alignment();
8012 if (option->wrapMode() != QTextOption::NoWrap)
8013 tf |= Qt::TextWordWrap;
8015 if (option->flags() & QTextOption::IncludeTrailingSpaces)
8016 tf |= Qt::TextIncludeTrailingSpaces;
8018 if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
8019 tf |= Qt::TextExpandTabs;
8022 // we need to copy r here to protect against the case (&r == brect).
8025 bool dontclip = (tf & Qt::TextDontClip);
8026 bool wordwrap = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
8027 bool singleline = (tf & Qt::TextSingleLine);
8028 bool showmnemonic = (tf & Qt::TextShowMnemonic);
8029 bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
8031 Qt::LayoutDirection layout_direction;
8032 if (tf & Qt::TextForceLeftToRight)
8033 layout_direction = Qt::LeftToRight;
8034 else if (tf & Qt::TextForceRightToLeft)
8035 layout_direction = Qt::RightToLeft;
8037 layout_direction = option->textDirection();
8039 layout_direction = painter->layoutDirection();
8041 layout_direction = Qt::LeftToRight;
8043 tf = QStyle::visualAlignment(layout_direction, QFlag(tf));
8045 bool isRightToLeft = layout_direction == Qt::RightToLeft;
8046 bool expandtabs = ((tf & Qt::TextExpandTabs) &&
8047 (((tf & Qt::AlignLeft) && !isRightToLeft) ||
8048 ((tf & Qt::AlignRight) && isRightToLeft)));
8051 tf |= Qt::TextDontPrint;
8053 uint maxUnderlines = 0;
8054 int numUnderlines = 0;
8055 QVarLengthArray<int, 32> underlinePositions(1);
8057 QFontMetricsF fm(fnt);
8060 start_lengthVariant:
8061 bool hasMoreLengthVariants = false;
8062 // compatible behaviour to the old implementation. Replace
8064 int old_offset = offset;
8065 for (; offset < text.length(); offset++) {
8066 QChar chr = text.at(offset);
8067 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
8068 text[offset] = QLatin1Char(' ');
8069 } else if (chr == QLatin1Char('\n')) {
8070 text[offset] = QChar::LineSeparator;
8071 } else if (chr == QLatin1Char('&')) {
8073 } else if (chr == QLatin1Char('\t')) {
8075 text[offset] = QLatin1Char(' ');
8076 } else if (!tabarraylen && !tabstops) {
8077 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
8079 } else if (chr == QChar(ushort(0x9c))) {
8080 // string with multiple length variants
8081 hasMoreLengthVariants = true;
8086 int length = offset - old_offset;
8087 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
8088 underlinePositions.resize(maxUnderlines + 1);
8090 QChar *cout = text.data() + old_offset;
8094 if (*cin == QLatin1Char('&')) {
8100 if (*cin != QLatin1Char('&') && !hidemnmemonic)
8101 underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
8110 // no need to do extra work for underlines if we don't paint
8111 if (tf & Qt::TextDontPrint)
8114 underlinePositions[numUnderlines] = -1;
8118 QString finalText = text.mid(old_offset, length);
8119 QStackTextEngine engine(finalText, fnt);
8121 engine.option = *option;
8124 if (engine.option.tabStop() < 0 && tabstops > 0)
8125 engine.option.setTabStop(tabstops);
8127 if (engine.option.tabs().isEmpty() && ta) {
8129 for (int i = 0; i < tabarraylen; i++)
8130 tabs.append(qreal(ta[i]));
8131 engine.option.setTabArray(tabs);
8134 engine.option.setTextDirection(layout_direction);
8135 if (tf & Qt::AlignJustify)
8136 engine.option.setAlignment(Qt::AlignJustify);
8138 engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
8140 if (!option && (tf & Qt::TextWrapAnywhere))
8141 engine.option.setWrapMode(QTextOption::WrapAnywhere);
8143 if (tf & Qt::TextJustificationForced)
8144 engine.forceJustification = true;
8145 QTextLayout textLayout(&engine);
8146 textLayout.setCacheEnabled(true);
8147 textLayout.engine()->underlinePositions = underlinePositions.data();
8149 if (finalText.isEmpty()) {
8150 height = fm.height();
8152 tf |= Qt::TextDontPrint;
8154 qreal lineWidth = 0x01000000;
8155 if (wordwrap || (tf & Qt::TextJustificationForced))
8156 lineWidth = qMax<qreal>(0, r.width());
8158 tf |= Qt::TextIncludeTrailingSpaces;
8159 textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
8160 textLayout.beginLayout();
8162 qreal leading = fm.leading();
8166 QTextLine l = textLayout.createLine();
8170 l.setLineWidth(lineWidth);
8172 l.setPosition(QPointF(0., height));
8173 height += l.height();
8174 width = qMax(width, l.naturalTextWidth());
8175 if (!dontclip && !brect && height >= r.height())
8178 textLayout.endLayout();
8183 if (tf & Qt::AlignBottom) {
8184 yoff = r.height() - height;
8185 } else if (tf & Qt::AlignVCenter) {
8186 yoff = (r.height() - height)/2;
8188 QTransform::TransformationType type = painter->transform().type();
8189 if (type <= QTransform::TxScale) {
8190 // do the rounding manually to work around inconsistencies
8191 // in the paint engines when drawing on floating point offsets
8192 const qreal scale = painter->transform().m22();
8194 yoff = -qRound(-yoff * scale) / scale;
8198 if (tf & Qt::AlignRight) {
8199 xoff = r.width() - width;
8200 } else if (tf & Qt::AlignHCenter) {
8201 xoff = (r.width() - width)/2;
8203 QTransform::TransformationType type = painter->transform().type();
8204 if (type <= QTransform::TxScale) {
8205 // do the rounding manually to work around inconsistencies
8206 // in the paint engines when drawing on floating point offsets
8207 const qreal scale = painter->transform().m11();
8209 xoff = qRound(xoff * scale) / scale;
8213 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
8215 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
8217 goto start_lengthVariant;
8222 if (!(tf & Qt::TextDontPrint)) {
8223 bool restore = false;
8224 if (!dontclip && !r.contains(bounds)) {
8227 painter->setClipRect(r, Qt::IntersectClip);
8230 for (int i = 0; i < textLayout.lineCount(); i++) {
8231 QTextLine line = textLayout.lineAt(i);
8233 qreal advance = line.horizontalAdvance();
8235 if (tf & Qt::AlignRight) {
8236 QTextEngine *eng = textLayout.engine();
8237 xoff = r.width() - advance -
8238 eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
8240 else if (tf & Qt::AlignHCenter)
8241 xoff = (r.width() - advance) / 2;
8243 line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
8253 Sets the layout direction used by the painter when drawing text,
8254 to the specified \a direction.
8256 The default is Qt::LayoutDirectionAuto, which will implicitly determine the
8257 direction from the text drawn.
8259 \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
8261 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
8265 d->state->layoutDirection = direction;
8269 Returns the layout direction used by the painter when drawing text.
8271 \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
8273 Qt::LayoutDirection QPainter::layoutDirection() const
8275 Q_D(const QPainter);
8276 return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
8279 QPainterState::QPainterState(const QPainterState *s)
8280 : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
8281 pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
8282 clipRegion(s->clipRegion), clipPath(s->clipPath),
8283 clipOperation(s->clipOperation),
8284 renderHints(s->renderHints), clipInfo(s->clipInfo),
8285 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
8286 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
8287 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
8288 opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
8289 clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
8290 layoutDirection(s->layoutDirection),
8291 composition_mode(s->composition_mode),
8292 emulationSpecifier(s->emulationSpecifier), changeFlags(0)
8294 dirtyFlags = s->dirtyFlags;
8297 QPainterState::QPainterState()
8298 : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
8300 wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
8301 opacity(1), WxF(false), VxF(false), clipEnabled(true),
8302 bgMode(Qt::TransparentMode), painter(0),
8303 layoutDirection(QApplication::layoutDirection()),
8304 composition_mode(QPainter::CompositionMode_SourceOver),
8305 emulationSpecifier(0), changeFlags(0)
8310 QPainterState::~QPainterState()
8314 void QPainterState::init(QPainter *p) {
8315 bgBrush = Qt::white;
8316 bgMode = Qt::TransparentMode;
8320 wx = wy = ww = wh = 0;
8321 vx = vy = vw = vh = 0;
8324 brushOrigin = QPointF(0, 0);
8326 font = deviceFont = QFont();
8327 clipRegion = QRegion();
8328 clipPath = QPainterPath();
8329 clipOperation = Qt::NoClip;
8331 worldMatrix.reset();
8333 layoutDirection = QApplication::layoutDirection();
8334 composition_mode = QPainter::CompositionMode_SourceOver;
8335 emulationSpecifier = 0;
8343 static void bitBlt_helper(QPaintDevice *dst, const QPoint &dp,
8344 const QPaintDevice *src, const QRect &sr, bool)
8349 if (src->devType() == QInternal::Pixmap) {
8350 const QPixmap *pixmap = static_cast<const QPixmap *>(src);
8352 pt.drawPixmap(dp, *pixmap, sr);
8355 qWarning("QPainter: bitBlt only works when source is of type pixmap");
8359 void bitBlt(QPaintDevice *dst, int dx, int dy,
8360 const QPaintDevice *src, int sx, int sy, int sw, int sh,
8363 bitBlt_helper(dst, QPoint(dx, dy), src, QRect(sx, sy, sw, sh), ignoreMask);
8366 void bitBlt(QPaintDevice *dst, const QPoint &dp, const QPaintDevice *src, const QRect &sr, bool ignoreMask)
8368 bitBlt_helper(dst, dp, src, sr, ignoreMask);
8371 void bitBlt(QPaintDevice *dst, int dx, int dy,
8372 const QImage *src, int sx, int sy, int sw, int sh, int fl)
8374 Qt::ImageConversionFlags flags(fl);
8375 QPixmap srcPixmap = QPixmap::fromImage(*src, flags);
8376 bitBlt_helper(dst, QPoint(dx, dy), &srcPixmap, QRect(sx, sy, sw, sh), false);
8379 #endif // QT3_SUPPORT
8382 \fn void QPainter::setBackgroundColor(const QColor &color)
8384 Use setBackground() instead.
8388 \fn const QColor &QPainter::backgroundColor() const
8390 Use background() and QBrush::color() instead.
8393 QColor myColor = backgroundColor();
8395 QColor myColor = background().color();
8398 Note that the background can be a complex brush such as a texture
8403 \fn void QPainter::drawText(int x, int y, const QString &text, int pos, int length)
8406 Use drawText() combined with QString::mid() instead.
8409 QPainter painter(this);
8410 painter.drawText(x, y, text, pos, length);
8412 QPainter painter(this);
8413 painter.drawText(x, y, text.mid(pos, length));
8418 \fn void QPainter::drawText(const QPoint &point, const QString &text, int pos, int length)
8421 Use drawText() combined with QString::mid() instead.
8424 QPainter painter(this);
8425 painter.drawText(point, text, pos, length);
8427 QPainter painter(this);
8428 painter.drawText(point, text.mid(pos, length));
8433 \fn void QPainter::drawText(int x, int y, const QString &text, int length)
8436 Use drawText() combined with QString::left() instead.
8439 QPainter painter(this);
8440 painter.drawText(x, y, text, length);
8442 QPainter painter(this);
8443 painter.drawText(x, y, text.left(length));
8448 \fn void QPainter::drawText(const QPoint &point, const QString &text, int length)
8451 Use drawText() combined with QString::left() instead.
8454 QPainter painter(this);
8455 painter.drawText(point, text, length);
8457 QPainter painter(this);
8458 painter.drawText(point, text.left(length));
8463 \fn bool QPainter::begin(QPaintDevice *device, const QWidget *init)
8466 Use begin() instead.
8468 If the paint \a device is a QWidget, QPainter is initialized after
8469 the widget's settings automatically. Otherwise, you must call the
8470 initFrom() function to initialize the painters pen, background and
8471 font to the same as any given widget.
8474 QPainter painter(this);
8475 painter.begin(device, init);
8477 QPainter painter(this);
8478 painter.begin(device);
8479 painter.initFrom(init);
8484 \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
8485 Qt::ImageConversionFlags flags)
8487 Draws the rectangular portion \a source of the given \a image
8488 into the \a target rectangle in the paint device.
8490 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8492 If the image needs to be modified to fit in a lower-resolution
8493 result (e.g. converting from 32-bit to 8-bit), use the \a flags to
8494 specify how you would prefer this to happen.
8499 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 20
8506 \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
8507 Qt::ImageConversionFlags flags)
8510 Draws the rectangular portion \a source of the given \a image
8511 into the \a target rectangle in the paint device.
8513 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8517 \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
8521 Draws the given \a image at the given \a point.
8525 \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
8529 Draws the given \a image at the given \a point.
8533 \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
8534 Qt::ImageConversionFlags flags = 0)
8538 Draws the rectangular portion \a source of the given \a image with
8539 its origin at the given \a point.
8543 \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
8544 Qt::ImageConversionFlags flags = 0)
8547 Draws the rectangular portion \a source of the given \a image with
8548 its origin at the given \a point.
8552 \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
8556 Draws the given \a image into the given \a rectangle.
8558 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8562 \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
8566 Draws the given \a image into the given \a rectangle.
8568 \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
8572 \fn void QPainter::drawImage(int x, int y, const QImage &image,
8573 int sx, int sy, int sw, int sh,
8574 Qt::ImageConversionFlags flags)
8577 Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
8580 (\a{x}, \a{y}) specifies the top-left point in the paint device that is
8581 to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
8582 image that is to be drawn. The default is (0, 0).
8584 (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
8585 The default, (0, 0) (and negative) means all the way to the
8586 bottom-right of the image.
8590 \fn void QPainter::redirect(QPaintDevice *pdev, QPaintDevice *replacement)
8592 Use setRedirected() instead.
8596 \fn QPaintDevice *QPainter::redirect(QPaintDevice *pdev)
8598 Use redirected() instead.
8602 \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
8603 const QString &text, int length)
8606 Returns the bounding rectangle for the given \a length of the \a
8607 text constrained by the provided \a rectangle.
8609 Use boundingRect() combined with QString::left() instead.
8612 QRect rectangle = boundingRect(rect, flags, text, length);
8614 QRect rectangle = boundingRect(rect, flags, text.left(length));
8619 \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text,
8620 int length, QRect *br)
8623 Use drawText() combined with QString::left() instead.
8626 QPainter painter(this);
8627 painter.drawText(rectangle, flags, text, length, br );
8629 QPainter painter(this);
8630 painter.drawText(rectangle, flags, text.left(length), br );
8635 \fn QRect QPainter::boundingRect(int x, int y, int width, int height, int flags,
8636 const QString &text, int length);
8640 Returns the bounding rectangle for the given \a length of the \a
8641 text constrained by the rectangle that begins at point (\a{x},
8642 \a{y}) with the given \a width and \a height.
8644 Use boundingRect() combined with QString::left() instead.
8647 QRect rectangle = boundingRect(x, y, width, height, flags, text, length);
8649 QRect rectangle = boundingRect(x, y, width, height, flags, text.left(length));
8654 \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
8655 const QString &text, int length, QRect *br)
8659 Use drawText() combined with QString::left() instead.
8662 QPainter painter(this);
8663 painter.drawText(x, y, width, height, flags, text, length, br );
8665 QPainter painter(this);
8666 painter.drawText(x, y, width, height, flags, text.left(length), br );
8672 \class QPaintEngineState
8675 \brief The QPaintEngineState class provides information about the
8676 active paint engine's current state.
8679 QPaintEngineState records which properties that have changed since
8680 the last time the paint engine was updated, as well as their
8683 Which properties that have changed can at any time be retrieved
8684 using the state() function. This function returns an instance of
8685 the QPaintEngine::DirtyFlags type which stores an OR combination
8686 of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
8687 enum defines whether a property has changed since the last update
8690 If a property is marked with a dirty flag, its current value can
8691 be retrieved using the corresponding get function:
8696 \header \o Property Flag \o Current Property Value
8697 \row \o QPaintEngine::DirtyBackground \o backgroundBrush()
8698 \row \o QPaintEngine::DirtyBackgroundMode \o backgroundMode()
8699 \row \o QPaintEngine::DirtyBrush \o brush()
8700 \row \o QPaintEngine::DirtyBrushOrigin \o brushOrigin()
8701 \row \o QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
8703 \row \o QPaintEngine::DirtyClipPath \o clipPath()
8704 \row \o QPaintEngine::DirtyClipRegion \o clipRegion()
8705 \row \o QPaintEngine::DirtyCompositionMode \o compositionMode()
8706 \row \o QPaintEngine::DirtyFont \o font()
8707 \row \o QPaintEngine::DirtyTransform \o transform()
8708 \row \o QPaintEngine::DirtyClipEnabled \o isClipEnabled()
8709 \row \o QPaintEngine::DirtyPen \o pen()
8710 \row \o QPaintEngine::DirtyHints \o renderHints()
8713 The QPaintEngineState class also provide the painter() function
8714 which returns a pointer to the painter that is currently updating
8717 An instance of this class, representing the current state of the
8718 active paint engine, is passed as argument to the
8719 QPaintEngine::updateState() function. The only situation in which
8720 you will have to use this class directly is when implementing your
8728 \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
8730 Returns a combination of flags identifying the set of properties
8731 that need to be updated when updating the paint engine's state
8732 (i.e. during a call to the QPaintEngine::updateState() function).
8734 \sa QPaintEngine::updateState()
8739 Returns the pen in the current paint engine state.
8741 This variable should only be used when the state() returns a
8742 combination which includes the QPaintEngine::DirtyPen flag.
8744 \sa state(), QPaintEngine::updateState()
8747 QPen QPaintEngineState::pen() const
8749 return static_cast<const QPainterState *>(this)->pen;
8753 Returns the brush in the current paint engine state.
8755 This variable should only be used when the state() returns a
8756 combination which includes the QPaintEngine::DirtyBrush flag.
8758 \sa state(), QPaintEngine::updateState()
8761 QBrush QPaintEngineState::brush() const
8763 return static_cast<const QPainterState *>(this)->brush;
8767 Returns the brush origin in the current paint engine state.
8769 This variable should only be used when the state() returns a
8770 combination which includes the QPaintEngine::DirtyBrushOrigin flag.
8772 \sa state(), QPaintEngine::updateState()
8775 QPointF QPaintEngineState::brushOrigin() const
8777 return static_cast<const QPainterState *>(this)->brushOrigin;
8781 Returns the background brush in the current paint engine state.
8783 This variable should only be used when the state() returns a
8784 combination which includes the QPaintEngine::DirtyBackground flag.
8786 \sa state(), QPaintEngine::updateState()
8789 QBrush QPaintEngineState::backgroundBrush() const
8791 return static_cast<const QPainterState *>(this)->bgBrush;
8795 Returns the background mode in the current paint engine
8798 This variable should only be used when the state() returns a
8799 combination which includes the QPaintEngine::DirtyBackgroundMode flag.
8801 \sa state(), QPaintEngine::updateState()
8804 Qt::BGMode QPaintEngineState::backgroundMode() const
8806 return static_cast<const QPainterState *>(this)->bgMode;
8810 Returns the font in the current paint engine
8813 This variable should only be used when the state() returns a
8814 combination which includes the QPaintEngine::DirtyFont flag.
8816 \sa state(), QPaintEngine::updateState()
8819 QFont QPaintEngineState::font() const
8821 return static_cast<const QPainterState *>(this)->font;
8828 Returns the matrix in the current paint engine
8831 \note It is advisable to use transform() instead of this function to
8832 preserve the properties of perspective transformations.
8834 This variable should only be used when the state() returns a
8835 combination which includes the QPaintEngine::DirtyTransform flag.
8837 \sa state(), QPaintEngine::updateState()
8840 QMatrix QPaintEngineState::matrix() const
8842 const QPainterState *st = static_cast<const QPainterState *>(this);
8844 return st->matrix.toAffine();
8850 Returns the matrix in the current paint engine state.
8852 This variable should only be used when the state() returns a
8853 combination which includes the QPaintEngine::DirtyTransform flag.
8855 \sa state(), QPaintEngine::updateState()
8859 QTransform QPaintEngineState::transform() const
8861 const QPainterState *st = static_cast<const QPainterState *>(this);
8868 Returns the clip operation in the current paint engine
8871 This variable should only be used when the state() returns a
8872 combination which includes either the QPaintEngine::DirtyClipPath
8873 or the QPaintEngine::DirtyClipRegion flag.
8875 \sa state(), QPaintEngine::updateState()
8878 Qt::ClipOperation QPaintEngineState::clipOperation() const
8880 return static_cast<const QPainterState *>(this)->clipOperation;
8886 Returns whether the coordinate of the fill have been specified
8887 as bounded by the current rendering operation and have to be
8888 resolved (about the currently rendered primitive).
8890 bool QPaintEngineState::brushNeedsResolving() const
8892 const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
8893 return needsResolving(brush);
8900 Returns whether the coordinate of the stroke have been specified
8901 as bounded by the current rendering operation and have to be
8902 resolved (about the currently rendered primitive).
8904 bool QPaintEngineState::penNeedsResolving() const
8906 const QPen &pen = static_cast<const QPainterState *>(this)->pen;
8907 return needsResolving(pen.brush());
8911 Returns the clip region in the current paint engine state.
8913 This variable should only be used when the state() returns a
8914 combination which includes the QPaintEngine::DirtyClipRegion flag.
8916 \sa state(), QPaintEngine::updateState()
8919 QRegion QPaintEngineState::clipRegion() const
8921 return static_cast<const QPainterState *>(this)->clipRegion;
8925 Returns the clip path in the current paint engine state.
8927 This variable should only be used when the state() returns a
8928 combination which includes the QPaintEngine::DirtyClipPath flag.
8930 \sa state(), QPaintEngine::updateState()
8933 QPainterPath QPaintEngineState::clipPath() const
8935 return static_cast<const QPainterState *>(this)->clipPath;
8939 Returns whether clipping is enabled or not in the current paint
8942 This variable should only be used when the state() returns a
8943 combination which includes the QPaintEngine::DirtyClipEnabled
8946 \sa state(), QPaintEngine::updateState()
8949 bool QPaintEngineState::isClipEnabled() const
8951 return static_cast<const QPainterState *>(this)->clipEnabled;
8955 Returns the render hints in the current paint engine state.
8957 This variable should only be used when the state() returns a
8958 combination which includes the QPaintEngine::DirtyHints
8961 \sa state(), QPaintEngine::updateState()
8964 QPainter::RenderHints QPaintEngineState::renderHints() const
8966 return static_cast<const QPainterState *>(this)->renderHints;
8970 Returns the composition mode in the current paint engine state.
8972 This variable should only be used when the state() returns a
8973 combination which includes the QPaintEngine::DirtyCompositionMode
8976 \sa state(), QPaintEngine::updateState()
8979 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8981 return static_cast<const QPainterState *>(this)->composition_mode;
8986 Returns a pointer to the painter currently updating the paint
8990 QPainter *QPaintEngineState::painter() const
8992 return static_cast<const QPainterState *>(this)->painter;
8999 Returns the opacity in the current paint engine state.
9002 qreal QPaintEngineState::opacity() const
9004 return static_cast<const QPainterState *>(this)->opacity;
9010 Sets the world transformation matrix.
9011 If \a combine is true, the specified \a transform is combined with
9012 the current matrix; otherwise it replaces the current matrix.
9014 \sa transform() setWorldTransform()
9017 void QPainter::setTransform(const QTransform &transform, bool combine )
9019 setWorldTransform(transform, combine);
9023 Returns the world transformation matrix.
9025 \sa worldTransform()
9028 const QTransform & QPainter::transform() const
9030 return worldTransform();
9035 Returns the matrix that transforms from logical coordinates to
9036 device coordinates of the platform dependent paint device.
9038 This function is \e only needed when using platform painting
9039 commands on the platform dependent handle (Qt::HANDLE), and the
9040 platform does not do transformations nativly.
9042 The QPaintEngine::PaintEngineFeature enum can be queried to
9043 determine whether the platform performs the transformations or
9046 \sa worldTransform(), QPaintEngine::hasFeature(),
9049 const QTransform & QPainter::deviceTransform() const
9051 Q_D(const QPainter);
9053 qWarning("QPainter::deviceTransform: Painter not active");
9054 return d->fakeState()->transform;
9056 return d->state->matrix;
9061 Resets any transformations that were made using translate(),
9062 scale(), shear(), rotate(), setWorldTransform(), setViewport()
9065 \sa {Coordinate Transformations}
9068 void QPainter::resetTransform()
9071 #ifdef QT_DEBUG_DRAW
9072 if (qt_show_painter_debug_output)
9073 printf("QPainter::resetMatrix()\n");
9076 qWarning("QPainter::resetMatrix: Painter not active");
9080 d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0; // default view origins
9081 d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
9082 d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
9083 d->state->worldMatrix = QTransform();
9084 setMatrixEnabled(false);
9085 setViewTransformEnabled(false);
9087 d->extended->transformChanged();
9089 d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
9093 Sets the world transformation matrix.
9094 If \a combine is true, the specified \a matrix is combined with the current matrix;
9095 otherwise it replaces the current matrix.
9097 \sa transform(), setTransform()
9100 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
9105 qWarning("QPainter::setWorldTransform: Painter not active");
9110 d->state->worldMatrix = matrix * d->state->worldMatrix; // combines
9112 d->state->worldMatrix = matrix; // set new matrix
9114 d->state->WxF = true;
9119 Returns the world transformation matrix.
9122 const QTransform & QPainter::worldTransform() const
9124 Q_D(const QPainter);
9126 qWarning("QPainter::worldTransform: Painter not active");
9127 return d->fakeState()->transform;
9129 return d->state->worldMatrix;
9133 Returns the transformation matrix combining the current
9134 window/viewport and world transformation.
9136 \sa setWorldTransform(), setWindow(), setViewport()
9139 QTransform QPainter::combinedTransform() const
9141 Q_D(const QPainter);
9143 qWarning("QPainter::combinedTransform: Painter not active");
9144 return QTransform();
9146 return d->state->worldMatrix * d->viewTransform();
9152 This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
9153 at multiple positions with different scale, rotation and opacity. \a
9154 fragments is an array of \a fragmentCount elements specifying the
9155 parameters used to draw each pixmap fragment. The \a hints
9156 parameter can be used to pass in drawing hints.
9158 This function is potentially faster than multiple calls to drawPixmap(),
9159 since the backend can optimize state changes.
9161 \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
9164 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
9165 const QPixmap &pixmap, PixmapFragmentHints hints)
9169 if (!d->engine || pixmap.isNull())
9173 for (int i = 0; i < fragmentCount; ++i) {
9174 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
9175 fragments[i].width, fragments[i].height);
9176 if (!(QRectF(pixmap.rect()).contains(sourceRect)))
9177 qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
9181 if (d->engine->isExtended()) {
9182 d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
9184 qreal oldOpacity = opacity();
9185 QTransform oldTransform = transform();
9187 for (int i = 0; i < fragmentCount; ++i) {
9188 QTransform transform = oldTransform;
9191 if (fragments[i].rotation == 0) {
9192 xOffset = fragments[i].x;
9193 yOffset = fragments[i].y;
9195 transform.translate(fragments[i].x, fragments[i].y);
9196 transform.rotate(fragments[i].rotation);
9198 setOpacity(oldOpacity * fragments[i].opacity);
9199 setTransform(transform);
9201 qreal w = fragments[i].scaleX * fragments[i].width;
9202 qreal h = fragments[i].scaleY * fragments[i].height;
9203 QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
9204 fragments[i].width, fragments[i].height);
9205 drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
9208 setOpacity(oldOpacity);
9209 setTransform(oldTransform);
9215 \class QPainter::PixmapFragment
9217 \brief This class is used in conjunction with the
9218 QPainter::drawPixmapFragments() function to specify how a pixmap, or
9219 sub-rect of a pixmap, is drawn.
9221 The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
9222 as a source rectangle within the pixmap passed into the
9223 QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
9224 width and \a height are used to calculate the target rectangle that is
9225 drawn. \a x and \a y denotes the center of the target rectangle. The \a
9226 width and \a height in the target rectangle is scaled by the \a scaleX and
9227 \a scaleY values. The resulting target rectangle is then rotated \a
9228 rotation degrees around the \a x, \a y center point.
9230 \sa QPainter::drawPixmapFragments()
9236 This is a convenience function that returns a QPainter::PixmapFragment that is
9237 initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
9238 rotation, \a opacity parameters.
9241 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
9242 qreal scaleX, qreal scaleY, qreal rotation,
9245 PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
9246 sourceRect.height(), scaleX, scaleY, rotation, opacity};
9251 \variable QPainter::PixmapFragment::x
9252 \brief the x coordinate of center point in the target rectangle.
9256 \variable QPainter::PixmapFragment::y
9257 \brief the y coordinate of the center point in the target rectangle.
9261 \variable QPainter::PixmapFragment::sourceLeft
9262 \brief the left coordinate of the source rectangle.
9266 \variable QPainter::PixmapFragment::sourceTop
9267 \brief the top coordinate of the source rectangle.
9271 \variable QPainter::PixmapFragment::width
9273 \brief the width of the source rectangle and is used to calculate the width
9274 of the target rectangle.
9278 \variable QPainter::PixmapFragment::height
9280 \brief the height of the source rectangle and is used to calculate the
9281 height of the target rectangle.
9285 \variable QPainter::PixmapFragment::scaleX
9286 \brief the horizontal scale of the target rectangle.
9290 \variable QPainter::PixmapFragment::scaleY
9291 \brief the vertical scale of the target rectangle.
9295 \variable QPainter::PixmapFragment::rotation
9297 \brief the rotation of the target rectangle in degrees. The target
9298 rectangle is rotated after it has been scaled.
9302 \variable QPainter::PixmapFragment::opacity
9304 \brief the opacity of the target rectangle, where 0.0 is fully transparent
9305 and 1.0 is fully opaque.
9311 \enum QPainter::PixmapFragmentHint
9313 \value OpaqueHint Indicates that the pixmap fragments to be drawn are
9314 opaque. Opaque fragments are potentially faster to draw.
9316 \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
9319 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
9321 p->draw_helper(path, operation);
9324 /*! \fn Display *QPaintDevice::x11Display() const
9325 Use QX11Info::display() instead.
9328 Display *display = widget->x11Display();
9330 Display *display = QX11Info::display();
9333 \sa QWidget::x11Info(), QX11Info::display()
9336 /*! \fn int QPaintDevice::x11Screen() const
9337 Use QX11Info::screen() instead.
9340 int screen = widget->x11Screen();
9342 int screen = widget->x11Info().screen();
9345 \sa QWidget::x11Info(), QPixmap::x11Info()
9348 /*! \fn void *QPaintDevice::x11Visual() const
9349 Use QX11Info::visual() instead.
9352 void *visual = widget->x11Visual();
9354 void *visual = widget->x11Info().visual();
9357 \sa QWidget::x11Info(), QPixmap::x11Info()
9360 /*! \fn int QPaintDevice::x11Depth() const
9361 Use QX11Info::depth() instead.
9364 int depth = widget->x11Depth();
9366 int depth = widget->x11Info().depth();
9369 \sa QWidget::x11Info(), QPixmap::x11Info()
9372 /*! \fn int QPaintDevice::x11Cells() const
9373 Use QX11Info::cells() instead.
9376 int cells = widget->x11Cells();
9378 int cells = widget->x11Info().cells();
9381 \sa QWidget::x11Info(), QPixmap::x11Info()
9384 /*! \fn Qt::HANDLE QPaintDevice::x11Colormap() const
9385 Use QX11Info::colormap() instead.
9388 unsigned long screen = widget->x11Colormap();
9390 unsigned long screen = widget->x11Info().colormap();
9393 \sa QWidget::x11Info(), QPixmap::x11Info()
9396 /*! \fn bool QPaintDevice::x11DefaultColormap() const
9397 Use QX11Info::defaultColormap() instead.
9400 bool isDefault = widget->x11DefaultColormap();
9402 bool isDefault = widget->x11Info().defaultColormap();
9405 \sa QWidget::x11Info(), QPixmap::x11Info()
9408 /*! \fn bool QPaintDevice::x11DefaultVisual() const
9409 Use QX11Info::defaultVisual() instead.
9412 bool isDefault = widget->x11DefaultVisual();
9414 bool isDefault = widget->x11Info().defaultVisual();
9417 \sa QWidget::x11Info(), QPixmap::x11Info()
9420 /*! \fn void *QPaintDevice::x11AppVisual(int screen)
9421 Use QX11Info::visual() instead.
9424 void *visual = QPaintDevice::x11AppVisual(screen);
9426 void *visual = qApp->x11Info(screen).visual();
9429 \sa QWidget::x11Info(), QPixmap::x11Info()
9432 /*! \fn Qt::HANDLE QPaintDevice::x11AppColormap(int screen)
9433 Use QX11Info::colormap() instead.
9436 unsigned long colormap = QPaintDevice::x11AppColormap(screen);
9438 unsigned long colormap = qApp->x11Info(screen).colormap();
9441 \sa QWidget::x11Info(), QPixmap::x11Info()
9444 /*! \fn Display *QPaintDevice::x11AppDisplay()
9445 Use QX11Info::display() instead.
9448 Display *display = QPaintDevice::x11AppDisplay();
9450 Display *display = qApp->x11Info().display();
9453 \sa QWidget::x11Info(), QPixmap::x11Info()
9456 /*! \fn int QPaintDevice::x11AppScreen()
9457 Use QX11Info::screen() instead.
9460 int screen = QPaintDevice::x11AppScreen();
9462 int screen = qApp->x11Info().screen();
9465 \sa QWidget::x11Info(), QPixmap::x11Info()
9468 /*! \fn int QPaintDevice::x11AppDepth(int screen)
9469 Use QX11Info::depth() instead.
9472 int depth = QPaintDevice::x11AppDepth(screen);
9474 int depth = qApp->x11Info(screen).depth();
9477 \sa QWidget::x11Info(), QPixmap::x11Info()
9480 /*! \fn int QPaintDevice::x11AppCells(int screen)
9481 Use QX11Info::cells() instead.
9484 int cells = QPaintDevice::x11AppCells(screen);
9486 int cells = qApp->x11Info(screen).cells();
9489 \sa QWidget::x11Info(), QPixmap::x11Info()
9492 /*! \fn Qt::HANDLE QPaintDevice::x11AppRootWindow(int screen)
9493 Use QX11Info::appRootWindow() instead.
9496 unsigned long window = QPaintDevice::x11AppRootWindow(screen);
9498 unsigned long window = qApp->x11Info(screen).appRootWindow();
9501 \sa QWidget::x11Info(), QPixmap::x11Info()
9504 /*! \fn bool QPaintDevice::x11AppDefaultColormap(int screen)
9505 Use QX11Info::defaultColormap() instead.
9508 bool isDefault = QPaintDevice::x11AppDefaultColormap(screen);
9510 bool isDefault = qApp->x11Info(screen).defaultColormap();
9513 \sa QWidget::x11Info(), QPixmap::x11Info()
9516 /*! \fn bool QPaintDevice::x11AppDefaultVisual(int screen)
9517 Use QX11Info::defaultVisual() instead.
9520 bool isDefault = QPaintDevice::x11AppDefaultVisual(screen);
9522 bool isDefault = qApp->x11Info(screen).defaultVisual();
9525 \sa QWidget::x11Info(), QPixmap::x11Info()
9528 /*! \fn void QPaintDevice::x11SetAppDpiX(int dpi, int screen)
9529 Use QX11Info::setAppDpiX() instead.
9532 /*! \fn void QPaintDevice::x11SetAppDpiY(int dpi, int screen)
9533 Use QX11Info::setAppDpiY() instead.
9536 /*! \fn int QPaintDevice::x11AppDpiX(int screen)
9537 Use QX11Info::appDpiX() instead.
9540 bool isDefault = QPaintDevice::x11AppDpiX(screen);
9542 bool isDefault = qApp->x11Info(screen).appDpiX();
9545 \sa QWidget::x11Info(), QPixmap::x11Info()
9548 /*! \fn int QPaintDevice::x11AppDpiY(int screen)
9549 Use QX11Info::appDpiY() instead.
9552 bool isDefault = QPaintDevice::x11AppDpiY(screen);
9554 bool isDefault = qApp->x11Info(screen).appDpiY();
9557 \sa QWidget::x11Info(), QPixmap::x11Info()
9560 /*! \fn HDC QPaintDevice::getDC() const
9564 /*! \fn void QPaintDevice::releaseDC(HDC) const
9568 /*! \fn QWSDisplay *QPaintDevice::qwsDisplay()