Enablers for shared graphics cache in raster paint engine
[profile/ivi/qtbase.git] / src / gui / painting / qpainter.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 // QtCore
43 #include <qdebug.h>
44 #include <qmath.h>
45 #include <qmutex.h>
46
47 // QtGui
48 #include "qbitmap.h"
49 #include "qimage.h"
50 #include "qpaintdevice.h"
51 #include "qpaintengine.h"
52 #include "qpainter.h"
53 #include "qpainter_p.h"
54 #include "qpainterpath.h"
55 #include "qpicture.h"
56 #include "qpixmapcache.h"
57 #include "qpolygon.h"
58 #include "qtextlayout.h"
59 #include "qthread.h"
60 #include "qvarlengtharray.h"
61 #include "qstatictext.h"
62 #include "qglyphrun.h"
63
64 #include <private/qfontengine_p.h>
65 #include <private/qpaintengine_p.h>
66 #include <private/qemulationpaintengine_p.h>
67 #include <private/qpainterpath_p.h>
68 #include <private/qtextengine_p.h>
69 #include <private/qpaintengine_raster_p.h>
70 #include <private/qmath_p.h>
71 #include <private/qstatictext_p.h>
72 #include <private/qglyphrun_p.h>
73 #include <private/qhexstring_p.h>
74 #include <private/qguiapplication_p.h>
75 #include <private/qrawfont_p.h>
76
77 QT_BEGIN_NAMESPACE
78
79 #define QGradient_StretchToDevice 0x10000000
80 #define QPaintEngine_OpaqueBackground 0x40000000
81
82 // #define QT_DEBUG_DRAW
83 #ifdef QT_DEBUG_DRAW
84 bool qt_show_painter_debug_output = true;
85 #endif
86
87 extern QPixmap qt_pixmapForBrush(int style, bool invert);
88
89 void qt_format_text(const QFont &font,
90                     const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect,
91                     int tabstops, int* tabarray, int tabarraylen,
92                     QPainter *painter);
93 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
94                                    QTextCharFormat::UnderlineStyle underlineStyle,
95                                    QTextItem::RenderFlags flags, qreal width,
96                                    const QTextCharFormat &charFormat);
97 // Helper function to calculate left most position, width and flags for decoration drawing
98 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
99                                                 const QFixedPoint *positions, int glyphCount,
100                                                 QFontEngine *fontEngine, const QFont &font,
101                                                 const QTextCharFormat &charFormat);
102
103 static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush)
104 {
105     switch (brush.style()) {
106     case Qt::LinearGradientPattern:
107     case Qt::RadialGradientPattern:
108     case Qt::ConicalGradientPattern:
109         return brush.gradient()->coordinateMode();
110     default:
111         ;
112     }
113     return QGradient::LogicalMode;
114 }
115
116 /* Returns true if the gradient requires stretch to device...*/
117 static inline bool check_gradient(const QBrush &brush)
118 {
119     return coordinateMode(brush) == QGradient::StretchToDeviceMode;
120 }
121
122 extern bool qHasPixmapTexture(const QBrush &);
123
124 static inline bool is_brush_transparent(const QBrush &brush) {
125     Qt::BrushStyle s = brush.style();
126     bool brushBitmap = qHasPixmapTexture(brush)
127                        ? brush.texture().isQBitmap()
128                        : (brush.textureImage().depth() == 1);
129     return ((s >= Qt::Dense1Pattern && s <= Qt::DiagCrossPattern)
130             || (s == Qt::TexturePattern && brushBitmap));
131 }
132
133 static inline bool is_pen_transparent(const QPen &pen) {
134     return pen.style() > Qt::SolidLine || is_brush_transparent(pen.brush());
135 }
136
137 /* Discards the emulation flags that are not relevant for line drawing
138    and returns the result
139 */
140 static inline uint line_emulation(uint emulation)
141 {
142     return emulation & (QPaintEngine::PrimitiveTransform
143                         | QPaintEngine::AlphaBlend
144                         | QPaintEngine::Antialiasing
145                         | QPaintEngine::BrushStroke
146                         | QPaintEngine::ConstantOpacity
147                         | QGradient_StretchToDevice
148                         | QPaintEngine::ObjectBoundingModeGradients
149                         | QPaintEngine_OpaqueBackground);
150 }
151
152 #ifndef QT_NO_DEBUG
153 static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
154 {
155     switch (devType) {
156     case QInternal::Image:
157     case QInternal::Printer:
158     case QInternal::Picture:
159         // can be drawn onto these devices safely from any thread
160         if (extraCondition)
161             break;
162     default:
163         if (!extraCondition && QThread::currentThread() != qApp->thread()) {
164             qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
165             return false;
166         }
167         break;
168     }
169     return true;
170 }
171 #endif
172
173 void QPainterPrivate::checkEmulation()
174 {
175     Q_ASSERT(extended);
176     if (extended->flags() & QPaintEngineEx::DoNotEmulate)
177         return;
178
179     bool doEmulation = false;
180     if (state->bgMode == Qt::OpaqueMode)
181         doEmulation = true;
182
183     const QGradient *bg = state->brush.gradient();
184     if (bg && bg->coordinateMode() > QGradient::LogicalMode)
185         doEmulation = true;
186
187     const QGradient *pg = qpen_brush(state->pen).gradient();
188     if (pg && pg->coordinateMode() > QGradient::LogicalMode)
189         doEmulation = true;
190
191     if (doEmulation) {
192         if (extended != emulationEngine) {
193             if (!emulationEngine)
194                 emulationEngine = new QEmulationPaintEngine(extended);
195             extended = emulationEngine;
196             extended->setState(state);
197         }
198     } else if (emulationEngine == extended) {
199         extended = emulationEngine->real_engine;
200     }
201 }
202
203
204 QPainterPrivate::~QPainterPrivate()
205 {
206     delete emulationEngine;
207     for (int i=0; i<states.size(); ++i)
208         delete states.at(i);
209
210     if (dummyState)
211         delete dummyState;
212 }
213
214
215 QTransform QPainterPrivate::viewTransform() const
216 {
217     if (state->VxF) {
218         qreal scaleW = qreal(state->vw)/qreal(state->ww);
219         qreal scaleH = qreal(state->vh)/qreal(state->wh);
220         return QTransform(scaleW, 0, 0, scaleH,
221                           state->vx - state->wx*scaleW, state->vy - state->wy*scaleH);
222     }
223     return QTransform();
224 }
225
226
227 /*
228    \internal
229    Returns true if using a shared painter; otherwise false.
230 */
231 bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
232 {
233     Q_ASSERT(q);
234     Q_ASSERT(pdev);
235
236     QPainter *sp = pdev->sharedPainter();
237     if (!sp)
238         return false;
239
240     // Save the current state of the shared painter and assign
241     // the current d_ptr to the shared painter's d_ptr.
242     sp->save();
243     if (!sp->d_ptr->d_ptrs) {
244         // Allocate space for 4 d-pointers (enough for up to 4 sub-sequent
245         // redirections within the same paintEvent(), which should be enough
246         // in 99% of all cases). E.g: A renders B which renders C which renders D.
247         sp->d_ptr->d_ptrs_size = 4;
248         sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
249         Q_CHECK_PTR(sp->d_ptr->d_ptrs);
250     } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
251         // However, to support corner cases we grow the array dynamically if needed.
252         sp->d_ptr->d_ptrs_size <<= 1;
253         const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
254         sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize));
255     }
256     sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
257     q->d_ptr.take();
258     q->d_ptr.reset(sp->d_ptr.data());
259
260     Q_ASSERT(q->d_ptr->state);
261
262     // Now initialize the painter with correct widget properties.
263     q->initFrom(pdev);
264     QPoint offset;
265     pdev->redirected(&offset);
266     offset += q->d_ptr->engine->coordinateOffset();
267
268     // Update system rect.
269     q->d_ptr->state->ww = q->d_ptr->state->vw = pdev->width();
270     q->d_ptr->state->wh = q->d_ptr->state->vh = pdev->height();
271
272     // Update matrix.
273     if (q->d_ptr->state->WxF) {
274         q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix;
275         q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
276         q->d_ptr->state->worldMatrix = QTransform();
277         q->d_ptr->state->WxF = false;
278     } else {
279         q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
280     }
281     q->d_ptr->updateMatrix();
282
283     QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
284     if (enginePrivate->currentClipDevice == pdev) {
285         enginePrivate->systemStateChanged();
286         return true;
287     }
288
289     // Update system transform and clip.
290     enginePrivate->currentClipDevice = pdev;
291     enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
292     return true;
293 }
294
295 void QPainterPrivate::detachPainterPrivate(QPainter *q)
296 {
297     Q_ASSERT(refcount > 1);
298     Q_ASSERT(q);
299
300     QPainterPrivate *original = d_ptrs[--refcount - 1];
301     if (inDestructor) {
302         inDestructor = false;
303         if (original)
304             original->inDestructor = true;
305     } else if (!original) {
306         original = new QPainterPrivate(q);
307     }
308
309     d_ptrs[refcount - 1] = 0;
310     q->restore();
311     q->d_ptr.take();
312     q->d_ptr.reset(original);
313
314     if (emulationEngine) {
315         extended = emulationEngine->real_engine;
316         delete emulationEngine;
317         emulationEngine = 0;
318     }
319 }
320
321
322 void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperation op)
323 {
324 #ifdef QT_DEBUG_DRAW
325     if (qt_show_painter_debug_output) {
326         printf("QPainter::drawHelper\n");
327     }
328 #endif
329
330     if (originalPath.isEmpty())
331         return;
332
333     QPaintEngine::PaintEngineFeatures gradientStretch =
334         QPaintEngine::PaintEngineFeatures(QGradient_StretchToDevice
335                                           | QPaintEngine::ObjectBoundingModeGradients);
336
337     const bool mustEmulateObjectBoundingModeGradients = extended
338                                                         || ((state->emulationSpecifier & QPaintEngine::ObjectBoundingModeGradients)
339                                                             && !engine->hasFeature(QPaintEngine::PatternTransform));
340
341     if (!(state->emulationSpecifier & ~gradientStretch)
342         && !mustEmulateObjectBoundingModeGradients) {
343         drawStretchedGradient(originalPath, op);
344         return;
345     } else if (state->emulationSpecifier & QPaintEngine_OpaqueBackground) {
346         drawOpaqueBackground(originalPath, op);
347         return;
348     }
349
350     Q_Q(QPainter);
351
352     qreal strokeOffsetX = 0, strokeOffsetY = 0;
353
354     QPainterPath path = originalPath * state->matrix;
355     QRectF pathBounds = path.boundingRect();
356     QRectF strokeBounds;
357     bool doStroke = (op & StrokeDraw) && (state->pen.style() != Qt::NoPen);
358     if (doStroke) {
359         qreal penWidth = state->pen.widthF();
360         if (penWidth == 0) {
361             strokeOffsetX = 1;
362             strokeOffsetY = 1;
363         } else {
364             // In case of complex xform
365             if (state->matrix.type() > QTransform::TxScale) {
366                 QPainterPathStroker stroker;
367                 stroker.setWidth(penWidth);
368                 stroker.setJoinStyle(state->pen.joinStyle());
369                 stroker.setCapStyle(state->pen.capStyle());
370                 QPainterPath stroke = stroker.createStroke(originalPath);
371                 strokeBounds = (stroke * state->matrix).boundingRect();
372             } else {
373                 strokeOffsetX = qAbs(penWidth * state->matrix.m11() / 2.0);
374                 strokeOffsetY = qAbs(penWidth * state->matrix.m22() / 2.0);
375             }
376         }
377     }
378
379     QRect absPathRect;
380     if (!strokeBounds.isEmpty()) {
381         absPathRect = strokeBounds.intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
382     } else {
383         absPathRect = pathBounds.adjusted(-strokeOffsetX, -strokeOffsetY, strokeOffsetX, strokeOffsetY)
384             .intersected(QRectF(0, 0, device->width(), device->height())).toAlignedRect();
385     }
386
387     if (q->hasClipping()) {
388         bool hasPerspectiveTransform = false;
389         for (int i = 0; i < state->clipInfo.size(); ++i) {
390             const QPainterClipInfo &info = state->clipInfo.at(i);
391             if (info.matrix.type() == QTransform::TxProject) {
392                 hasPerspectiveTransform = true;
393                 break;
394             }
395         }
396         // avoid mapping QRegions with perspective transforms
397         if (!hasPerspectiveTransform) {
398             // The trick with txinv and invMatrix is done in order to
399             // avoid transforming the clip to logical coordinates, and
400             // then back to device coordinates. This is a problem with
401             // QRegion/QRect based clips, since they use integer
402             // coordinates and converting to/from logical coordinates will
403             // lose precision.
404             bool old_txinv = txinv;
405             QTransform old_invMatrix = invMatrix;
406             txinv = true;
407             invMatrix = QTransform();
408             QPainterPath clipPath = q->clipPath();
409             QRectF r = clipPath.boundingRect().intersected(absPathRect);
410             absPathRect = r.toAlignedRect();
411             txinv = old_txinv;
412             invMatrix = old_invMatrix;
413         }
414     }
415
416 //     qDebug("\nQPainterPrivate::draw_helper(), x=%d, y=%d, w=%d, h=%d",
417 //            devMinX, devMinY, device->width(), device->height());
418 //     qDebug() << " - matrix" << state->matrix;
419 //     qDebug() << " - originalPath.bounds" << originalPath.boundingRect();
420 //     qDebug() << " - path.bounds" << path.boundingRect();
421
422     if (absPathRect.width() <= 0 || absPathRect.height() <= 0)
423         return;
424
425     QImage image(absPathRect.width(), absPathRect.height(), QImage::Format_ARGB32_Premultiplied);
426     image.fill(0);
427
428     QPainter p(&image);
429
430     p.d_ptr->helper_device = helper_device;
431
432     p.setOpacity(state->opacity);
433     p.translate(-absPathRect.x(), -absPathRect.y());
434     p.setTransform(state->matrix, true);
435     p.setPen(doStroke ? state->pen : QPen(Qt::NoPen));
436     p.setBrush((op & FillDraw) ? state->brush : QBrush(Qt::NoBrush));
437     p.setBackground(state->bgBrush);
438     p.setBackgroundMode(state->bgMode);
439     p.setBrushOrigin(state->brushOrigin);
440
441     p.setRenderHint(QPainter::Antialiasing, state->renderHints & QPainter::Antialiasing);
442     p.setRenderHint(QPainter::SmoothPixmapTransform,
443                     state->renderHints & QPainter::SmoothPixmapTransform);
444
445     p.drawPath(originalPath);
446
447 #ifndef QT_NO_DEBUG
448     static bool do_fallback_overlay = qgetenv("QT_PAINT_FALLBACK_OVERLAY").size() > 0;
449     if (do_fallback_overlay) {
450         QImage block(8, 8, QImage::Format_ARGB32_Premultiplied);
451         QPainter pt(&block);
452         pt.fillRect(0, 0, 8, 8, QColor(196, 0, 196));
453         pt.drawLine(0, 0, 8, 8);
454         pt.end();
455         p.resetTransform();
456         p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
457         p.setOpacity(0.5);
458         p.fillRect(0, 0, image.width(), image.height(), QBrush(block));
459     }
460 #endif
461
462     p.end();
463
464     q->save();
465     state->matrix = QTransform();
466     if (extended) {
467         extended->transformChanged();
468     } else {
469         state->dirtyFlags |= QPaintEngine::DirtyTransform;
470         updateState(state);
471     }
472     engine->drawImage(absPathRect,
473                  image,
474                  QRectF(0, 0, absPathRect.width(), absPathRect.height()),
475                  Qt::OrderedDither | Qt::OrderedAlphaDither);
476     q->restore();
477 }
478
479 void QPainterPrivate::drawOpaqueBackground(const QPainterPath &path, DrawOperation op)
480 {
481     Q_Q(QPainter);
482
483     q->setBackgroundMode(Qt::TransparentMode);
484
485     if (op & FillDraw && state->brush.style() != Qt::NoBrush) {
486         q->fillPath(path, state->bgBrush.color());
487         q->fillPath(path, state->brush);
488     }
489
490     if (op & StrokeDraw && state->pen.style() != Qt::NoPen) {
491         q->strokePath(path, QPen(state->bgBrush.color(), state->pen.width()));
492         q->strokePath(path, state->pen);
493     }
494
495     q->setBackgroundMode(Qt::OpaqueMode);
496 }
497
498 static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRectF &boundingRect)
499 {
500     Q_ASSERT(brush.style() >= Qt::LinearGradientPattern
501              && brush.style() <= Qt::ConicalGradientPattern);
502
503     QTransform gradientToUser(boundingRect.width(), 0, 0, boundingRect.height(),
504                               boundingRect.x(), boundingRect.y());
505
506     QGradient g = *brush.gradient();
507     g.setCoordinateMode(QGradient::LogicalMode);
508
509     QBrush b(g);
510     b.setTransform(gradientToUser * b.transform());
511     return b;
512 }
513
514 void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperation op)
515 {
516     Q_Q(QPainter);
517
518     const qreal sw = helper_device->width();
519     const qreal sh = helper_device->height();
520
521     bool changedPen = false;
522     bool changedBrush = false;
523     bool needsFill = false;
524
525     const QPen pen = state->pen;
526     const QBrush brush = state->brush;
527
528     const QGradient::CoordinateMode penMode = coordinateMode(pen.brush());
529     const QGradient::CoordinateMode brushMode = coordinateMode(brush);
530
531     QRectF boundingRect;
532
533     // Draw the xformed fill if the brush is a stretch gradient.
534     if ((op & FillDraw) && brush.style() != Qt::NoBrush) {
535         if (brushMode == QGradient::StretchToDeviceMode) {
536             q->setPen(Qt::NoPen);
537             changedPen = pen.style() != Qt::NoPen;
538             q->scale(sw, sh);
539             updateState(state);
540
541             const qreal isw = 1.0 / sw;
542             const qreal ish = 1.0 / sh;
543             QTransform inv(isw, 0, 0, ish, 0, 0);
544             engine->drawPath(path * inv);
545             q->scale(isw, ish);
546         } else {
547             needsFill = true;
548
549             if (brushMode == QGradient::ObjectBoundingMode) {
550                 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
551                 boundingRect = path.boundingRect();
552                 q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
553                 changedBrush = true;
554             }
555         }
556     }
557
558     if ((op & StrokeDraw) && pen.style() != Qt::NoPen) {
559         // Draw the xformed outline if the pen is a stretch gradient.
560         if (penMode == QGradient::StretchToDeviceMode) {
561             q->setPen(Qt::NoPen);
562             changedPen = true;
563
564             if (needsFill) {
565                 updateState(state);
566                 engine->drawPath(path);
567             }
568
569             q->scale(sw, sh);
570             q->setBrush(pen.brush());
571             changedBrush = true;
572             updateState(state);
573
574             QPainterPathStroker stroker;
575             stroker.setDashPattern(pen.style());
576             stroker.setWidth(pen.widthF());
577             stroker.setJoinStyle(pen.joinStyle());
578             stroker.setCapStyle(pen.capStyle());
579             stroker.setMiterLimit(pen.miterLimit());
580             QPainterPath stroke = stroker.createStroke(path);
581
582             const qreal isw = 1.0 / sw;
583             const qreal ish = 1.0 / sh;
584             QTransform inv(isw, 0, 0, ish, 0, 0);
585             engine->drawPath(stroke * inv);
586             q->scale(isw, ish);
587         } else {
588             if (!needsFill && brush.style() != Qt::NoBrush) {
589                 q->setBrush(Qt::NoBrush);
590                 changedBrush = true;
591             }
592
593             if (penMode == QGradient::ObjectBoundingMode) {
594                 Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
595
596                 // avoid computing the bounding rect twice
597                 if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
598                     boundingRect = path.boundingRect();
599
600                 QPen p = pen;
601                 p.setBrush(stretchGradientToUserSpace(pen.brush(), boundingRect));
602                 q->setPen(p);
603                 changedPen = true;
604             } else if (changedPen) {
605                 q->setPen(pen);
606                 changedPen = false;
607             }
608
609             updateState(state);
610             engine->drawPath(path);
611         }
612     } else if (needsFill) {
613         if (pen.style() != Qt::NoPen) {
614             q->setPen(Qt::NoPen);
615             changedPen = true;
616         }
617
618         updateState(state);
619         engine->drawPath(path);
620     }
621
622     if (changedPen)
623         q->setPen(pen);
624     if (changedBrush)
625         q->setBrush(brush);
626 }
627
628
629 void QPainterPrivate::updateMatrix()
630 {
631     state->matrix = state->WxF ? state->worldMatrix : QTransform();
632     if (state->VxF)
633         state->matrix *= viewTransform();
634
635     txinv = false;                                // no inverted matrix
636     state->matrix *= state->redirectionMatrix;
637     if (extended)
638         extended->transformChanged();
639     else
640         state->dirtyFlags |= QPaintEngine::DirtyTransform;
641
642 //     printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
643 //     qDebug() << " --- using matrix" << state->matrix << redirection_offset;
644 }
645
646 /*! \internal */
647 void QPainterPrivate::updateInvMatrix()
648 {
649     Q_ASSERT(txinv == false);
650     txinv = true;                                // creating inverted matrix
651     invMatrix = state->matrix.inverted();
652 }
653
654 extern bool qt_isExtendedRadialGradient(const QBrush &brush);
655
656 void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
657 {
658     bool alpha = false;
659     bool linearGradient = false;
660     bool radialGradient = false;
661     bool extendedRadialGradient = false;
662     bool conicalGradient = false;
663     bool patternBrush = false;
664     bool xform = false;
665     bool complexXform = false;
666
667     bool skip = true;
668
669     // Pen and brush properties (we have to check both if one changes because the
670     // one that's unchanged can still be in a state which requires emulation)
671     if (s->state() & (QPaintEngine::DirtyPen | QPaintEngine::DirtyBrush | QPaintEngine::DirtyHints)) {
672         // Check Brush stroke emulation
673         if (!s->pen.isSolid() && !engine->hasFeature(QPaintEngine::BrushStroke))
674             s->emulationSpecifier |= QPaintEngine::BrushStroke;
675         else
676             s->emulationSpecifier &= ~QPaintEngine::BrushStroke;
677
678         skip = false;
679
680         QBrush penBrush = (qpen_style(s->pen) == Qt::NoPen) ? QBrush(Qt::NoBrush) : qpen_brush(s->pen);
681         Qt::BrushStyle brushStyle = qbrush_style(s->brush);
682         Qt::BrushStyle penBrushStyle = qbrush_style(penBrush);
683         alpha = (penBrushStyle != Qt::NoBrush
684                  && (penBrushStyle < Qt::LinearGradientPattern && penBrush.color().alpha() != 255)
685                  && !penBrush.isOpaque())
686                 || (brushStyle != Qt::NoBrush
687                     && (brushStyle < Qt::LinearGradientPattern && s->brush.color().alpha() != 255)
688                     && !s->brush.isOpaque());
689         linearGradient = ((penBrushStyle == Qt::LinearGradientPattern) ||
690                            (brushStyle == Qt::LinearGradientPattern));
691         radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
692                            (brushStyle == Qt::RadialGradientPattern));
693         extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
694         conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
695                             (brushStyle == Qt::ConicalGradientPattern));
696         patternBrush = (((penBrushStyle > Qt::SolidPattern
697                            && penBrushStyle < Qt::LinearGradientPattern)
698                           || penBrushStyle == Qt::TexturePattern) ||
699                          ((brushStyle > Qt::SolidPattern
700                            && brushStyle < Qt::LinearGradientPattern)
701                           || brushStyle == Qt::TexturePattern));
702
703         bool penTextureAlpha = false;
704         if (penBrush.style() == Qt::TexturePattern)
705             penTextureAlpha = qHasPixmapTexture(penBrush)
706                               ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
707                               : penBrush.textureImage().hasAlphaChannel();
708         bool brushTextureAlpha = false;
709         if (s->brush.style() == Qt::TexturePattern) {
710             brushTextureAlpha = qHasPixmapTexture(s->brush)
711                                 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
712                                 : s->brush.textureImage().hasAlphaChannel();
713         }
714         if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
715              || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
716             && !engine->hasFeature(QPaintEngine::MaskedBrush))
717             s->emulationSpecifier |= QPaintEngine::MaskedBrush;
718         else
719             s->emulationSpecifier &= ~QPaintEngine::MaskedBrush;
720     }
721
722     if (s->state() & (QPaintEngine::DirtyHints
723                       | QPaintEngine::DirtyOpacity
724                       | QPaintEngine::DirtyBackgroundMode)) {
725         skip = false;
726     }
727
728     if (skip)
729         return;
730
731 #if 0
732     qDebug("QPainterPrivate::updateEmulationSpecifier, state=%p\n"
733            " - alpha: %d\n"
734            " - linearGradient: %d\n"
735            " - radialGradient: %d\n"
736            " - conicalGradient: %d\n"
737            " - patternBrush: %d\n"
738            " - hints: %x\n"
739            " - xform: %d\n",
740            s,
741            alpha,
742            linearGradient,
743            radialGradient,
744            conicalGradient,
745            patternBrush,
746            uint(s->renderHints),
747            xform);
748 #endif
749
750     // XForm properties
751     if (s->state() & QPaintEngine::DirtyTransform) {
752         xform = !s->matrix.isIdentity();
753         complexXform = !s->matrix.isAffine();
754     } else if (s->matrix.type() >= QTransform::TxTranslate) {
755         xform = true;
756         complexXform = !s->matrix.isAffine();
757     }
758
759     const bool brushXform = (!s->brush.transform().type() == QTransform::TxNone);
760     const bool penXform = (!s->pen.brush().transform().type() == QTransform::TxNone);
761
762     const bool patternXform = patternBrush && (xform || brushXform || penXform);
763
764     // Check alphablending
765     if (alpha && !engine->hasFeature(QPaintEngine::AlphaBlend))
766         s->emulationSpecifier |= QPaintEngine::AlphaBlend;
767     else
768         s->emulationSpecifier &= ~QPaintEngine::AlphaBlend;
769
770     // Linear gradient emulation
771     if (linearGradient && !engine->hasFeature(QPaintEngine::LinearGradientFill))
772         s->emulationSpecifier |= QPaintEngine::LinearGradientFill;
773     else
774         s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
775
776     // Radial gradient emulation
777     if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
778         s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
779     else
780         s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
781
782     // Conical gradient emulation
783     if (conicalGradient && !engine->hasFeature(QPaintEngine::ConicalGradientFill))
784         s->emulationSpecifier |= QPaintEngine::ConicalGradientFill;
785     else
786         s->emulationSpecifier &= ~QPaintEngine::ConicalGradientFill;
787
788     // Pattern brushes
789     if (patternBrush && !engine->hasFeature(QPaintEngine::PatternBrush))
790         s->emulationSpecifier |= QPaintEngine::PatternBrush;
791     else
792         s->emulationSpecifier &= ~QPaintEngine::PatternBrush;
793
794     // Pattern XForms
795     if (patternXform && !engine->hasFeature(QPaintEngine::PatternTransform))
796         s->emulationSpecifier |= QPaintEngine::PatternTransform;
797     else
798         s->emulationSpecifier &= ~QPaintEngine::PatternTransform;
799
800     // Primitive XForms
801     if (xform && !engine->hasFeature(QPaintEngine::PrimitiveTransform))
802         s->emulationSpecifier |= QPaintEngine::PrimitiveTransform;
803     else
804         s->emulationSpecifier &= ~QPaintEngine::PrimitiveTransform;
805
806     // Perspective XForms
807     if (complexXform && !engine->hasFeature(QPaintEngine::PerspectiveTransform))
808         s->emulationSpecifier |= QPaintEngine::PerspectiveTransform;
809     else
810         s->emulationSpecifier &= ~QPaintEngine::PerspectiveTransform;
811
812     // Constant opacity
813     if (state->opacity != 1 && !engine->hasFeature(QPaintEngine::ConstantOpacity))
814         s->emulationSpecifier |= QPaintEngine::ConstantOpacity;
815     else
816         s->emulationSpecifier &= ~QPaintEngine::ConstantOpacity;
817
818     bool gradientStretch = false;
819     bool objectBoundingMode = false;
820     if (linearGradient || conicalGradient || radialGradient) {
821         QGradient::CoordinateMode brushMode = coordinateMode(s->brush);
822         QGradient::CoordinateMode penMode = coordinateMode(s->pen.brush());
823
824         gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
825         gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
826
827         objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
828         objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
829     }
830     if (gradientStretch)
831         s->emulationSpecifier |= QGradient_StretchToDevice;
832     else
833         s->emulationSpecifier &= ~QGradient_StretchToDevice;
834
835     if (objectBoundingMode && !engine->hasFeature(QPaintEngine::ObjectBoundingModeGradients))
836         s->emulationSpecifier |= QPaintEngine::ObjectBoundingModeGradients;
837     else
838         s->emulationSpecifier &= ~QPaintEngine::ObjectBoundingModeGradients;
839
840     // Opaque backgrounds...
841     if (s->bgMode == Qt::OpaqueMode &&
842         (is_pen_transparent(s->pen) || is_brush_transparent(s->brush)))
843         s->emulationSpecifier |= QPaintEngine_OpaqueBackground;
844     else
845         s->emulationSpecifier &= ~QPaintEngine_OpaqueBackground;
846
847 #if 0
848     //won't be correct either way because the device can already have
849     // something rendered to it in which case subsequent emulation
850     // on a fully transparent qimage and then blitting the results
851     // won't produce correct results
852     // Blend modes
853     if (state->composition_mode > QPainter::CompositionMode_Xor &&
854         !engine->hasFeature(QPaintEngine::BlendModes))
855         s->emulationSpecifier |= QPaintEngine::BlendModes;
856     else
857         s->emulationSpecifier &= ~QPaintEngine::BlendModes;
858 #endif
859 }
860
861 void QPainterPrivate::updateStateImpl(QPainterState *newState)
862 {
863     // ### we might have to call QPainter::begin() here...
864     if (!engine->state) {
865         engine->state = newState;
866         engine->setDirty(QPaintEngine::AllDirty);
867     }
868
869     if (engine->state->painter() != newState->painter)
870         // ### this could break with clip regions vs paths.
871         engine->setDirty(QPaintEngine::AllDirty);
872
873     // Upon restore, revert all changes since last save
874     else if (engine->state != newState)
875         newState->dirtyFlags |= QPaintEngine::DirtyFlags(static_cast<QPainterState *>(engine->state)->changeFlags);
876
877     // We need to store all changes made so that restore can deal with them
878     else
879         newState->changeFlags |= newState->dirtyFlags;
880
881     updateEmulationSpecifier(newState);
882
883     // Unset potential dirty background mode
884     newState->dirtyFlags &= ~(QPaintEngine::DirtyBackgroundMode
885             | QPaintEngine::DirtyBackground);
886
887     engine->state = newState;
888     engine->updateState(*newState);
889     engine->clearDirty(QPaintEngine::AllDirty);
890
891 }
892
893 void QPainterPrivate::updateState(QPainterState *newState)
894 {
895
896     if (!newState) {
897         engine->state = newState;
898
899     } else if (newState->state() || engine->state!=newState) {
900         bool setNonCosmeticPen = (newState->renderHints & QPainter::NonCosmeticDefaultPen)
901                                  && newState->pen.widthF() == 0;
902         if (setNonCosmeticPen) {
903             // Override the default pen's cosmetic state if the
904             // NonCosmeticDefaultPen render hint is used.
905             QPen oldPen = newState->pen;
906             newState->pen.setWidth(1);
907             newState->pen.setCosmetic(false);
908             newState->dirtyFlags |= QPaintEngine::DirtyPen;
909
910             updateStateImpl(newState);
911
912             // Restore the state pen back to its default to preserve visible
913             // state.
914             newState->pen = oldPen;
915         } else {
916             updateStateImpl(newState);
917         }
918     }
919 }
920
921
922 /*!
923     \class QPainter
924     \brief The QPainter class performs low-level painting on widgets and
925     other paint devices.
926
927     \ingroup painting
928
929     \reentrant
930
931     QPainter provides highly optimized functions to do most of the
932     drawing GUI programs require. It can draw everything from simple
933     lines to complex shapes like pies and chords. It can also draw
934     aligned text and pixmaps. Normally, it draws in a "natural"
935     coordinate system, but it can also do view and world
936     transformation. QPainter can operate on any object that inherits
937     the QPaintDevice class.
938
939     The common use of QPainter is inside a widget's paint event:
940     Construct and customize (e.g. set the pen or the brush) the
941     painter. Then draw. Remember to destroy the QPainter object after
942     drawing. For example:
943
944     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 0
945
946     The core functionality of QPainter is drawing, but the class also
947     provide several functions that allows you to customize QPainter's
948     settings and its rendering quality, and others that enable
949     clipping. In addition you can control how different shapes are
950     merged together by specifying the painter's composition mode.
951
952     The isActive() function indicates whether the painter is active. A
953     painter is activated by the begin() function and the constructor
954     that takes a QPaintDevice argument. The end() function, and the
955     destructor, deactivates it.
956
957     Together with the QPaintDevice and QPaintEngine classes, QPainter
958     form the basis for Qt's paint system. QPainter is the class used
959     to perform drawing operations. QPaintDevice represents a device
960     that can be painted on using a QPainter. QPaintEngine provides the
961     interface that the painter uses to draw onto different types of
962     devices. If the painter is active, device() returns the paint
963     device on which the painter paints, and paintEngine() returns the
964     paint engine that the painter is currently operating on. For more
965     information, see the \l {Paint System}.
966
967     Sometimes it is desirable to make someone else paint on an unusual
968     QPaintDevice. QPainter supports a static function to do this,
969     setRedirected().
970
971     \warning When the paintdevice is a widget, QPainter can only be
972     used inside a paintEvent() function or in a function called by
973     paintEvent(); that is unless the Qt::WA_PaintOutsidePaintEvent
974     widget attribute is set. On Mac OS X and Windows, you can only
975     paint in a paintEvent() function regardless of this attribute's
976     setting.
977
978     \tableofcontents
979
980     \section1 Settings
981
982     There are several settings that you can customize to make QPainter
983     draw according to your preferences:
984
985     \list
986
987     \li font() is the font used for drawing text. If the painter
988         isActive(), you can retrieve information about the currently set
989         font, and its metrics, using the fontInfo() and fontMetrics()
990         functions respectively.
991
992     \li brush() defines the color or pattern that is used for filling
993        shapes.
994
995     \li pen() defines the color or stipple that is used for drawing
996        lines or boundaries.
997
998     \li backgroundMode() defines whether there is a background() or
999        not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode.
1000
1001     \li background() only applies when backgroundMode() is \l
1002        Qt::OpaqueMode and pen() is a stipple. In that case, it
1003        describes the color of the background pixels in the stipple.
1004
1005     \li brushOrigin() defines the origin of the tiled brushes, normally
1006        the origin of widget's background.
1007
1008     \li viewport(), window(), worldTransform() make up the painter's coordinate
1009         transformation system. For more information, see the \l
1010         {Coordinate Transformations} section and the \l {Coordinate
1011         System} documentation.
1012
1013     \li hasClipping() tells whether the painter clips at all. (The paint
1014        device clips, too.) If the painter clips, it clips to clipRegion().
1015
1016     \li layoutDirection() defines the layout direction used by the
1017        painter when drawing text.
1018
1019     \li worldMatrixEnabled() tells whether world transformation is enabled.
1020
1021     \li viewTransformEnabled() tells whether view transformation is
1022         enabled.
1023
1024     \endlist
1025
1026     Note that some of these settings mirror settings in some paint
1027     devices, e.g.  QWidget::font(). The QPainter::begin() function (or
1028     equivalently the QPainter constructor) copies these attributes
1029     from the paint device.
1030
1031     You can at any time save the QPainter's state by calling the
1032     save() function which saves all the available settings on an
1033     internal stack. The restore() function pops them back.
1034
1035     \section1 Drawing
1036
1037     QPainter provides functions to draw most primitives: drawPoint(),
1038     drawPoints(), drawLine(), drawRect(), drawRoundedRect(),
1039     drawEllipse(), drawArc(), drawPie(), drawChord(), drawPolyline(),
1040     drawPolygon(), drawConvexPolygon() and drawCubicBezier().  The two
1041     convenience functions, drawRects() and drawLines(), draw the given
1042     number of rectangles or lines in the given array of \l
1043     {QRect}{QRects} or \l {QLine}{QLines} using the current pen and
1044     brush.
1045
1046     The QPainter class also provides the fillRect() function which
1047     fills the given QRect, with the given QBrush, and the eraseRect()
1048     function that erases the area inside the given rectangle.
1049
1050     All of these functions have both integer and floating point
1051     versions.
1052
1053     \table 100%
1054     \row
1055     \li \inlineimage qpainter-basicdrawing.png
1056     \li
1057     \b {Basic Drawing Example}
1058
1059     The \l {painting/basicdrawing}{Basic Drawing} example shows how to
1060     display basic graphics primitives in a variety of styles using the
1061     QPainter class.
1062
1063     \endtable
1064
1065     If you need to draw a complex shape, especially if you need to do
1066     so repeatedly, consider creating a QPainterPath and drawing it
1067     using drawPath().
1068
1069     \table 100%
1070     \row
1071     \li
1072     \b {Painter Paths example}
1073
1074     The QPainterPath class provides a container for painting
1075     operations, enabling graphical shapes to be constructed and
1076     reused.
1077
1078     The \l {painting/painterpaths}{Painter Paths} example shows how
1079     painter paths can be used to build complex shapes for rendering.
1080
1081     \li \inlineimage qpainter-painterpaths.png
1082     \endtable
1083
1084     QPainter also provides the fillPath() function which fills the
1085     given QPainterPath with the given QBrush, and the strokePath()
1086     function that draws the outline of the given path (i.e. strokes
1087     the path).
1088
1089     See also the \l {painting/deform}{Vector Deformation} example which
1090     shows how to use advanced vector techniques to draw text using a
1091     QPainterPath, the \l {painting/gradients}{Gradients} example which shows
1092     the different types of gradients that are available in Qt, and the \l
1093     {painting/pathstroke}{Path Stroking} example which shows Qt's built-in
1094     dash patterns and shows how custom patterns can be used to extend
1095     the range of available patterns.
1096
1097     \table
1098     \header
1099     \li \l {painting/deform}{Vector Deformation}
1100     \li \l {painting/gradients}{Gradients}
1101     \li \l {painting/pathstroke}{Path Stroking}
1102     \row
1103     \li \inlineimage qpainter-vectordeformation.png
1104     \li \inlineimage qpainter-gradients.png
1105     \li \inlineimage qpainter-pathstroking.png
1106     \endtable
1107
1108
1109     There are functions to draw pixmaps/images, namely drawPixmap(),
1110     drawImage() and drawTiledPixmap(). Both drawPixmap() and drawImage()
1111     produce the same result, except that drawPixmap() is faster
1112     on-screen while drawImage() may be faster on a QPrinter or other
1113     devices.
1114
1115     Text drawing is done using drawText(). When you need
1116     fine-grained positioning, boundingRect() tells you where a given
1117     drawText() command will draw.
1118
1119     There is a drawPicture() function that draws the contents of an
1120     entire QPicture. The drawPicture() function is the only function
1121     that disregards all the painter's settings as QPicture has its own
1122     settings.
1123
1124     \section1 Rendering Quality
1125
1126     To get the optimal rendering result using QPainter, you should use
1127     the platform independent QImage as paint device; i.e. using QImage
1128     will ensure that the result has an identical pixel representation
1129     on any platform.
1130
1131     The QPainter class also provides a means of controlling the
1132     rendering quality through its RenderHint enum and the support for
1133     floating point precision: All the functions for drawing primitives
1134     has a floating point version. These are often used in combination
1135     with the \l {RenderHint}{QPainter::Antialiasing} render hint.
1136
1137     \table 100%
1138     \row
1139     \li \inlineimage qpainter-concentriccircles.png
1140     \li
1141     \b {Concentric Circles Example}
1142
1143     The \l {painting/concentriccircles}{Concentric Circles} example
1144     shows the improved rendering quality that can be obtained using
1145     floating point precision and anti-aliasing when drawing custom
1146     widgets.
1147
1148     The application's main window displays several widgets which are
1149     drawn using the various combinations of precision and
1150     anti-aliasing.
1151
1152     \endtable
1153
1154     The RenderHint enum specifies flags to QPainter that may or may
1155     not be respected by any given engine.  \l
1156     {RenderHint}{QPainter::Antialiasing} indicates that the engine
1157     should antialias edges of primitives if possible, \l
1158     {RenderHint}{QPainter::TextAntialiasing} indicates that the engine
1159     should antialias text if possible, and the \l
1160     {RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
1161     engine should use a smooth pixmap transformation algorithm.
1162     \l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
1163     indicating that the engine should use fragment programs and offscreen
1164     rendering for antialiasing.
1165
1166     The renderHints() function returns a flag that specifies the
1167     rendering hints that are set for this painter.  Use the
1168     setRenderHint() function to set or clear the currently set
1169     RenderHints.
1170
1171     \section1 Coordinate Transformations
1172
1173     Normally, the QPainter operates on the device's own coordinate
1174     system (usually pixels), but QPainter has good support for
1175     coordinate transformations.
1176
1177     \table
1178     \header
1179     \li  nop \li rotate() \li scale() \li translate()
1180     \row
1181     \li \inlineimage qpainter-clock.png
1182     \li \inlineimage qpainter-rotation.png
1183     \li \inlineimage qpainter-scale.png
1184     \li \inlineimage qpainter-translation.png
1185     \endtable
1186
1187     The most commonly used transformations are scaling, rotation,
1188     translation and shearing. Use the scale() function to scale the
1189     coordinate system by a given offset, the rotate() function to
1190     rotate it clockwise and translate() to translate it (i.e. adding a
1191     given offset to the points). You can also twist the coordinate
1192     system around the origin using the shear() function. See the \l
1193     {painting/affine}{Affine Transformations} example for a visualization of
1194     a sheared coordinate system.
1195
1196     See also the \l {painting/transformations}{Transformations}
1197     example which shows how transformations influence the way that
1198     QPainter renders graphics primitives. In particular it shows how
1199     the order of transformations affects the result.
1200
1201     \table 100%
1202     \row
1203     \li
1204     \b {Affine Transformations Example}
1205
1206     The \l {painting/affine}{Affine Transformations} example shows Qt's
1207     ability to perform affine transformations on painting
1208     operations. The demo also allows the user to experiment with the
1209     transformation operations and see the results immediately.
1210
1211     \li \inlineimage qpainter-affinetransformations.png
1212     \endtable
1213
1214     All the tranformation operations operate on the transformation
1215     worldTransform(). A matrix transforms a point in the plane to another
1216     point. For more information about the transformation matrix, see
1217     the \l {Coordinate System} and QTransform documentation.
1218
1219     The setWorldTransform() function can replace or add to the currently
1220     set worldTransform(). The resetTransform() function resets any
1221     transformations that were made using translate(), scale(),
1222     shear(), rotate(), setWorldTransform(), setViewport() and setWindow()
1223     functions. The deviceTransform() returns the matrix that transforms
1224     from logical coordinates to device coordinates of the platform
1225     dependent paint device. The latter function is only needed when
1226     using platform painting commands on the platform dependent handle,
1227     and the platform does not do transformations nativly.
1228
1229     When drawing with QPainter, we specify points using logical
1230     coordinates which then are converted into the physical coordinates
1231     of the paint device. The mapping of the logical coordinates to the
1232     physical coordinates are handled by QPainter's combinedTransform(), a
1233     combination of viewport() and window() and worldTransform(). The
1234     viewport() represents the physical coordinates specifying an
1235     arbitrary rectangle, the window() describes the same rectangle in
1236     logical coordinates, and the worldTransform() is identical with the
1237     transformation matrix.
1238
1239     See also \l {Coordinate System}
1240
1241     \section1 Clipping
1242
1243     QPainter can clip any drawing operation to a rectangle, a region,
1244     or a vector path. The current clip is available using the
1245     functions clipRegion() and clipPath(). Whether paths or regions are
1246     preferred (faster) depends on the underlying paintEngine(). For
1247     example, the QImage paint engine prefers paths while the X11 paint
1248     engine prefers regions. Setting a clip is done in the painters
1249     logical coordinates.
1250
1251     After QPainter's clipping, the paint device may also clip. For
1252     example, most widgets clip away the pixels used by child widgets,
1253     and most printers clip away an area near the edges of the paper.
1254     This additional clipping is not reflected by the return value of
1255     clipRegion() or hasClipping().
1256
1257     \section1 Composition Modes
1258     \target Composition Modes
1259
1260     QPainter provides the CompositionMode enum which defines the
1261     Porter-Duff rules for digital image compositing; it describes a
1262     model for combining the pixels in one image, the source, with the
1263     pixels in another image, the destination.
1264
1265     The two most common forms of composition are \l
1266     {QPainter::CompositionMode}{Source} and \l
1267     {QPainter::CompositionMode}{SourceOver}.  \l
1268     {QPainter::CompositionMode}{Source} is used to draw opaque objects
1269     onto a paint device. In this mode, each pixel in the source
1270     replaces the corresponding pixel in the destination. In \l
1271     {QPainter::CompositionMode}{SourceOver} composition mode, the
1272     source object is transparent and is drawn on top of the
1273     destination.
1274
1275     Note that composition transformation operates pixelwise. For that
1276     reason, there is a difference between using the graphic primitive
1277     itself and its bounding rectangle: The bounding rect contains
1278     pixels with alpha == 0 (i.e the pixels surrounding the
1279     primitive). These pixels will overwrite the other image's pixels,
1280     affectively clearing those, while the primitive only overwrites
1281     its own area.
1282
1283     \table 100%
1284     \row
1285     \li \inlineimage qpainter-compositiondemo.png
1286
1287     \li
1288     \b {Composition Modes Example}
1289
1290     The \l {painting/composition}{Composition Modes} example, available in
1291     Qt's examples directory, allows you to experiment with the various
1292     composition modes and see the results immediately.
1293
1294     \endtable
1295
1296     \section1 Limitations
1297     \target Limitations
1298
1299     If you are using coordinates with Qt's raster-based paint engine, it is
1300     important to note that, while coordinates greater than +/- 2\sup 15 can
1301     be used, any painting performed with coordinates outside this range is not
1302     guaranteed to be shown; the drawing may be clipped. This is due to the
1303     use of \c{short int} in the implementation.
1304
1305     The outlines generated by Qt's stroker are only an approximation when dealing
1306     with curved shapes. It is in most cases impossible to represent the outline of
1307     a bezier curve segment using another bezier curve segment, and so Qt approximates
1308     the curve outlines by using several smaller curves. For performance reasons there
1309     is a limit to how many curves Qt uses for these outlines, and thus when using
1310     large pen widths or scales the outline error increases. To generate outlines with
1311     smaller errors it is possible to use the QPainterPathStroker class, which has the
1312     setCurveThreshold member function which let's the user specify the error tolerance.
1313     Another workaround is to convert the paths to polygons first and then draw the
1314     polygons instead.
1315
1316     \section1 Performance
1317
1318     QPainter is a rich framework that allows developers to do a great
1319     variety of graphical operations, such as gradients, composition
1320     modes and vector graphics. And QPainter can do this across a
1321     variety of different hardware and software stacks. Naturally the
1322     underlying combination of hardware and software has some
1323     implications for performance, and ensuring that every single
1324     operation is fast in combination with all the various combinations
1325     of composition modes, brushes, clipping, transformation, etc, is
1326     close to an impossible task because of the number of
1327     permutations. As a compromise we have selected a subset of the
1328     QPainter API and backends, where performance is guaranteed to be as
1329     good as we can sensibly get it for the given combination of
1330     hardware and software.
1331
1332     The backends we focus on as high-performance engines are:
1333
1334     \list
1335
1336     \li Raster - This backend implements all rendering in pure software
1337     and is always used to render into QImages. For optimal performance
1338     only use the format types QImage::Format_ARGB32_Premultiplied,
1339     QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
1340     including QImage::Format_ARGB32, has significantly worse
1341     performance. This engine is used by default for QWidget and QPixmap.
1342
1343     \li OpenGL 2.0 (ES) - This backend is the primary backend for
1344     hardware accelerated graphics. It can be run on desktop machines
1345     and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
1346     specification. This includes most graphics chips produced in the
1347     last couple of years. The engine can be enabled by using QPainter
1348     onto a QOpenGLWidget or by passing \c {-graphicssystem opengl} on the
1349     command line when the underlying system supports it.
1350
1351     \li OpenVG - This backend implements the Khronos standard for 2D
1352     and Vector Graphics. It is primarily for embedded devices with
1353     hardware support for OpenVG.  The engine can be enabled by
1354     passing \c {-graphicssystem openvg} on the command line when
1355     the underlying system supports it.
1356
1357     \endlist
1358
1359     These operations are:
1360
1361     \list
1362
1363     \li Simple transformations, meaning translation and scaling, pluss
1364     0, 90, 180, 270 degree rotations.
1365
1366     \li \c drawPixmap() in combination with simple transformations and
1367     opacity with non-smooth transformation mode
1368     (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
1369
1370     \li Rectangle fills with solid color, two-color linear gradients
1371     and simple transforms.
1372
1373     \li Rectangular clipping with simple transformations and intersect
1374     clip.
1375
1376     \li Composition Modes \c QPainter::CompositionMode_Source and
1377     QPainter::CompositionMode_SourceOver
1378
1379     \li Rounded rectangle filling using solid color and two-color
1380     linear gradients fills.
1381
1382     \li 3x3 patched pixmaps, via qDrawBorderPixmap.
1383
1384     \endlist
1385
1386     This list gives an indication of which features to safely use in
1387     an application where performance is critical. For certain setups,
1388     other operations may be fast too, but before making extensive use
1389     of them, it is recommended to benchmark and verify them on the
1390     system where the software will run in the end. There are also
1391     cases where expensive operations are ok to use, for instance when
1392     the result is cached in a QPixmap.
1393
1394     \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example},
1395         {Drawing Utility Functions}
1396 */
1397
1398 /*!
1399     \enum QPainter::RenderHint
1400
1401     Renderhints are used to specify flags to QPainter that may or
1402     may not be respected by any given engine.
1403
1404     \value Antialiasing Indicates that the engine should antialias
1405     edges of primitives if possible.
1406
1407     \value TextAntialiasing Indicates that the engine should antialias
1408     text if possible. To forcibly disable antialiasing for text, do not
1409     use this hint. Instead, set QFont::NoAntialias on your font's style
1410     strategy.
1411
1412     \value SmoothPixmapTransform Indicates that the engine should use
1413     a smooth pixmap transformation algorithm (such as bilinear) rather
1414     than nearest neighbor.
1415
1416     \value HighQualityAntialiasing An OpenGL-specific rendering hint
1417     indicating that the engine should use fragment programs and offscreen
1418     rendering for antialiasing.
1419
1420     \value NonCosmeticDefaultPen The engine should interpret pens with a width
1421     of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
1422     pen with a width of 1.
1423
1424     \sa renderHints(), setRenderHint(), {QPainter#Rendering
1425     Quality}{Rendering Quality}, {Concentric Circles Example}
1426
1427 */
1428
1429 /*!
1430     Constructs a painter.
1431
1432     \sa begin(), end()
1433 */
1434
1435 QPainter::QPainter()
1436     : d_ptr(new QPainterPrivate(this))
1437 {
1438 }
1439
1440 /*!
1441     \fn QPainter::QPainter(QPaintDevice *device)
1442
1443     Constructs a painter that begins painting the paint \a device
1444     immediately.
1445
1446     This constructor is convenient for short-lived painters, e.g. in a
1447     QWidget::paintEvent() and should be used only once. The
1448     constructor calls begin() for you and the QPainter destructor
1449     automatically calls end().
1450
1451     Here's an example using begin() and end():
1452     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 1
1453
1454     The same example using this constructor:
1455     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 2
1456
1457     Since the constructor cannot provide feedback when the initialization
1458     of the painter failed you should rather use begin() and end() to paint
1459     on external devices, e.g. printers.
1460
1461     \sa begin(), end()
1462 */
1463
1464 QPainter::QPainter(QPaintDevice *pd)
1465     : d_ptr(0)
1466 {
1467     Q_ASSERT(pd != 0);
1468     if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
1469         d_ptr.reset(new QPainterPrivate(this));
1470         begin(pd);
1471     }
1472     Q_ASSERT(d_ptr);
1473 }
1474
1475 /*!
1476     Destroys the painter.
1477 */
1478 QPainter::~QPainter()
1479 {
1480     d_ptr->inDestructor = true;
1481     QT_TRY {
1482         if (isActive())
1483             end();
1484         else if (d_ptr->refcount > 1)
1485             d_ptr->detachPainterPrivate(this);
1486     } QT_CATCH(...) {
1487         // don't throw anything in the destructor.
1488     }
1489     if (d_ptr) {
1490         // Make sure we haven't messed things up.
1491         Q_ASSERT(d_ptr->inDestructor);
1492         d_ptr->inDestructor = false;
1493         Q_ASSERT(d_ptr->refcount == 1);
1494         if (d_ptr->d_ptrs)
1495             free(d_ptr->d_ptrs);
1496     }
1497 }
1498
1499 /*!
1500     Returns the paint device on which this painter is currently
1501     painting, or 0 if the painter is not active.
1502
1503     \sa isActive()
1504 */
1505
1506 QPaintDevice *QPainter::device() const
1507 {
1508     Q_D(const QPainter);
1509     if (isActive() && d->engine->d_func()->currentClipDevice)
1510         return d->engine->d_func()->currentClipDevice;
1511     return d->original_device;
1512 }
1513
1514 /*!
1515     Returns true if begin() has been called and end() has not yet been
1516     called; otherwise returns false.
1517
1518     \sa begin(), QPaintDevice::paintingActive()
1519 */
1520
1521 bool QPainter::isActive() const
1522 {
1523     Q_D(const QPainter);
1524     return d->engine;
1525 }
1526
1527 /*!
1528     Initializes the painters pen, background and font to the same as
1529     the given \a paint device.
1530
1531     \obsolete
1532
1533     \sa begin(), {QPainter#Settings}{Settings}
1534 */
1535 void QPainter::initFrom(const QPaintDevice *device)
1536 {
1537     Q_ASSERT_X(device, "QPainter::initFrom(const QPaintDevice *device)", "QPaintDevice cannot be 0");
1538     Q_D(QPainter);
1539     if (!d->engine) {
1540         qWarning("QPainter::initFrom: Painter not active, aborted");
1541         return;
1542     }
1543
1544     device->init(this);
1545
1546     if (d->extended) {
1547         d->extended->penChanged();
1548     } else if (d->engine) {
1549         d->engine->setDirty(QPaintEngine::DirtyPen);
1550         d->engine->setDirty(QPaintEngine::DirtyBrush);
1551         d->engine->setDirty(QPaintEngine::DirtyFont);
1552     }
1553 }
1554
1555
1556 /*!
1557     Saves the current painter state (pushes the state onto a stack). A
1558     save() must be followed by a corresponding restore(); the end()
1559     function unwinds the stack.
1560
1561     \sa restore()
1562 */
1563
1564 void QPainter::save()
1565 {
1566 #ifdef QT_DEBUG_DRAW
1567     if (qt_show_painter_debug_output)
1568         printf("QPainter::save()\n");
1569 #endif
1570     Q_D(QPainter);
1571     if (!d->engine) {
1572         qWarning("QPainter::save: Painter not active");
1573         return;
1574     }
1575
1576     if (d->extended) {
1577         d->state = d->extended->createState(d->states.back());
1578         d->extended->setState(d->state);
1579     } else {
1580         d->updateState(d->state);
1581         d->state = new QPainterState(d->states.back());
1582         d->engine->state = d->state;
1583     }
1584     d->states.push_back(d->state);
1585 }
1586
1587 /*!
1588     Restores the current painter state (pops a saved state off the
1589     stack).
1590
1591     \sa save()
1592 */
1593
1594 void QPainter::restore()
1595 {
1596 #ifdef QT_DEBUG_DRAW
1597     if (qt_show_painter_debug_output)
1598         printf("QPainter::restore()\n");
1599 #endif
1600     Q_D(QPainter);
1601     if (d->states.size()<=1) {
1602         qWarning("QPainter::restore: Unbalanced save/restore");
1603         return;
1604     } else if (!d->engine) {
1605         qWarning("QPainter::restore: Painter not active");
1606         return;
1607     }
1608
1609     QPainterState *tmp = d->state;
1610     d->states.pop_back();
1611     d->state = d->states.back();
1612     d->txinv = false;
1613
1614     if (d->extended) {
1615         d->checkEmulation();
1616         d->extended->setState(d->state);
1617         delete tmp;
1618         return;
1619     }
1620
1621     // trigger clip update if the clip path/region has changed since
1622     // last save
1623     if (!d->state->clipInfo.isEmpty()
1624         && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) {
1625         // reuse the tmp state to avoid any extra allocs...
1626         tmp->dirtyFlags = QPaintEngine::DirtyClipPath;
1627         tmp->clipOperation = Qt::NoClip;
1628         tmp->clipPath = QPainterPath();
1629         d->engine->updateState(*tmp);
1630         // replay the list of clip states,
1631         for (int i=0; i<d->state->clipInfo.size(); ++i) {
1632             const QPainterClipInfo &info = d->state->clipInfo.at(i);
1633             tmp->matrix = info.matrix;
1634             tmp->matrix *= d->state->redirectionMatrix;
1635             tmp->clipOperation = info.operation;
1636             if (info.clipType == QPainterClipInfo::RectClip) {
1637                 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1638                 tmp->clipRegion = info.rect;
1639             } else if (info.clipType == QPainterClipInfo::RegionClip) {
1640                 tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
1641                 tmp->clipRegion = info.region;
1642             } else { // clipType == QPainterClipInfo::PathClip
1643                 tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform;
1644                 tmp->clipPath = info.path;
1645             }
1646             d->engine->updateState(*tmp);
1647         }
1648
1649
1650         //Since we've updated the clip region anyway, pretend that the clip path hasn't changed:
1651         d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1652         tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion);
1653         tmp->changeFlags |= QPaintEngine::DirtyTransform;
1654     }
1655
1656     d->updateState(d->state);
1657     delete tmp;
1658 }
1659
1660
1661 /*!
1662
1663     \fn bool QPainter::begin(QPaintDevice *device)
1664
1665     Begins painting the paint \a device and returns true if
1666     successful; otherwise returns false.
1667
1668     Notice that all painter settings (setPen(), setBrush() etc.) are reset
1669     to default values when begin() is called.
1670
1671     The errors that can occur are serious problems, such as these:
1672
1673     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 3
1674
1675     Note that most of the time, you can use one of the constructors
1676     instead of begin(), and that end() is automatically done at
1677     destruction.
1678
1679     \warning A paint device can only be painted by one painter at a
1680     time.
1681
1682     \warning Painting on a QImage with the format
1683     QImage::Format_Indexed8 is not supported.
1684
1685     \sa end(), QPainter()
1686 */
1687
1688 static inline void qt_cleanup_painter_state(QPainterPrivate *d)
1689 {
1690     d->states.clear();
1691     delete d->state;
1692     d->state = 0;
1693     d->engine = 0;
1694     d->device = 0;
1695 }
1696
1697 bool QPainter::begin(QPaintDevice *pd)
1698 {
1699     Q_ASSERT(pd);
1700
1701     if (pd->painters > 0) {
1702         qWarning("QPainter::begin: A paint device can only be painted by one painter at a time.");
1703         return false;
1704     }
1705
1706     if (d_ptr->engine) {
1707         qWarning("QPainter::begin: Painter already active");
1708         return false;
1709     }
1710
1711     if (QPainterPrivate::attachPainterPrivate(this, pd))
1712         return true;
1713
1714     Q_D(QPainter);
1715
1716     d->helper_device = pd;
1717     d->original_device = pd;
1718
1719     QPoint redirectionOffset;
1720     QPaintDevice *rpd = pd->redirected(&redirectionOffset);
1721     if (rpd)
1722         pd = rpd;
1723
1724 #ifdef QT_DEBUG_DRAW
1725     if (qt_show_painter_debug_output)
1726         printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());
1727 #endif
1728
1729     if (pd->devType() == QInternal::Pixmap)
1730         static_cast<QPixmap *>(pd)->detach();
1731     else if (pd->devType() == QInternal::Image)
1732         static_cast<QImage *>(pd)->detach();
1733
1734     d->engine = pd->paintEngine();
1735
1736     if (!d->engine) {
1737         qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());
1738         return false;
1739     }
1740
1741     d->device = pd;
1742
1743     d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0;
1744     if (d->emulationEngine)
1745         d->emulationEngine->real_engine = d->extended;
1746
1747     // Setup new state...
1748     Q_ASSERT(!d->state);
1749     d->state = d->extended ? d->extended->createState(0) : new QPainterState;
1750     d->state->painter = this;
1751     d->states.push_back(d->state);
1752
1753     d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
1754     d->state->brushOrigin = QPointF();
1755
1756     // Slip a painter state into the engine before we do any other operations
1757     if (d->extended)
1758         d->extended->setState(d->state);
1759     else
1760         d->engine->state = d->state;
1761
1762     switch (pd->devType()) {
1763 #if 0
1764         // is this needed any more??
1765         case QInternal::Widget:
1766         {
1767             const QWidget *widget = static_cast<const QWidget *>(pd);
1768             Q_ASSERT(widget);
1769
1770             const bool paintOutsidePaintEvent = widget->testAttribute(Qt::WA_PaintOutsidePaintEvent);
1771             const bool inPaintEvent = widget->testAttribute(Qt::WA_WState_InPaintEvent);
1772
1773             // Adjust offset for alien widgets painting outside the paint event.
1774             if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
1775                 && widget->testAttribute(Qt::WA_WState_Created)) {
1776                 const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
1777                 d->state->redirectionMatrix.translate(offset.x(), offset.y());
1778             }
1779             break;
1780         }
1781 #endif
1782         case QInternal::Pixmap:
1783         {
1784             QPixmap *pm = static_cast<QPixmap *>(pd);
1785             Q_ASSERT(pm);
1786             if (pm->isNull()) {
1787                 qWarning("QPainter::begin: Cannot paint on a null pixmap");
1788                 qt_cleanup_painter_state(d);
1789                 return false;
1790             }
1791
1792             if (pm->depth() == 1) {
1793                 d->state->pen = QPen(Qt::color1);
1794                 d->state->brush = QBrush(Qt::color0);
1795             }
1796             break;
1797         }
1798         case QInternal::Image:
1799         {
1800             QImage *img = static_cast<QImage *>(pd);
1801             Q_ASSERT(img);
1802             if (img->isNull()) {
1803                 qWarning("QPainter::begin: Cannot paint on a null image");
1804                 qt_cleanup_painter_state(d);
1805                 return false;
1806             } else if (img->format() == QImage::Format_Indexed8) {
1807                 // Painting on indexed8 images is not supported.
1808                 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
1809                 qt_cleanup_painter_state(d);
1810                 return false;
1811             }
1812             if (img->depth() == 1) {
1813                 d->state->pen = QPen(Qt::color1);
1814                 d->state->brush = QBrush(Qt::color0);
1815             }
1816             break;
1817         }
1818         default:
1819             break;
1820     }
1821     if (d->state->ww == 0) // For compat with 3.x painter defaults
1822         d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024;
1823
1824     d->engine->setPaintDevice(pd);
1825
1826     bool begun = d->engine->begin(pd);
1827     if (!begun) {
1828         qWarning("QPainter::begin(): Returned false");
1829         if (d->engine->isActive()) {
1830             end();
1831         } else {
1832             qt_cleanup_painter_state(d);
1833         }
1834         return false;
1835     } else {
1836         d->engine->setActive(begun);
1837     }
1838
1839     // Copy painter properties from original paint device,
1840     // required for QPixmap::grabWidget()
1841     if (d->original_device->devType() == QInternal::Widget) {
1842         initFrom(d->original_device);
1843     } else {
1844         d->state->layoutDirection = Qt::LayoutDirectionAuto;
1845         // make sure we have a font compatible with the paintdevice
1846         d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
1847     }
1848
1849     QRect systemRect = d->engine->systemRect();
1850     if (!systemRect.isEmpty()) {
1851         d->state->ww = d->state->vw = systemRect.width();
1852         d->state->wh = d->state->vh = systemRect.height();
1853     } else {
1854         d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth);
1855         d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
1856     }
1857
1858     const QPoint coordinateOffset = d->engine->coordinateOffset();
1859     d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
1860
1861     Q_ASSERT(d->engine->isActive());
1862
1863     if (!d->state->redirectionMatrix.isIdentity())
1864         d->updateMatrix();
1865
1866     Q_ASSERT(d->engine->isActive());
1867     d->state->renderHints = QPainter::TextAntialiasing;
1868     ++d->device->painters;
1869
1870     d->state->emulationSpecifier = 0;
1871
1872     return true;
1873 }
1874
1875 /*!
1876     Ends painting. Any resources used while painting are released. You
1877     don't normally need to call this since it is called by the
1878     destructor.
1879
1880     Returns true if the painter is no longer active; otherwise returns false.
1881
1882     \sa begin(), isActive()
1883 */
1884
1885 bool QPainter::end()
1886 {
1887 #ifdef QT_DEBUG_DRAW
1888     if (qt_show_painter_debug_output)
1889         printf("QPainter::end()\n");
1890 #endif
1891     Q_D(QPainter);
1892
1893     if (!d->engine) {
1894         qWarning("QPainter::end: Painter not active, aborted");
1895         qt_cleanup_painter_state(d);
1896         return false;
1897     }
1898
1899     if (d->refcount > 1) {
1900         d->detachPainterPrivate(this);
1901         return true;
1902     }
1903
1904     bool ended = true;
1905
1906     if (d->engine->isActive()) {
1907         ended = d->engine->end();
1908         d->updateState(0);
1909
1910         --d->device->painters;
1911         if (d->device->painters == 0) {
1912             d->engine->setPaintDevice(0);
1913             d->engine->setActive(false);
1914         }
1915     }
1916
1917     if (d->states.size() > 1) {
1918         qWarning("QPainter::end: Painter ended with %d saved states",
1919                  d->states.size());
1920     }
1921
1922     if (d->engine->autoDestruct()) {
1923         delete d->engine;
1924     }
1925
1926     if (d->emulationEngine) {
1927         delete d->emulationEngine;
1928         d->emulationEngine = 0;
1929     }
1930
1931     if (d->extended) {
1932         d->extended = 0;
1933     }
1934
1935     qt_cleanup_painter_state(d);
1936
1937     return ended;
1938 }
1939
1940
1941 /*!
1942     Returns the paint engine that the painter is currently operating
1943     on if the painter is active; otherwise 0.
1944
1945     \sa isActive()
1946 */
1947 QPaintEngine *QPainter::paintEngine() const
1948 {
1949     Q_D(const QPainter);
1950     return d->engine;
1951 }
1952
1953 /*!
1954     \since 4.6
1955
1956     Flushes the painting pipeline and prepares for the user issuing commands
1957     directly to the underlying graphics context. Must be followed by a call to
1958     endNativePainting().
1959
1960     Note that only the states the underlying paint engine changes will be reset
1961     to their respective default states. The states we reset may change from
1962     release to release. The following states are currently reset in the OpenGL
1963     2 engine:
1964
1965     \list
1966     \li blending is disabled
1967     \li the depth, stencil and scissor tests are disabled
1968     \li the active texture unit is reset to 0
1969     \li the depth mask, depth function and the clear depth are reset to their
1970     default values
1971     \li the stencil mask, stencil operation and stencil function are reset to
1972     their default values
1973      \li the current color is reset to solid white
1974     \endlist
1975
1976     If, for example, the OpenGL polygon mode is changed by the user inside a
1977     beginNativePaint()/endNativePainting() block, it will not be reset to the
1978     default state by endNativePainting(). Here is an example that shows
1979     intermixing of painter commands and raw OpenGL commands:
1980
1981     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
1982
1983     \sa endNativePainting()
1984 */
1985 void QPainter::beginNativePainting()
1986 {
1987     Q_D(QPainter);
1988     if (!d->engine) {
1989         qWarning("QPainter::beginNativePainting: Painter not active");
1990         return;
1991     }
1992
1993     if (d->extended)
1994         d->extended->beginNativePainting();
1995 }
1996
1997 /*!
1998     \since 4.6
1999
2000     Restores the painter after manually issuing native painting commands. Lets
2001     the painter restore any native state that it relies on before calling any
2002     other painter commands.
2003
2004     \sa beginNativePainting()
2005 */
2006 void QPainter::endNativePainting()
2007 {
2008     Q_D(const QPainter);
2009     if (!d->engine) {
2010         qWarning("QPainter::beginNativePainting: Painter not active");
2011         return;
2012     }
2013
2014     if (d->extended)
2015         d->extended->endNativePainting();
2016     else
2017         d->engine->syncState();
2018 }
2019
2020 /*!
2021     Returns the font metrics for the painter if the painter is
2022     active. Otherwise, the return value is undefined.
2023
2024     \sa font(), isActive(), {QPainter#Settings}{Settings}
2025 */
2026
2027 QFontMetrics QPainter::fontMetrics() const
2028 {
2029     Q_D(const QPainter);
2030     if (!d->engine) {
2031         qWarning("QPainter::fontMetrics: Painter not active");
2032         return QFontMetrics(QFont());
2033     }
2034     return QFontMetrics(d->state->font);
2035 }
2036
2037
2038 /*!
2039     Returns the font info for the painter if the painter is
2040     active. Otherwise, the return value is undefined.
2041
2042     \sa font(), isActive(), {QPainter#Settings}{Settings}
2043 */
2044
2045 QFontInfo QPainter::fontInfo() const
2046 {
2047     Q_D(const QPainter);
2048     if (!d->engine) {
2049         qWarning("QPainter::fontInfo: Painter not active");
2050         return QFontInfo(QFont());
2051     }
2052     return QFontInfo(d->state->font);
2053 }
2054
2055 /*!
2056     \since 4.2
2057
2058     Returns the opacity of the painter. The default value is
2059     1.
2060 */
2061
2062 qreal QPainter::opacity() const
2063 {
2064     Q_D(const QPainter);
2065     if (!d->engine) {
2066         qWarning("QPainter::opacity: Painter not active");
2067         return 1.0;
2068     }
2069     return d->state->opacity;
2070 }
2071
2072 /*!
2073     \since 4.2
2074
2075     Sets the opacity of the painter to \a opacity. The value should
2076     be in the range 0.0 to 1.0, where 0.0 is fully transparent and
2077     1.0 is fully opaque.
2078
2079     Opacity set on the painter will apply to all drawing operations
2080     individually.
2081 */
2082
2083 void QPainter::setOpacity(qreal opacity)
2084 {
2085     Q_D(QPainter);
2086
2087     if (!d->engine) {
2088         qWarning("QPainter::setOpacity: Painter not active");
2089         return;
2090     }
2091
2092     opacity = qMin(qreal(1), qMax(qreal(0), opacity));
2093
2094     if (opacity == d->state->opacity)
2095         return;
2096
2097     d->state->opacity = opacity;
2098
2099     if (d->extended)
2100         d->extended->opacityChanged();
2101     else
2102         d->state->dirtyFlags |= QPaintEngine::DirtyOpacity;
2103 }
2104
2105
2106 /*!
2107     Returns the currently set brush origin.
2108
2109     \sa setBrushOrigin(), {QPainter#Settings}{Settings}
2110 */
2111
2112 QPoint QPainter::brushOrigin() const
2113 {
2114     Q_D(const QPainter);
2115     if (!d->engine) {
2116         qWarning("QPainter::brushOrigin: Painter not active");
2117         return QPoint();
2118     }
2119     return QPointF(d->state->brushOrigin).toPoint();
2120 }
2121
2122 /*!
2123     \fn void QPainter::setBrushOrigin(const QPointF &position)
2124
2125     Sets the brush origin to \a position.
2126
2127     The brush origin specifies the (0, 0) coordinate of the painter's
2128     brush.
2129
2130     Note that while the brushOrigin() was necessary to adopt the
2131     parent's background for a widget in Qt 3, this is no longer the
2132     case since the Qt 4 painter doesn't paint the background unless
2133     you explicitly tell it to do so by setting the widget's \l
2134     {QWidget::autoFillBackground}{autoFillBackground} property to
2135     true.
2136
2137     \sa brushOrigin(), {QPainter#Settings}{Settings}
2138 */
2139
2140 void QPainter::setBrushOrigin(const QPointF &p)
2141 {
2142     Q_D(QPainter);
2143 #ifdef QT_DEBUG_DRAW
2144     if (qt_show_painter_debug_output)
2145         printf("QPainter::setBrushOrigin(), (%.2f,%.2f)\n", p.x(), p.y());
2146 #endif
2147
2148     if (!d->engine) {
2149         qWarning("QPainter::setBrushOrigin: Painter not active");
2150         return;
2151     }
2152
2153     d->state->brushOrigin = p;
2154
2155     if (d->extended) {
2156         d->extended->brushOriginChanged();
2157         return;
2158     }
2159
2160     d->state->dirtyFlags |= QPaintEngine::DirtyBrushOrigin;
2161 }
2162
2163 /*!
2164     \fn void QPainter::setBrushOrigin(const QPoint &position)
2165     \overload
2166
2167     Sets the brush's origin to the given \a position.
2168 */
2169
2170 /*!
2171     \fn void QPainter::setBrushOrigin(int x, int y)
2172
2173     \overload
2174
2175     Sets the brush's origin to point (\a x, \a y).
2176 */
2177
2178 /*!
2179     \enum QPainter::CompositionMode
2180
2181     Defines the modes supported for digital image compositing.
2182     Composition modes are used to specify how the pixels in one image,
2183     the source, are merged with the pixel in another image, the
2184     destination.
2185
2186     Please note that the bitwise raster operation modes, denoted with
2187     a RasterOp prefix, are only natively supported in the X11 and
2188     raster paint engines. This means that the only way to utilize
2189     these modes on the Mac is via a QImage. The RasterOp denoted blend
2190     modes are \e not supported for pens and brushes with alpha
2191     components. Also, turning on the QPainter::Antialiasing render
2192     hint will effectively disable the RasterOp modes.
2193
2194
2195      \image qpainter-compositionmode1.png
2196      \image qpainter-compositionmode2.png
2197
2198     The most common type is SourceOver (often referred to as just
2199     alpha blending) where the source pixel is blended on top of the
2200     destination pixel in such a way that the alpha component of the
2201     source defines the translucency of the pixel.
2202
2203     When the paint device is a QImage, the image format must be set to
2204     \l {QImage::Format}{Format_ARGB32_Premultiplied} or
2205     \l {QImage::Format}{Format_ARGB32} for the composition modes to have
2206     any effect. For performance the premultiplied version is the preferred
2207     format.
2208
2209     When a composition mode is set it applies to all painting
2210     operator, pens, brushes, gradients and pixmap/image drawing.
2211
2212     \value CompositionMode_SourceOver This is the default mode. The
2213     alpha of the source is used to blend the pixel on top of the
2214     destination.
2215
2216     \value CompositionMode_DestinationOver The alpha of the
2217     destination is used to blend it on top of the source pixels. This
2218     mode is the inverse of CompositionMode_SourceOver.
2219
2220     \value CompositionMode_Clear The pixels in the destination are
2221     cleared (set to fully transparent) independent of the source.
2222
2223     \value CompositionMode_Source The output is the source
2224     pixel. (This means a basic copy operation and is identical to
2225     SourceOver when the source pixel is opaque).
2226
2227     \value CompositionMode_Destination The output is the destination
2228     pixel. This means that the blending has no effect. This mode is
2229     the inverse of CompositionMode_Source.
2230
2231     \value CompositionMode_SourceIn The output is the source, where
2232     the alpha is reduced by that of the destination.
2233
2234     \value CompositionMode_DestinationIn The output is the
2235     destination, where the alpha is reduced by that of the
2236     source. This mode is the inverse of CompositionMode_SourceIn.
2237
2238     \value CompositionMode_SourceOut The output is the source, where
2239     the alpha is reduced by the inverse of destination.
2240
2241     \value CompositionMode_DestinationOut The output is the
2242     destination, where the alpha is reduced by the inverse of the
2243     source. This mode is the inverse of CompositionMode_SourceOut.
2244
2245     \value CompositionMode_SourceAtop The source pixel is blended on
2246     top of the destination, with the alpha of the source pixel reduced
2247     by the alpha of the destination pixel.
2248
2249     \value CompositionMode_DestinationAtop The destination pixel is
2250     blended on top of the source, with the alpha of the destination
2251     pixel is reduced by the alpha of the destination pixel. This mode
2252     is the inverse of CompositionMode_SourceAtop.
2253
2254     \value CompositionMode_Xor The source, whose alpha is reduced with
2255     the inverse of the destination alpha, is merged with the
2256     destination, whose alpha is reduced by the inverse of the source
2257     alpha. CompositionMode_Xor is not the same as the bitwise Xor.
2258
2259     \value CompositionMode_Plus Both the alpha and color of the source
2260     and destination pixels are added together.
2261
2262     \value CompositionMode_Multiply The output is the source color
2263     multiplied by the destination. Multiplying a color with white
2264     leaves the color unchanged, while multiplying a color
2265     with black produces black.
2266
2267     \value CompositionMode_Screen The source and destination colors
2268     are inverted and then multiplied. Screening a color with white
2269     produces white, whereas screening a color with black leaves the
2270     color unchanged.
2271
2272     \value CompositionMode_Overlay Multiplies or screens the colors
2273     depending on the destination color. The destination color is mixed
2274     with the source color to reflect the lightness or darkness of the
2275     destination.
2276
2277     \value CompositionMode_Darken The darker of the source and
2278     destination colors is selected.
2279
2280     \value CompositionMode_Lighten The lighter of the source and
2281     destination colors is selected.
2282
2283     \value CompositionMode_ColorDodge The destination color is
2284     brightened to reflect the source color. A black source color
2285     leaves the destination color unchanged.
2286
2287     \value CompositionMode_ColorBurn The destination color is darkened
2288     to reflect the source color. A white source color leaves the
2289     destination color unchanged.
2290
2291     \value CompositionMode_HardLight Multiplies or screens the colors
2292     depending on the source color. A light source color will lighten
2293     the destination color, whereas a dark source color will darken the
2294     destination color.
2295
2296     \value CompositionMode_SoftLight Darkens or lightens the colors
2297     depending on the source color. Similar to
2298     CompositionMode_HardLight.
2299
2300     \value CompositionMode_Difference Subtracts the darker of the
2301     colors from the lighter.  Painting with white inverts the
2302     destination color, whereas painting with black leaves the
2303     destination color unchanged.
2304
2305     \value CompositionMode_Exclusion Similar to
2306     CompositionMode_Difference, but with a lower contrast. Painting
2307     with white inverts the destination color, whereas painting with
2308     black leaves the destination color unchanged.
2309
2310     \value RasterOp_SourceOrDestination Does a bitwise OR operation on
2311     the source and destination pixels (src OR dst).
2312
2313     \value RasterOp_SourceAndDestination Does a bitwise AND operation
2314     on the source and destination pixels (src AND dst).
2315
2316     \value RasterOp_SourceXorDestination Does a bitwise XOR operation
2317     on the source and destination pixels (src XOR dst).
2318
2319     \value RasterOp_NotSourceAndNotDestination Does a bitwise NOR
2320     operation on the source and destination pixels ((NOT src) AND (NOT
2321     dst)).
2322
2323     \value RasterOp_NotSourceOrNotDestination Does a bitwise NAND
2324     operation on the source and destination pixels ((NOT src) OR (NOT
2325     dst)).
2326
2327     \value RasterOp_NotSourceXorDestination Does a bitwise operation
2328     where the source pixels are inverted and then XOR'ed with the
2329     destination ((NOT src) XOR dst).
2330
2331     \value RasterOp_NotSource Does a bitwise operation where the
2332     source pixels are inverted (NOT src).
2333
2334     \value RasterOp_NotSourceAndDestination Does a bitwise operation
2335     where the source is inverted and then AND'ed with the destination
2336     ((NOT src) AND dst).
2337
2338     \value RasterOp_SourceAndNotDestination Does a bitwise operation
2339     where the source is AND'ed with the inverted destination pixels
2340     (src AND (NOT dst)).
2341
2342     \sa compositionMode(), setCompositionMode(), {QPainter#Composition
2343     Modes}{Composition Modes}, {Image Composition Example}
2344 */
2345
2346 /*!
2347     Sets the composition mode to the given \a mode.
2348
2349     \warning Only a QPainter operating on a QImage fully supports all
2350     composition modes. The RasterOp modes are supported for X11 as
2351     described in compositionMode().
2352
2353     \sa compositionMode()
2354 */
2355 void QPainter::setCompositionMode(CompositionMode mode)
2356 {
2357     Q_D(QPainter);
2358     if (!d->engine) {
2359         qWarning("QPainter::setCompositionMode: Painter not active");
2360         return;
2361     }
2362     if (d->state->composition_mode == mode)
2363         return;
2364     if (d->extended) {
2365         d->state->composition_mode = mode;
2366         d->extended->compositionModeChanged();
2367         return;
2368     }
2369
2370     if (mode >= QPainter::RasterOp_SourceOrDestination) {
2371         if (!d->engine->hasFeature(QPaintEngine::RasterOpModes)) {
2372             qWarning("QPainter::setCompositionMode: "
2373                      "Raster operation modes not supported on device");
2374             return;
2375         }
2376     } else if (mode >= QPainter::CompositionMode_Plus) {
2377         if (!d->engine->hasFeature(QPaintEngine::BlendModes)) {
2378             qWarning("QPainter::setCompositionMode: "
2379                      "Blend modes not supported on device");
2380             return;
2381         }
2382     } else if (!d->engine->hasFeature(QPaintEngine::PorterDuff)) {
2383         if (mode != CompositionMode_Source && mode != CompositionMode_SourceOver) {
2384             qWarning("QPainter::setCompositionMode: "
2385                      "PorterDuff modes not supported on device");
2386             return;
2387         }
2388     }
2389
2390     d->state->composition_mode = mode;
2391     d->state->dirtyFlags |= QPaintEngine::DirtyCompositionMode;
2392 }
2393
2394 /*!
2395   Returns the current composition mode.
2396
2397   \sa CompositionMode, setCompositionMode()
2398 */
2399 QPainter::CompositionMode QPainter::compositionMode() const
2400 {
2401     Q_D(const QPainter);
2402     if (!d->engine) {
2403         qWarning("QPainter::compositionMode: Painter not active");
2404         return QPainter::CompositionMode_SourceOver;
2405     }
2406     return d->state->composition_mode;
2407 }
2408
2409 /*!
2410     Returns the current background brush.
2411
2412     \sa setBackground(), {QPainter#Settings}{Settings}
2413 */
2414
2415 const QBrush &QPainter::background() const
2416 {
2417     Q_D(const QPainter);
2418     if (!d->engine) {
2419         qWarning("QPainter::background: Painter not active");
2420         return d->fakeState()->brush;
2421     }
2422     return d->state->bgBrush;
2423 }
2424
2425
2426 /*!
2427     Returns true if clipping has been set; otherwise returns false.
2428
2429     \sa setClipping(), {QPainter#Clipping}{Clipping}
2430 */
2431
2432 bool QPainter::hasClipping() const
2433 {
2434     Q_D(const QPainter);
2435     if (!d->engine) {
2436         qWarning("QPainter::hasClipping: Painter not active");
2437         return false;
2438     }
2439     return d->state->clipEnabled && d->state->clipOperation != Qt::NoClip;
2440 }
2441
2442
2443 /*!
2444     Enables clipping if  \a enable is true, or disables clipping if  \a
2445     enable is false.
2446
2447     \sa hasClipping(), {QPainter#Clipping}{Clipping}
2448 */
2449
2450 void QPainter::setClipping(bool enable)
2451 {
2452     Q_D(QPainter);
2453 #ifdef QT_DEBUG_DRAW
2454     if (qt_show_painter_debug_output)
2455         printf("QPainter::setClipping(), enable=%s, was=%s\n",
2456                enable ? "on" : "off",
2457                hasClipping() ? "on" : "off");
2458 #endif
2459     if (!d->engine) {
2460         qWarning("QPainter::setClipping: Painter not active, state will be reset by begin");
2461         return;
2462     }
2463
2464     if (hasClipping() == enable)
2465         return;
2466
2467     // we can't enable clipping if we don't have a clip
2468     if (enable
2469         && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
2470         return;
2471     d->state->clipEnabled = enable;
2472
2473     if (d->extended) {
2474         d->extended->clipEnabledChanged();
2475         return;
2476     }
2477
2478     d->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled;
2479     d->updateState(d->state);
2480 }
2481
2482
2483 /*!
2484     Returns the currently set clip region. Note that the clip region
2485     is given in logical coordinates.
2486
2487     \warning QPainter does not store the combined clip explicitly as
2488     this is handled by the underlying QPaintEngine, so the path is
2489     recreated on demand and transformed to the current logical
2490     coordinate system. This is potentially an expensive operation.
2491
2492     \sa setClipRegion(), clipPath(), setClipping()
2493 */
2494
2495 QRegion QPainter::clipRegion() const
2496 {
2497     Q_D(const QPainter);
2498     if (!d->engine) {
2499         qWarning("QPainter::clipRegion: Painter not active");
2500         return QRegion();
2501     }
2502
2503     QRegion region;
2504     bool lastWasNothing = true;
2505
2506     if (!d->txinv)
2507         const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2508
2509     // ### Falcon: Use QPainterPath
2510     for (int i=0; i<d->state->clipInfo.size(); ++i) {
2511         const QPainterClipInfo &info = d->state->clipInfo.at(i);
2512         switch (info.clipType) {
2513
2514         case QPainterClipInfo::RegionClip: {
2515             QTransform matrix = (info.matrix * d->invMatrix);
2516             if (lastWasNothing) {
2517                 region = info.region * matrix;
2518                 lastWasNothing = false;
2519                 continue;
2520             }
2521             if (info.operation == Qt::IntersectClip)
2522                 region &= info.region * matrix;
2523             else if (info.operation == Qt::NoClip) {
2524                 lastWasNothing = true;
2525                 region = QRegion();
2526             } else
2527                 region = info.region * matrix;
2528             break;
2529         }
2530
2531         case QPainterClipInfo::PathClip: {
2532             QTransform matrix = (info.matrix * d->invMatrix);
2533             if (lastWasNothing) {
2534                 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2535                                  info.path.fillRule());
2536                 lastWasNothing = false;
2537                 continue;
2538             }
2539             if (info.operation == Qt::IntersectClip) {
2540                 region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2541                                   info.path.fillRule());
2542             } else if (info.operation == Qt::NoClip) {
2543                 lastWasNothing = true;
2544                 region = QRegion();
2545             } else {
2546                 region = QRegion((info.path * matrix).toFillPolygon().toPolygon(),
2547                                  info.path.fillRule());
2548             }
2549             break;
2550         }
2551
2552         case QPainterClipInfo::RectClip: {
2553             QTransform matrix = (info.matrix * d->invMatrix);
2554             if (lastWasNothing) {
2555                 region = QRegion(info.rect) * matrix;
2556                 lastWasNothing = false;
2557                 continue;
2558             }
2559             if (info.operation == Qt::IntersectClip) {
2560                 // Use rect intersection if possible.
2561                 if (matrix.type() <= QTransform::TxScale)
2562                     region &= matrix.mapRect(info.rect);
2563                 else
2564                     region &= matrix.map(QRegion(info.rect));
2565             } else if (info.operation == Qt::NoClip) {
2566                 lastWasNothing = true;
2567                 region = QRegion();
2568             } else {
2569                 region = QRegion(info.rect) * matrix;
2570             }
2571             break;
2572         }
2573
2574         case QPainterClipInfo::RectFClip: {
2575             QTransform matrix = (info.matrix * d->invMatrix);
2576             if (lastWasNothing) {
2577                 region = QRegion(info.rectf.toRect()) * matrix;
2578                 lastWasNothing = false;
2579                 continue;
2580             }
2581             if (info.operation == Qt::IntersectClip) {
2582                 // Use rect intersection if possible.
2583                 if (matrix.type() <= QTransform::TxScale)
2584                     region &= matrix.mapRect(info.rectf.toRect());
2585                 else
2586                     region &= matrix.map(QRegion(info.rectf.toRect()));
2587             } else if (info.operation == Qt::NoClip) {
2588                 lastWasNothing = true;
2589                 region = QRegion();
2590             } else {
2591                 region = QRegion(info.rectf.toRect()) * matrix;
2592             }
2593             break;
2594         }
2595         }
2596     }
2597
2598     return region;
2599 }
2600
2601 extern QPainterPath qt_regionToPath(const QRegion &region);
2602
2603 /*!
2604     Returns the currently clip as a path. Note that the clip path is
2605     given in logical coordinates.
2606
2607     \warning QPainter does not store the combined clip explicitly as
2608     this is handled by the underlying QPaintEngine, so the path is
2609     recreated on demand and transformed to the current logical
2610     coordinate system. This is potentially an expensive operation.
2611
2612     \sa setClipPath(), clipRegion(), setClipping()
2613 */
2614 QPainterPath QPainter::clipPath() const
2615 {
2616     Q_D(const QPainter);
2617
2618     // ### Since we do not support path intersections and path unions yet,
2619     // we just use clipRegion() here...
2620     if (!d->engine) {
2621         qWarning("QPainter::clipPath: Painter not active");
2622         return QPainterPath();
2623     }
2624
2625     // No clip, return empty
2626     if (d->state->clipInfo.size() == 0) {
2627         return QPainterPath();
2628     } else {
2629
2630         // Update inverse matrix, used below.
2631         if (!d->txinv)
2632             const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2633
2634         // For the simple case avoid conversion.
2635         if (d->state->clipInfo.size() == 1
2636             && d->state->clipInfo.at(0).clipType == QPainterClipInfo::PathClip) {
2637             QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2638             return d->state->clipInfo.at(0).path * matrix;
2639
2640         } else if (d->state->clipInfo.size() == 1
2641                    && d->state->clipInfo.at(0).clipType == QPainterClipInfo::RectClip) {
2642             QTransform matrix = (d->state->clipInfo.at(0).matrix * d->invMatrix);
2643             QPainterPath path;
2644             path.addRect(d->state->clipInfo.at(0).rect);
2645             return path * matrix;
2646         } else {
2647             // Fallback to clipRegion() for now, since we don't have isect/unite for paths
2648             return qt_regionToPath(clipRegion());
2649         }
2650     }
2651 }
2652
2653 /*!
2654     Returns the bounding rectangle of the current clip if there is a clip;
2655     otherwise returns an empty rectangle. Note that the clip region is
2656     given in logical coordinates.
2657
2658     The bounding rectangle is not guaranteed to be tight.
2659
2660     \sa setClipRect(), setClipPath(), setClipRegion()
2661
2662     \since 4.8
2663  */
2664
2665 QRectF QPainter::clipBoundingRect() const
2666 {
2667     Q_D(const QPainter);
2668
2669     if (!d->engine) {
2670         qWarning("QPainter::clipBoundingRect: Painter not active");
2671         return QRectF();
2672     }
2673
2674     // Accumulate the bounding box in device space. This is not 100%
2675     // precise, but it fits within the guarantee and it is reasonably
2676     // fast.
2677     QRectF bounds;
2678     for (int i=0; i<d->state->clipInfo.size(); ++i) {
2679          QRectF r;
2680          const QPainterClipInfo &info = d->state->clipInfo.at(i);
2681
2682          if (info.clipType == QPainterClipInfo::RectClip)
2683              r = info.rect;
2684          else if (info.clipType == QPainterClipInfo::RectFClip)
2685              r = info.rectf;
2686          else if (info.clipType == QPainterClipInfo::RegionClip)
2687              r = info.region.boundingRect();
2688          else
2689              r = info.path.boundingRect();
2690
2691          r = info.matrix.mapRect(r);
2692
2693          if (i == 0)
2694              bounds = r;
2695          else if (info.operation == Qt::IntersectClip)
2696              bounds &= r;
2697     }
2698
2699
2700     // Map the rectangle back into logical space using the inverse
2701     // matrix.
2702     if (!d->txinv)
2703         const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
2704
2705     return d->invMatrix.mapRect(bounds);
2706 }
2707
2708 /*!
2709     \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
2710
2711     Enables clipping, and sets the clip region to the given \a
2712     rectangle using the given clip \a operation. The default operation
2713     is to replace the current clip rectangle.
2714
2715     Note that the clip rectangle is specified in logical (painter)
2716     coordinates.
2717
2718     \sa clipRegion(), setClipping(), {QPainter#Clipping}{Clipping}
2719 */
2720 void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
2721 {
2722     Q_D(QPainter);
2723
2724     if (d->extended) {
2725         if ((!d->state->clipEnabled && op != Qt::NoClip))
2726             op = Qt::ReplaceClip;
2727
2728         if (!d->engine) {
2729             qWarning("QPainter::setClipRect: Painter not active");
2730             return;
2731         }
2732         qreal right = rect.x() + rect.width();
2733         qreal bottom = rect.y() + rect.height();
2734         qreal pts[] = { rect.x(), rect.y(),
2735                         right, rect.y(),
2736                         right, bottom,
2737                         rect.x(), bottom };
2738         QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
2739         d->state->clipEnabled = true;
2740         d->extended->clip(vp, op);
2741         if (op == Qt::ReplaceClip || op == Qt::NoClip)
2742             d->state->clipInfo.clear();
2743         d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2744         d->state->clipOperation = op;
2745         return;
2746     }
2747
2748     if (qreal(int(rect.top())) == rect.top()
2749         && qreal(int(rect.bottom())) == rect.bottom()
2750         && qreal(int(rect.left())) == rect.left()
2751         && qreal(int(rect.right())) == rect.right())
2752     {
2753         setClipRect(rect.toRect(), op);
2754         return;
2755     }
2756
2757     if (rect.isEmpty()) {
2758         setClipRegion(QRegion(), op);
2759         return;
2760     }
2761
2762     QPainterPath path;
2763     path.addRect(rect);
2764     setClipPath(path, op);
2765 }
2766
2767 /*!
2768     \fn void QPainter::setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
2769     \overload
2770
2771     Enables clipping, and sets the clip region to the given \a rectangle using the given
2772     clip \a operation.
2773 */
2774 void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
2775 {
2776     Q_D(QPainter);
2777
2778     if (!d->engine) {
2779         qWarning("QPainter::setClipRect: Painter not active");
2780         return;
2781     }
2782
2783     if ((!d->state->clipEnabled && op != Qt::NoClip))
2784         op = Qt::ReplaceClip;
2785
2786     if (d->extended) {
2787         d->state->clipEnabled = true;
2788         d->extended->clip(rect, op);
2789         if (op == Qt::ReplaceClip || op == Qt::NoClip)
2790             d->state->clipInfo.clear();
2791         d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2792         d->state->clipOperation = op;
2793         return;
2794     }
2795
2796     if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2797         op = Qt::ReplaceClip;
2798
2799     d->state->clipRegion = rect;
2800     d->state->clipOperation = op;
2801     if (op == Qt::NoClip || op == Qt::ReplaceClip)
2802         d->state->clipInfo.clear();
2803     d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
2804     d->state->clipEnabled = true;
2805     d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2806     d->updateState(d->state);
2807 }
2808
2809 /*!
2810     \fn void QPainter::setClipRect(int x, int y, int width, int height, Qt::ClipOperation operation)
2811
2812     Enables clipping, and sets the clip region to the rectangle beginning at (\a x, \a y)
2813     with the given \a width and \a height.
2814 */
2815
2816 /*!
2817     \fn void QPainter::setClipRegion(const QRegion &region, Qt::ClipOperation operation)
2818
2819     Sets the clip region to the given \a region using the specified clip
2820     \a operation. The default clip operation is to replace the current
2821     clip region.
2822
2823     Note that the clip region is given in logical coordinates.
2824
2825     \sa clipRegion(), setClipRect(), {QPainter#Clipping}{Clipping}
2826 */
2827 void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
2828 {
2829     Q_D(QPainter);
2830 #ifdef QT_DEBUG_DRAW
2831     QRect rect = r.boundingRect();
2832     if (qt_show_painter_debug_output)
2833         printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n",
2834            r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height());
2835 #endif
2836     if (!d->engine) {
2837         qWarning("QPainter::setClipRegion: Painter not active");
2838         return;
2839     }
2840
2841     if ((!d->state->clipEnabled && op != Qt::NoClip))
2842         op = Qt::ReplaceClip;
2843
2844     if (d->extended) {
2845         d->state->clipEnabled = true;
2846         d->extended->clip(r, op);
2847         if (op == Qt::NoClip || op == Qt::ReplaceClip)
2848             d->state->clipInfo.clear();
2849         d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2850         d->state->clipOperation = op;
2851         return;
2852     }
2853
2854     if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
2855         op = Qt::ReplaceClip;
2856
2857     d->state->clipRegion = r;
2858     d->state->clipOperation = op;
2859     if (op == Qt::NoClip || op == Qt::ReplaceClip)
2860         d->state->clipInfo.clear();
2861     d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
2862     d->state->clipEnabled = true;
2863     d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
2864     d->updateState(d->state);
2865 }
2866
2867 /*!
2868     \since 4.2
2869     \obsolete
2870
2871     Sets the transformation matrix to \a matrix and enables transformations.
2872
2873     \note It is advisable to use setWorldTransform() instead of this function to
2874     preserve the properties of perspective transformations.
2875
2876     If \a combine is true, then \a matrix is combined with the current
2877     transformation matrix; otherwise \a matrix replaces the current
2878     transformation matrix.
2879
2880     If \a matrix is the identity matrix and \a combine is false, this
2881     function calls setWorldMatrixEnabled(false). (The identity matrix is the
2882     matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the
2883     rest are 0.0.)
2884
2885     The following functions can transform the coordinate system without using
2886     a QMatrix:
2887     \list
2888     \li translate()
2889     \li scale()
2890     \li shear()
2891     \li rotate()
2892     \endlist
2893
2894     They operate on the painter's worldMatrix() and are implemented like this:
2895
2896     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 4
2897
2898     Note that when using setWorldMatrix() function you should always have
2899     \a combine be true when you are drawing into a QPicture. Otherwise
2900     it may not be possible to replay the picture with additional
2901     transformations; using the translate(), scale(), etc. convenience
2902     functions is safe.
2903
2904     For more information about the coordinate system, transformations
2905     and window-viewport conversion, see \l {Coordinate System}.
2906
2907     \sa setWorldTransform(), QTransform
2908 */
2909
2910 void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine)
2911 {
2912     setWorldTransform(QTransform(matrix), combine);
2913 }
2914
2915 /*!
2916     \since 4.2
2917     \obsolete
2918
2919     Returns the world transformation matrix.
2920
2921     It is advisable to use worldTransform() because worldMatrix() does not
2922     preserve the properties of perspective transformations.
2923
2924     \sa {QPainter#Coordinate Transformations}{Coordinate Transformations},
2925     {Coordinate System}
2926 */
2927
2928 const QMatrix &QPainter::worldMatrix() const
2929 {
2930     Q_D(const QPainter);
2931     if (!d->engine) {
2932         qWarning("QPainter::worldMatrix: Painter not active");
2933         return d->fakeState()->transform.toAffine();
2934     }
2935     return d->state->worldMatrix.toAffine();
2936 }
2937
2938 /*!
2939     \obsolete
2940
2941     Use setWorldTransform() instead.
2942
2943     \sa setWorldTransform()
2944 */
2945
2946 void QPainter::setMatrix(const QMatrix &matrix, bool combine)
2947 {
2948     setWorldTransform(QTransform(matrix), combine);
2949 }
2950
2951 /*!
2952     \obsolete
2953
2954     Use worldTransform() instead.
2955
2956     \sa worldTransform()
2957 */
2958
2959 const QMatrix &QPainter::matrix() const
2960 {
2961     return worldMatrix();
2962 }
2963
2964
2965 /*!
2966     \since 4.2
2967     \obsolete
2968
2969     Returns the transformation matrix combining the current
2970     window/viewport and world transformation.
2971
2972     It is advisable to use combinedTransform() instead of this
2973     function to preserve the properties of perspective transformations.
2974
2975     \sa setWorldTransform(), setWindow(), setViewport()
2976 */
2977 QMatrix QPainter::combinedMatrix() const
2978 {
2979     return combinedTransform().toAffine();
2980 }
2981
2982
2983 /*!
2984     \obsolete
2985
2986     Returns the matrix that transforms from logical coordinates to
2987     device coordinates of the platform dependent paint device.
2988
2989     \note It is advisable to use deviceTransform() instead of this
2990     function to preserve the properties of perspective transformations.
2991
2992     This function is \e only needed when using platform painting
2993     commands on the platform dependent handle (Qt::HANDLE), and the
2994     platform does not do transformations nativly.
2995
2996     The QPaintEngine::PaintEngineFeature enum can be queried to
2997     determine whether the platform performs the transformations or
2998     not.
2999
3000     \sa worldMatrix(), QPaintEngine::hasFeature(),
3001 */
3002 const QMatrix &QPainter::deviceMatrix() const
3003 {
3004     Q_D(const QPainter);
3005     if (!d->engine) {
3006         qWarning("QPainter::deviceMatrix: Painter not active");
3007         return d->fakeState()->transform.toAffine();
3008     }
3009     return d->state->matrix.toAffine();
3010 }
3011
3012 /*!
3013     \obsolete
3014
3015     Resets any transformations that were made using translate(), scale(),
3016     shear(), rotate(), setWorldMatrix(), setViewport() and
3017     setWindow().
3018
3019     It is advisable to use resetTransform() instead of this function
3020     to preserve the properties of perspective transformations.
3021
3022     \sa {QPainter#Coordinate Transformations}{Coordinate
3023     Transformations}
3024 */
3025
3026 void QPainter::resetMatrix()
3027 {
3028     resetTransform();
3029 }
3030
3031
3032 /*!
3033     \since 4.2
3034
3035     Enables transformations if \a enable is true, or disables
3036     transformations if \a enable is false. The world transformation
3037     matrix is not changed.
3038
3039     \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate
3040     Transformations}{Coordinate Transformations}
3041 */
3042
3043 void QPainter::setWorldMatrixEnabled(bool enable)
3044 {
3045     Q_D(QPainter);
3046 #ifdef QT_DEBUG_DRAW
3047     if (qt_show_painter_debug_output)
3048         printf("QPainter::setMatrixEnabled(), enable=%d\n", enable);
3049 #endif
3050
3051     if (!d->engine) {
3052         qWarning("QPainter::setMatrixEnabled: Painter not active");
3053         return;
3054     }
3055     if (enable == d->state->WxF)
3056         return;
3057
3058     d->state->WxF = enable;
3059     d->updateMatrix();
3060 }
3061
3062 /*!
3063     \since 4.2
3064
3065     Returns true if world transformation is enabled; otherwise returns
3066     false.
3067
3068     \sa setWorldMatrixEnabled(), worldTransform(), {Coordinate System}
3069 */
3070
3071 bool QPainter::worldMatrixEnabled() const
3072 {
3073     Q_D(const QPainter);
3074     if (!d->engine) {
3075         qWarning("QPainter::worldMatrixEnabled: Painter not active");
3076         return false;
3077     }
3078     return d->state->WxF;
3079 }
3080
3081 /*!
3082     \obsolete
3083
3084     Use setWorldMatrixEnabled() instead.
3085
3086     \sa setWorldMatrixEnabled()
3087 */
3088
3089 void QPainter::setMatrixEnabled(bool enable)
3090 {
3091     setWorldMatrixEnabled(enable);
3092 }
3093
3094 /*!
3095     \obsolete
3096
3097     Use worldMatrixEnabled() instead
3098
3099     \sa worldMatrixEnabled()
3100 */
3101
3102 bool QPainter::matrixEnabled() const
3103 {
3104     return worldMatrixEnabled();
3105 }
3106
3107 /*!
3108     Scales the coordinate system by (\a{sx}, \a{sy}).
3109
3110     \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate
3111     Transformations}
3112 */
3113
3114 void QPainter::scale(qreal sx, qreal sy)
3115 {
3116 #ifdef QT_DEBUG_DRAW
3117     if (qt_show_painter_debug_output)
3118         printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3119 #endif
3120     Q_D(QPainter);
3121     if (!d->engine) {
3122         qWarning("QPainter::scale: Painter not active");
3123         return;
3124     }
3125
3126     d->state->worldMatrix.scale(sx,sy);
3127     d->state->WxF = true;
3128     d->updateMatrix();
3129 }
3130
3131 /*!
3132     Shears the coordinate system by (\a{sh}, \a{sv}).
3133
3134     \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3135     Transformations}
3136 */
3137
3138 void QPainter::shear(qreal sh, qreal sv)
3139 {
3140 #ifdef QT_DEBUG_DRAW
3141     if (qt_show_painter_debug_output)
3142         printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3143 #endif
3144     Q_D(QPainter);
3145     if (!d->engine) {
3146         qWarning("QPainter::shear: Painter not active");
3147         return;
3148     }
3149
3150     d->state->worldMatrix.shear(sh, sv);
3151     d->state->WxF = true;
3152     d->updateMatrix();
3153 }
3154
3155 /*!
3156     \fn void QPainter::rotate(qreal angle)
3157
3158     Rotates the coordinate system the given \a angle clockwise.
3159
3160     \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3161     Transformations}
3162 */
3163
3164 void QPainter::rotate(qreal a)
3165 {
3166 #ifdef QT_DEBUG_DRAW
3167     if (qt_show_painter_debug_output)
3168         printf("QPainter::rotate(), angle=%f\n", a);
3169 #endif
3170     Q_D(QPainter);
3171     if (!d->engine) {
3172         qWarning("QPainter::rotate: Painter not active");
3173         return;
3174     }
3175
3176     d->state->worldMatrix.rotate(a);
3177     d->state->WxF = true;
3178     d->updateMatrix();
3179 }
3180
3181 /*!
3182     Translates the coordinate system by the given \a offset; i.e. the
3183     given \a offset is added to points.
3184
3185     \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate
3186     Transformations}
3187 */
3188 void QPainter::translate(const QPointF &offset)
3189 {
3190     qreal dx = offset.x();
3191     qreal dy = offset.y();
3192 #ifdef QT_DEBUG_DRAW
3193     if (qt_show_painter_debug_output)
3194         printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3195 #endif
3196     Q_D(QPainter);
3197     if (!d->engine) {
3198         qWarning("QPainter::translate: Painter not active");
3199         return;
3200     }
3201
3202     d->state->worldMatrix.translate(dx, dy);
3203     d->state->WxF = true;
3204     d->updateMatrix();
3205 }
3206
3207 /*!
3208     \fn void QPainter::translate(const QPoint &offset)
3209     \overload
3210
3211     Translates the coordinate system by the given \a offset.
3212 */
3213
3214 /*!
3215     \fn void QPainter::translate(qreal dx, qreal dy)
3216     \overload
3217
3218     Translates the coordinate system by the vector (\a dx, \a dy).
3219 */
3220
3221 /*!
3222     \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3223
3224     Enables clipping, and sets the clip path for the painter to the
3225     given \a path, with the clip \a operation.
3226
3227     Note that the clip path is specified in logical (painter)
3228     coordinates.
3229
3230     \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3231
3232 */
3233 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3234 {
3235 #ifdef QT_DEBUG_DRAW
3236     if (qt_show_painter_debug_output) {
3237         QRectF b = path.boundingRect();
3238         printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3239                path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3240     }
3241 #endif
3242     Q_D(QPainter);
3243
3244     if (!d->engine) {
3245         qWarning("QPainter::setClipPath: Painter not active");
3246         return;
3247     }
3248
3249     if ((!d->state->clipEnabled && op != Qt::NoClip))
3250         op = Qt::ReplaceClip;
3251
3252     if (d->extended) {
3253         d->state->clipEnabled = true;
3254         d->extended->clip(path, op);
3255         if (op == Qt::NoClip || op == Qt::ReplaceClip)
3256             d->state->clipInfo.clear();
3257         d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3258         d->state->clipOperation = op;
3259         return;
3260     }
3261
3262     if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
3263         op = Qt::ReplaceClip;
3264
3265     d->state->clipPath = path;
3266     d->state->clipOperation = op;
3267     if (op == Qt::NoClip || op == Qt::ReplaceClip)
3268         d->state->clipInfo.clear();
3269     d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3270     d->state->clipEnabled = true;
3271     d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3272     d->updateState(d->state);
3273 }
3274
3275 /*!
3276     Draws the outline (strokes) the path \a path with the pen specified
3277     by \a pen
3278
3279     \sa fillPath(), {QPainter#Drawing}{Drawing}
3280 */
3281 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3282 {
3283     Q_D(QPainter);
3284
3285     if (!d->engine) {
3286         qWarning("QPainter::strokePath: Painter not active");
3287         return;
3288     }
3289
3290     if (path.isEmpty())
3291         return;
3292
3293     if (d->extended) {
3294         const QGradient *g = qpen_brush(pen).gradient();
3295         if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3296             d->extended->stroke(qtVectorPathForPath(path), pen);
3297             return;
3298         }
3299     }
3300
3301     QBrush oldBrush = d->state->brush;
3302     QPen oldPen = d->state->pen;
3303
3304     setPen(pen);
3305     setBrush(Qt::NoBrush);
3306
3307     drawPath(path);
3308
3309     // Reset old state
3310     setPen(oldPen);
3311     setBrush(oldBrush);
3312 }
3313
3314 /*!
3315     Fills the given \a path using the given \a brush. The outline is
3316     not drawn.
3317
3318     Alternatively, you can specify a QColor instead of a QBrush; the
3319     QBrush constructor (taking a QColor argument) will automatically
3320     create a solid pattern brush.
3321
3322     \sa drawPath()
3323 */
3324 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3325 {
3326     Q_D(QPainter);
3327
3328     if (!d->engine) {
3329         qWarning("QPainter::fillPath: Painter not active");
3330         return;
3331     }
3332
3333     if (path.isEmpty())
3334         return;
3335
3336     if (d->extended) {
3337         const QGradient *g = brush.gradient();
3338         if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3339             d->extended->fill(qtVectorPathForPath(path), brush);
3340             return;
3341         }
3342     }
3343
3344     QBrush oldBrush = d->state->brush;
3345     QPen oldPen = d->state->pen;
3346
3347     setPen(Qt::NoPen);
3348     setBrush(brush);
3349
3350     drawPath(path);
3351
3352     // Reset old state
3353     setPen(oldPen);
3354     setBrush(oldBrush);
3355 }
3356
3357 /*!
3358     Draws the given painter \a path using the current pen for outline
3359     and the current brush for filling.
3360
3361     \table 100%
3362     \row
3363     \li \inlineimage qpainter-path.png
3364     \li
3365     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 5
3366     \endtable
3367
3368     \sa {painting/painterpaths}{the Painter Paths
3369     example},{painting/deform}{the Vector Deformation example}
3370 */
3371 void QPainter::drawPath(const QPainterPath &path)
3372 {
3373 #ifdef QT_DEBUG_DRAW
3374     QRectF pathBounds = path.boundingRect();
3375     if (qt_show_painter_debug_output)
3376         printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3377                path.elementCount(),
3378                pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3379 #endif
3380
3381     Q_D(QPainter);
3382
3383     if (!d->engine) {
3384         qWarning("QPainter::drawPath: Painter not active");
3385         return;
3386     }
3387
3388     if (d->extended) {
3389         d->extended->drawPath(path);
3390         return;
3391     }
3392     d->updateState(d->state);
3393
3394     if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3395         d->engine->drawPath(path);
3396     } else {
3397         d->draw_helper(path);
3398     }
3399 }
3400
3401 /*!
3402     \fn void QPainter::drawLine(const QLineF &line)
3403
3404     Draws a line defined by \a line.
3405
3406     \table 100%
3407     \row
3408     \li \inlineimage qpainter-line.png
3409     \li
3410     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 6
3411     \endtable
3412
3413     \sa drawLines(), drawPolyline(), {Coordinate System}
3414 */
3415
3416 /*!
3417     \fn void QPainter::drawLine(const QLine &line)
3418     \overload
3419
3420     Draws a line defined by \a line.
3421 */
3422
3423 /*!
3424     \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3425     \overload
3426
3427     Draws a line from \a p1 to \a p2.
3428 */
3429
3430 /*!
3431     \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3432     \overload
3433
3434     Draws a line from \a p1 to \a p2.
3435 */
3436
3437 /*!
3438     \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3439     \overload
3440
3441     Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3442     current pen position to (\a x2, \a y2).
3443 */
3444
3445 /*!
3446     \fn void QPainter::drawRect(const QRectF &rectangle)
3447
3448     Draws the current \a rectangle with the current pen and brush.
3449
3450     A filled rectangle has a size of \a{rectangle}.size(). A stroked
3451     rectangle has a size of \a{rectangle}.size() plus the pen width.
3452
3453     \table 100%
3454     \row
3455     \li \inlineimage qpainter-rectangle.png
3456     \li
3457     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 7
3458     \endtable
3459
3460     \sa drawRects(), drawPolygon(), {Coordinate System}
3461 */
3462
3463 /*!
3464     \fn void QPainter::drawRect(const QRect &rectangle)
3465
3466     \overload
3467
3468     Draws the current \a rectangle with the current pen and brush.
3469 */
3470
3471 /*!
3472     \fn void QPainter::drawRect(int x, int y, int width, int height)
3473
3474     \overload
3475
3476     Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3477     with the given \a width and \a height.
3478 */
3479
3480 /*!
3481     \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3482
3483     Draws the first \a rectCount of the given \a rectangles using the
3484     current pen and brush.
3485
3486     \sa drawRect()
3487 */
3488 void QPainter::drawRects(const QRectF *rects, int rectCount)
3489 {
3490 #ifdef QT_DEBUG_DRAW
3491     if (qt_show_painter_debug_output)
3492         printf("QPainter::drawRects(), count=%d\n", rectCount);
3493 #endif
3494     Q_D(QPainter);
3495
3496     if (!d->engine) {
3497         qWarning("QPainter::drawRects: Painter not active");
3498         return;
3499     }
3500
3501     if (rectCount <= 0)
3502         return;
3503
3504     if (d->extended) {
3505         d->extended->drawRects(rects, rectCount);
3506         return;
3507     }
3508
3509     d->updateState(d->state);
3510
3511     if (!d->state->emulationSpecifier) {
3512         d->engine->drawRects(rects, rectCount);
3513         return;
3514     }
3515
3516     if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3517         && d->state->matrix.type() == QTransform::TxTranslate) {
3518         for (int i=0; i<rectCount; ++i) {
3519             QRectF r(rects[i].x() + d->state->matrix.dx(),
3520                      rects[i].y() + d->state->matrix.dy(),
3521                      rects[i].width(),
3522                      rects[i].height());
3523             d->engine->drawRects(&r, 1);
3524         }
3525     } else {
3526         if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3527             for (int i=0; i<rectCount; ++i) {
3528                 QPainterPath rectPath;
3529                 rectPath.addRect(rects[i]);
3530                 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3531             }
3532         } else {
3533             QPainterPath rectPath;
3534             for (int i=0; i<rectCount; ++i)
3535                 rectPath.addRect(rects[i]);
3536             d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3537         }
3538     }
3539 }
3540
3541 /*!
3542     \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3543     \overload
3544
3545     Draws the first \a rectCount of the given \a rectangles using the
3546     current pen and brush.
3547 */
3548 void QPainter::drawRects(const QRect *rects, int rectCount)
3549 {
3550 #ifdef QT_DEBUG_DRAW
3551     if (qt_show_painter_debug_output)
3552         printf("QPainter::drawRects(), count=%d\n", rectCount);
3553 #endif
3554     Q_D(QPainter);
3555
3556     if (!d->engine) {
3557         qWarning("QPainter::drawRects: Painter not active");
3558         return;
3559     }
3560
3561     if (rectCount <= 0)
3562         return;
3563
3564     if (d->extended) {
3565         d->extended->drawRects(rects, rectCount);
3566         return;
3567     }
3568
3569     d->updateState(d->state);
3570
3571     if (!d->state->emulationSpecifier) {
3572         d->engine->drawRects(rects, rectCount);
3573         return;
3574     }
3575
3576     if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3577         && d->state->matrix.type() == QTransform::TxTranslate) {
3578         for (int i=0; i<rectCount; ++i) {
3579             QRectF r(rects[i].x() + d->state->matrix.dx(),
3580                      rects[i].y() + d->state->matrix.dy(),
3581                      rects[i].width(),
3582                      rects[i].height());
3583
3584             d->engine->drawRects(&r, 1);
3585         }
3586     } else {
3587         if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3588             for (int i=0; i<rectCount; ++i) {
3589                 QPainterPath rectPath;
3590                 rectPath.addRect(rects[i]);
3591                 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3592             }
3593         } else {
3594             QPainterPath rectPath;
3595             for (int i=0; i<rectCount; ++i)
3596                 rectPath.addRect(rects[i]);
3597
3598             d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3599         }
3600     }
3601 }
3602
3603 /*!
3604     \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3605     \overload
3606
3607     Draws the given \a rectangles using the current pen and brush.
3608 */
3609
3610 /*!
3611     \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3612
3613     \overload
3614
3615     Draws the given \a rectangles using the current pen and brush.
3616 */
3617
3618 /*!
3619   \fn void QPainter::drawPoint(const QPointF &position)
3620
3621     Draws a single point at the given \a position using the current
3622     pen's color.
3623
3624     \sa {Coordinate System}
3625 */
3626
3627 /*!
3628     \fn void QPainter::drawPoint(const QPoint &position)
3629     \overload
3630
3631     Draws a single point at the given \a position using the current
3632     pen's color.
3633 */
3634
3635 /*! \fn void QPainter::drawPoint(int x, int y)
3636
3637     \overload
3638
3639     Draws a single point at position (\a x, \a y).
3640 */
3641
3642 /*!
3643     Draws the first \a pointCount points in the array \a points using
3644     the current pen's color.
3645
3646     \sa {Coordinate System}
3647 */
3648 void QPainter::drawPoints(const QPointF *points, int pointCount)
3649 {
3650 #ifdef QT_DEBUG_DRAW
3651     if (qt_show_painter_debug_output)
3652         printf("QPainter::drawPoints(), count=%d\n", pointCount);
3653 #endif
3654     Q_D(QPainter);
3655
3656     if (!d->engine) {
3657         qWarning("QPainter::drawPoints: Painter not active");
3658         return;
3659     }
3660
3661     if (pointCount <= 0)
3662         return;
3663
3664     if (d->extended) {
3665         d->extended->drawPoints(points, pointCount);
3666         return;
3667     }
3668
3669     d->updateState(d->state);
3670
3671     if (!d->state->emulationSpecifier) {
3672         d->engine->drawPoints(points, pointCount);
3673         return;
3674     }
3675
3676     if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3677         && d->state->matrix.type() == QTransform::TxTranslate) {
3678         // ### use drawPoints function
3679         for (int i=0; i<pointCount; ++i) {
3680             QPointF pt(points[i].x() + d->state->matrix.dx(),
3681                        points[i].y() + d->state->matrix.dy());
3682             d->engine->drawPoints(&pt, 1);
3683         }
3684     } else {
3685         QPen pen = d->state->pen;
3686         bool flat_pen = pen.capStyle() == Qt::FlatCap;
3687         if (flat_pen) {
3688             save();
3689             pen.setCapStyle(Qt::SquareCap);
3690             setPen(pen);
3691         }
3692         QPainterPath path;
3693         for (int i=0; i<pointCount; ++i) {
3694             path.moveTo(points[i].x(), points[i].y());
3695             path.lineTo(points[i].x() + 0.0001, points[i].y());
3696         }
3697         d->draw_helper(path, QPainterPrivate::StrokeDraw);
3698         if (flat_pen)
3699             restore();
3700     }
3701 }
3702
3703 /*!
3704     \overload
3705
3706     Draws the first \a pointCount points in the array \a points using
3707     the current pen's color.
3708 */
3709
3710 void QPainter::drawPoints(const QPoint *points, int pointCount)
3711 {
3712 #ifdef QT_DEBUG_DRAW
3713     if (qt_show_painter_debug_output)
3714         printf("QPainter::drawPoints(), count=%d\n", pointCount);
3715 #endif
3716     Q_D(QPainter);
3717
3718     if (!d->engine) {
3719         qWarning("QPainter::drawPoints: Painter not active");
3720         return;
3721     }
3722
3723     if (pointCount <= 0)
3724         return;
3725
3726     if (d->extended) {
3727         d->extended->drawPoints(points, pointCount);
3728         return;
3729     }
3730
3731     d->updateState(d->state);
3732
3733     if (!d->state->emulationSpecifier) {
3734         d->engine->drawPoints(points, pointCount);
3735         return;
3736     }
3737
3738     if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3739         && d->state->matrix.type() == QTransform::TxTranslate) {
3740         // ### use drawPoints function
3741         for (int i=0; i<pointCount; ++i) {
3742             QPointF pt(points[i].x() + d->state->matrix.dx(),
3743                        points[i].y() + d->state->matrix.dy());
3744             d->engine->drawPoints(&pt, 1);
3745         }
3746     } else {
3747         QPen pen = d->state->pen;
3748         bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3749         if (flat_pen) {
3750             save();
3751             pen.setCapStyle(Qt::SquareCap);
3752             setPen(pen);
3753         }
3754         QPainterPath path;
3755         for (int i=0; i<pointCount; ++i) {
3756             path.moveTo(points[i].x(), points[i].y());
3757             path.lineTo(points[i].x() + 0.0001, points[i].y());
3758         }
3759         d->draw_helper(path, QPainterPrivate::StrokeDraw);
3760         if (flat_pen)
3761             restore();
3762     }
3763 }
3764
3765 /*!
3766     \fn void QPainter::drawPoints(const QPolygonF &points)
3767
3768     \overload
3769
3770     Draws the points in the vector  \a points.
3771 */
3772
3773 /*!
3774     \fn void QPainter::drawPoints(const QPolygon &points)
3775
3776     \overload
3777
3778     Draws the points in the vector  \a points.
3779 */
3780
3781 /*!
3782     Sets the background mode of the painter to the given \a mode
3783
3784     Qt::TransparentMode (the default) draws stippled lines and text
3785     without setting the background pixels.  Qt::OpaqueMode fills these
3786     space with the current background color.
3787
3788     Note that in order to draw a bitmap or pixmap transparently, you
3789     must use QPixmap::setMask().
3790
3791     \sa backgroundMode(), setBackground(),
3792     {QPainter#Settings}{Settings}
3793 */
3794
3795 void QPainter::setBackgroundMode(Qt::BGMode mode)
3796 {
3797 #ifdef QT_DEBUG_DRAW
3798     if (qt_show_painter_debug_output)
3799         printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3800 #endif
3801
3802     Q_D(QPainter);
3803     if (!d->engine) {
3804         qWarning("QPainter::setBackgroundMode: Painter not active");
3805         return;
3806     }
3807     if (d->state->bgMode == mode)
3808         return;
3809
3810     d->state->bgMode = mode;
3811     if (d->extended) {
3812         d->checkEmulation();
3813     } else {
3814         d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3815     }
3816 }
3817
3818 /*!
3819     Returns the current background mode.
3820
3821     \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3822 */
3823 Qt::BGMode QPainter::backgroundMode() const
3824 {
3825     Q_D(const QPainter);
3826     if (!d->engine) {
3827         qWarning("QPainter::backgroundMode: Painter not active");
3828         return Qt::TransparentMode;
3829     }
3830     return d->state->bgMode;
3831 }
3832
3833
3834 /*!
3835     \overload
3836
3837     Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3838     specified \a color.
3839 */
3840
3841 void QPainter::setPen(const QColor &color)
3842 {
3843 #ifdef QT_DEBUG_DRAW
3844     if (qt_show_painter_debug_output)
3845         printf("QPainter::setPen(), color=%04x\n", color.rgb());
3846 #endif
3847     Q_D(QPainter);
3848     if (!d->engine) {
3849         qWarning("QPainter::setPen: Painter not active");
3850         return;
3851     }
3852
3853     if (d->state->pen.style() == Qt::SolidLine
3854         && d->state->pen.widthF() == 0
3855         && d->state->pen.isSolid()
3856         && d->state->pen.color() == color)
3857         return;
3858
3859     QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
3860
3861     d->state->pen = pen;
3862     if (d->extended)
3863         d->extended->penChanged();
3864     else
3865         d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3866 }
3867
3868 /*!
3869     Sets the painter's pen to be the given \a pen.
3870
3871     The \a pen defines how to draw lines and outlines, and it also
3872     defines the text color.
3873
3874     \sa pen(), {QPainter#Settings}{Settings}
3875 */
3876
3877 void QPainter::setPen(const QPen &pen)
3878 {
3879
3880 #ifdef QT_DEBUG_DRAW
3881     if (qt_show_painter_debug_output)
3882         printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3883            pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3884 #endif
3885     Q_D(QPainter);
3886     if (!d->engine) {
3887         qWarning("QPainter::setPen: Painter not active");
3888         return;
3889     }
3890
3891     if (d->state->pen == pen)
3892         return;
3893
3894     d->state->pen = pen;
3895
3896     if (d->extended) {
3897         d->checkEmulation();
3898         d->extended->penChanged();
3899         return;
3900     }
3901
3902     d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3903 }
3904
3905 /*!
3906     \overload
3907
3908     Sets the painter's pen to have the given \a style, width 0 and
3909     black color.
3910 */
3911
3912 void QPainter::setPen(Qt::PenStyle style)
3913 {
3914     Q_D(QPainter);
3915     if (!d->engine) {
3916         qWarning("QPainter::setPen: Painter not active");
3917         return;
3918     }
3919
3920     if (d->state->pen.style() == style
3921         && (style == Qt::NoPen || (d->state->pen.widthF() == 0
3922                                    && d->state->pen.isSolid()
3923                                    && d->state->pen.color() == QColor(Qt::black))))
3924         return;
3925
3926     // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
3927     // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
3928     d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
3929
3930     if (d->extended)
3931         d->extended->penChanged();
3932     else
3933         d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3934
3935 }
3936
3937 /*!
3938     Returns the painter's current pen.
3939
3940     \sa setPen(), {QPainter#Settings}{Settings}
3941 */
3942
3943 const QPen &QPainter::pen() const
3944 {
3945     Q_D(const QPainter);
3946     if (!d->engine) {
3947         qWarning("QPainter::pen: Painter not active");
3948         return d->fakeState()->pen;
3949     }
3950     return d->state->pen;
3951 }
3952
3953
3954 /*!
3955     Sets the painter's brush to the given \a brush.
3956
3957     The painter's brush defines how shapes are filled.
3958
3959     \sa brush(), {QPainter#Settings}{Settings}
3960 */
3961
3962 void QPainter::setBrush(const QBrush &brush)
3963 {
3964 #ifdef QT_DEBUG_DRAW
3965     if (qt_show_painter_debug_output)
3966         printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
3967 #endif
3968     Q_D(QPainter);
3969     if (!d->engine) {
3970         qWarning("QPainter::setBrush: Painter not active");
3971         return;
3972     }
3973
3974     if (d->state->brush.d == brush.d)
3975         return;
3976
3977     if (d->extended) {
3978         d->state->brush = brush;
3979         d->checkEmulation();
3980         d->extended->brushChanged();
3981         return;
3982     }
3983
3984     d->state->brush = brush;
3985     d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
3986 }
3987
3988
3989 /*!
3990     \overload
3991
3992     Sets the painter's brush to black color and the specified \a
3993     style.
3994 */
3995
3996 void QPainter::setBrush(Qt::BrushStyle style)
3997 {
3998     Q_D(QPainter);
3999     if (!d->engine) {
4000         qWarning("QPainter::setBrush: Painter not active");
4001         return;
4002     }
4003     if (d->state->brush.style() == style &&
4004         (style == Qt::NoBrush
4005          || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
4006         return;
4007     d->state->brush = QBrush(Qt::black, style);
4008     if (d->extended)
4009         d->extended->brushChanged();
4010     else
4011         d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
4012 }
4013
4014 /*!
4015     Returns the painter's current brush.
4016
4017     \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
4018 */
4019
4020 const QBrush &QPainter::brush() const
4021 {
4022     Q_D(const QPainter);
4023     if (!d->engine) {
4024         qWarning("QPainter::brush: Painter not active");
4025         return d->fakeState()->brush;
4026     }
4027     return d->state->brush;
4028 }
4029
4030 /*!
4031     \fn void QPainter::setBackground(const QBrush &brush)
4032
4033     Sets the background brush of the painter to the given \a brush.
4034
4035     The background brush is the brush that is filled in when drawing
4036     opaque text, stippled lines and bitmaps. The background brush has
4037     no effect in transparent background mode (which is the default).
4038
4039     \sa background(), setBackgroundMode(),
4040     {QPainter#Settings}{Settings}
4041 */
4042
4043 void QPainter::setBackground(const QBrush &bg)
4044 {
4045 #ifdef QT_DEBUG_DRAW
4046     if (qt_show_painter_debug_output)
4047         printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4048 #endif
4049
4050     Q_D(QPainter);
4051     if (!d->engine) {
4052         qWarning("QPainter::setBackground: Painter not active");
4053         return;
4054     }
4055     d->state->bgBrush = bg;
4056     if (!d->extended)
4057         d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4058 }
4059
4060 /*!
4061     Sets the painter's font to the given \a font.
4062
4063     This font is used by subsequent drawText() functions. The text
4064     color is the same as the pen color.
4065
4066     If you set a font that isn't available, Qt finds a close match.
4067     font() will return what you set using setFont() and fontInfo() returns the
4068     font actually being used (which may be the same).
4069
4070     \sa font(), drawText(), {QPainter#Settings}{Settings}
4071 */
4072
4073 void QPainter::setFont(const QFont &font)
4074 {
4075     Q_D(QPainter);
4076
4077 #ifdef QT_DEBUG_DRAW
4078     if (qt_show_painter_debug_output)
4079         printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4080 #endif
4081
4082     if (!d->engine) {
4083         qWarning("QPainter::setFont: Painter not active");
4084         return;
4085     }
4086
4087     d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4088     if (!d->extended)
4089         d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4090 }
4091
4092 /*!
4093     Returns the currently set font used for drawing text.
4094
4095     \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4096 */
4097 const QFont &QPainter::font() const
4098 {
4099     Q_D(const QPainter);
4100     if (!d->engine) {
4101         qWarning("QPainter::font: Painter not active");
4102         return d->fakeState()->font;
4103     }
4104     return d->state->font;
4105 }
4106
4107 /*!
4108     \since 4.4
4109
4110     Draws the given rectangle \a rect with rounded corners.
4111
4112     The \a xRadius and \a yRadius arguments specify the radii
4113     of the ellipses defining the corners of the rounded rectangle.
4114     When \a mode is Qt::RelativeSize, \a xRadius and
4115     \a yRadius are specified in percentage of half the rectangle's
4116     width and height respectively, and should be in the range
4117     0.0 to 100.0.
4118
4119     A filled rectangle has a size of rect.size(). A stroked rectangle
4120     has a size of rect.size() plus the pen width.
4121
4122     \table 100%
4123     \row
4124     \li \inlineimage qpainter-roundrect.png
4125     \li
4126     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 8
4127     \endtable
4128
4129     \sa drawRect(), QPen
4130 */
4131 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4132 {
4133 #ifdef QT_DEBUG_DRAW
4134     if (qt_show_painter_debug_output)
4135         printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4136 #endif
4137     Q_D(QPainter);
4138
4139     if (!d->engine)
4140         return;
4141
4142     if (xRadius <= 0 || yRadius <= 0) {             // draw normal rectangle
4143         drawRect(rect);
4144         return;
4145     }
4146
4147     if (d->extended) {
4148         d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4149         return;
4150     }
4151
4152     QPainterPath path;
4153     path.addRoundedRect(rect, xRadius, yRadius, mode);
4154     drawPath(path);
4155 }
4156
4157 /*!
4158     \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4159                                        Qt::SizeMode mode = Qt::AbsoluteSize);
4160     \since 4.4
4161     \overload
4162
4163     Draws the given rectangle \a rect with rounded corners.
4164 */
4165
4166 /*!
4167     \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4168                                        Qt::SizeMode mode = Qt::AbsoluteSize);
4169     \since 4.4
4170     \overload
4171
4172     Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4173 */
4174
4175 /*!
4176     \obsolete
4177
4178     Draws a rectangle \a r with rounded corners.
4179
4180     The \a xRnd and \a yRnd arguments specify how rounded the corners
4181     should be. 0 is angled corners, 99 is maximum roundedness.
4182
4183     A filled rectangle has a size of r.size(). A stroked rectangle
4184     has a size of r.size() plus the pen width.
4185
4186     \sa drawRoundedRect()
4187 */
4188 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4189 {
4190     drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4191 }
4192
4193
4194 /*!
4195     \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4196
4197     \overload
4198     \obsolete
4199
4200     Draws the rectangle \a r with rounded corners.
4201 */
4202
4203 /*!
4204     \obsolete
4205
4206     \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4207
4208     \overload
4209
4210     Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4211 */
4212
4213 /*!
4214     \fn void QPainter::drawEllipse(const QRectF &rectangle)
4215
4216     Draws the ellipse defined by the given \a rectangle.
4217
4218     A filled ellipse has a size of \a{rectangle}.\l
4219     {QRect::size()}{size()}. A stroked ellipse has a size of
4220     \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4221
4222     \table 100%
4223     \row
4224     \li \inlineimage qpainter-ellipse.png
4225     \li
4226     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 9
4227     \endtable
4228
4229     \sa drawPie(), {Coordinate System}
4230 */
4231 void QPainter::drawEllipse(const QRectF &r)
4232 {
4233 #ifdef QT_DEBUG_DRAW
4234     if (qt_show_painter_debug_output)
4235         printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4236 #endif
4237     Q_D(QPainter);
4238
4239     if (!d->engine)
4240         return;
4241
4242     QRectF rect(r.normalized());
4243
4244     if (d->extended) {
4245         d->extended->drawEllipse(rect);
4246         return;
4247     }
4248
4249     d->updateState(d->state);
4250     if (d->state->emulationSpecifier) {
4251         if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4252             && d->state->matrix.type() == QTransform::TxTranslate) {
4253             rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4254         } else {
4255             QPainterPath path;
4256             path.addEllipse(rect);
4257             d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4258             return;
4259         }
4260     }
4261
4262     d->engine->drawEllipse(rect);
4263 }
4264
4265 /*!
4266     \fn QPainter::drawEllipse(const QRect &rectangle)
4267
4268     \overload
4269
4270     Draws the ellipse defined by the given \a rectangle.
4271 */
4272 void QPainter::drawEllipse(const QRect &r)
4273 {
4274 #ifdef QT_DEBUG_DRAW
4275     if (qt_show_painter_debug_output)
4276         printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4277 #endif
4278     Q_D(QPainter);
4279
4280     if (!d->engine)
4281         return;
4282
4283     QRect rect(r.normalized());
4284
4285     if (d->extended) {
4286         d->extended->drawEllipse(rect);
4287         return;
4288     }
4289
4290     d->updateState(d->state);
4291
4292     if (d->state->emulationSpecifier) {
4293         if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4294             && d->state->matrix.type() == QTransform::TxTranslate) {
4295             rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4296         } else {
4297             QPainterPath path;
4298             path.addEllipse(rect);
4299             d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4300             return;
4301         }
4302     }
4303
4304     d->engine->drawEllipse(rect);
4305 }
4306
4307 /*!
4308     \fn QPainter::drawEllipse(int x, int y, int width, int height)
4309
4310     \overload
4311
4312     Draws the ellipse defined by the rectangle beginning at (\a{x},
4313     \a{y}) with the given \a width and \a height.
4314 */
4315
4316 /*!
4317     \since 4.4
4318
4319     \fn QPainter::drawEllipse(const QPointF &center, qreal rx, qreal ry)
4320
4321     \overload
4322
4323     Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4324 */
4325
4326 /*!
4327     \since 4.4
4328
4329     \fn QPainter::drawEllipse(const QPoint &center, int rx, int ry)
4330
4331     \overload
4332
4333     Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4334 */
4335
4336 /*!
4337     \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4338
4339     Draws the arc defined by the given \a rectangle, \a startAngle and
4340     \a spanAngle.
4341
4342     The \a startAngle and \a spanAngle must be specified in 1/16th of
4343     a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4344     values for the angles mean counter-clockwise while negative values
4345     mean the clockwise direction. Zero degrees is at the 3 o'clock
4346     position.
4347
4348     \table 100%
4349     \row
4350     \li \inlineimage qpainter-arc.png
4351     \li
4352     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 10
4353     \endtable
4354
4355     \sa drawPie(), drawChord(), {Coordinate System}
4356 */
4357
4358 void QPainter::drawArc(const QRectF &r, int a, int alen)
4359 {
4360 #ifdef QT_DEBUG_DRAW
4361     if (qt_show_painter_debug_output)
4362         printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4363            r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4364 #endif
4365     Q_D(QPainter);
4366
4367     if (!d->engine)
4368         return;
4369
4370     QRectF rect = r.normalized();
4371
4372     QPainterPath path;
4373     path.arcMoveTo(rect, a/16.0);
4374     path.arcTo(rect, a/16.0, alen/16.0);
4375     strokePath(path, d->state->pen);
4376 }
4377
4378 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4379                                int spanAngle)
4380
4381     \overload
4382
4383     Draws the arc defined by the given \a rectangle, \a startAngle and
4384     \a spanAngle.
4385 */
4386
4387 /*!
4388     \fn void QPainter::drawArc(int x, int y, int width, int height,
4389                                int startAngle, int spanAngle)
4390
4391     \overload
4392
4393     Draws the arc defined by the rectangle beginning at (\a x, \a y)
4394     with the specified \a width and \a height, and the given \a
4395     startAngle and \a spanAngle.
4396 */
4397
4398 /*!
4399     \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4400
4401     Draws a pie defined by the given \a rectangle, \a startAngle and
4402     and \a spanAngle.
4403
4404     The pie is filled with the current brush().
4405
4406     The startAngle and spanAngle must be specified in 1/16th of a
4407     degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4408     for the angles mean counter-clockwise while negative values mean
4409     the clockwise direction. Zero degrees is at the 3 o'clock
4410     position.
4411
4412     \table 100%
4413     \row
4414     \li \inlineimage qpainter-pie.png
4415     \li
4416     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 11
4417     \endtable
4418
4419     \sa drawEllipse(), drawChord(), {Coordinate System}
4420 */
4421 void QPainter::drawPie(const QRectF &r, int a, int alen)
4422 {
4423 #ifdef QT_DEBUG_DRAW
4424     if (qt_show_painter_debug_output)
4425         printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4426            r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4427 #endif
4428     Q_D(QPainter);
4429
4430     if (!d->engine)
4431         return;
4432
4433     if (a > (360*16)) {
4434         a = a % (360*16);
4435     } else if (a < 0) {
4436         a = a % (360*16);
4437         if (a < 0) a += (360*16);
4438     }
4439
4440     QRectF rect = r.normalized();
4441
4442     QPainterPath path;
4443     path.moveTo(rect.center());
4444     path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4445     path.closeSubpath();
4446     drawPath(path);
4447
4448 }
4449
4450 /*!
4451     \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4452     \overload
4453
4454     Draws a pie defined by the given \a rectangle, \a startAngle and
4455     and \a spanAngle.
4456 */
4457
4458 /*!
4459     \fn void QPainter::drawPie(int x, int y, int width, int height, int
4460     startAngle, int spanAngle)
4461
4462     \overload
4463
4464     Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4465     the specified \a width and \a height, and the given \a startAngle and
4466     \a spanAngle.
4467 */
4468
4469 /*!
4470     \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4471
4472     Draws the chord defined by the given \a rectangle, \a startAngle and
4473     \a spanAngle.  The chord is filled with the current brush().
4474
4475     The startAngle and spanAngle must be specified in 1/16th of a
4476     degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4477     for the angles mean counter-clockwise while negative values mean
4478     the clockwise direction. Zero degrees is at the 3 o'clock
4479     position.
4480
4481     \table 100%
4482     \row
4483     \li \inlineimage qpainter-chord.png
4484     \li
4485     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 12
4486     \endtable
4487
4488     \sa drawArc(), drawPie(), {Coordinate System}
4489 */
4490 void QPainter::drawChord(const QRectF &r, int a, int alen)
4491 {
4492 #ifdef QT_DEBUG_DRAW
4493     if (qt_show_painter_debug_output)
4494         printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4495            r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4496 #endif
4497     Q_D(QPainter);
4498
4499     if (!d->engine)
4500         return;
4501
4502     QRectF rect = r.normalized();
4503
4504     QPainterPath path;
4505     path.arcMoveTo(rect, a/16.0);
4506     path.arcTo(rect, a/16.0, alen/16.0);
4507     path.closeSubpath();
4508     drawPath(path);
4509 }
4510 /*!
4511     \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4512
4513     \overload
4514
4515     Draws the chord defined by the given \a rectangle, \a startAngle and
4516     \a spanAngle.
4517 */
4518
4519 /*!
4520     \fn void QPainter::drawChord(int x, int y, int width, int height, int
4521     startAngle, int spanAngle)
4522
4523     \overload
4524
4525    Draws the chord defined by the rectangle beginning at (\a x, \a y)
4526    with the specified \a width and \a height, and the given \a
4527    startAngle and \a spanAngle.
4528 */
4529
4530
4531 /*!
4532     Draws the first \a lineCount lines in the array \a lines
4533     using the current pen.
4534
4535     \sa drawLine(), drawPolyline()
4536 */
4537 void QPainter::drawLines(const QLineF *lines, int lineCount)
4538 {
4539 #ifdef QT_DEBUG_DRAW
4540     if (qt_show_painter_debug_output)
4541         printf("QPainter::drawLines(), line count=%d\n", lineCount);
4542 #endif
4543
4544     Q_D(QPainter);
4545
4546     if (!d->engine || lineCount < 1)
4547         return;
4548
4549     if (d->extended) {
4550         d->extended->drawLines(lines, lineCount);
4551         return;
4552     }
4553
4554     d->updateState(d->state);
4555
4556     uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4557
4558     if (lineEmulation) {
4559         if (lineEmulation == QPaintEngine::PrimitiveTransform
4560             && d->state->matrix.type() == QTransform::TxTranslate) {
4561             for (int i = 0; i < lineCount; ++i) {
4562                 QLineF line = lines[i];
4563                 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4564                 d->engine->drawLines(&line, 1);
4565             }
4566         } else {
4567             QPainterPath linePath;
4568             for (int i = 0; i < lineCount; ++i) {
4569                 linePath.moveTo(lines[i].p1());
4570                 linePath.lineTo(lines[i].p2());
4571             }
4572             d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4573         }
4574         return;
4575     }
4576     d->engine->drawLines(lines, lineCount);
4577 }
4578
4579 /*!
4580     \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4581     \overload
4582
4583     Draws the first \a lineCount lines in the array \a lines
4584     using the current pen.
4585 */
4586 void QPainter::drawLines(const QLine *lines, int lineCount)
4587 {
4588 #ifdef QT_DEBUG_DRAW
4589     if (qt_show_painter_debug_output)
4590         printf("QPainter::drawLine(), line count=%d\n", lineCount);
4591 #endif
4592
4593     Q_D(QPainter);
4594
4595     if (!d->engine || lineCount < 1)
4596         return;
4597
4598     if (d->extended) {
4599         d->extended->drawLines(lines, lineCount);
4600         return;
4601     }
4602
4603     d->updateState(d->state);
4604
4605     uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4606
4607     if (lineEmulation) {
4608         if (lineEmulation == QPaintEngine::PrimitiveTransform
4609             && d->state->matrix.type() == QTransform::TxTranslate) {
4610             for (int i = 0; i < lineCount; ++i) {
4611                 QLineF line = lines[i];
4612                 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4613                 d->engine->drawLines(&line, 1);
4614             }
4615         } else {
4616             QPainterPath linePath;
4617             for (int i = 0; i < lineCount; ++i) {
4618                 linePath.moveTo(lines[i].p1());
4619                 linePath.lineTo(lines[i].p2());
4620             }
4621             d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4622         }
4623         return;
4624     }
4625     d->engine->drawLines(lines, lineCount);
4626 }
4627
4628 /*!
4629     \overload
4630
4631     Draws the first \a lineCount lines in the array \a pointPairs
4632     using the current pen.  The lines are specified as pairs of points
4633     so the number of entries in \a pointPairs must be at least \a
4634     lineCount * 2.
4635 */
4636 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4637 {
4638     Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4639
4640     drawLines((QLineF*)pointPairs, lineCount);
4641 }
4642
4643 /*!
4644     \overload
4645
4646     Draws the first \a lineCount lines in the array \a pointPairs
4647     using the current pen.
4648 */
4649 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4650 {
4651     Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4652
4653     drawLines((QLine*)pointPairs, lineCount);
4654 }
4655
4656
4657 /*!
4658     \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4659     \overload
4660
4661     Draws a line for each pair of points in the vector \a pointPairs
4662     using the current pen. If there is an odd number of points in the
4663     array, the last point will be ignored.
4664 */
4665
4666 /*!
4667     \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4668     \overload
4669
4670     Draws a line for each pair of points in the vector \a pointPairs
4671     using the current pen.
4672 */
4673
4674 /*!
4675     \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4676     \overload
4677
4678     Draws the set of lines defined by the list \a lines using the
4679     current pen and brush.
4680 */
4681
4682 /*!
4683     \fn void QPainter::drawLines(const QVector<QLine> &lines)
4684     \overload
4685
4686     Draws the set of lines defined by the list \a lines using the
4687     current pen and brush.
4688 */
4689
4690 /*!
4691     Draws the polyline defined by the first \a pointCount points in \a
4692     points using the current pen.
4693
4694     Note that unlike the drawPolygon() function the last point is \e
4695     not connected to the first, neither is the polyline filled.
4696
4697     \table 100%
4698     \row
4699     \li
4700     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 13
4701     \endtable
4702
4703     \sa drawLines(), drawPolygon(), {Coordinate System}
4704 */
4705 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4706 {
4707 #ifdef QT_DEBUG_DRAW
4708     if (qt_show_painter_debug_output)
4709         printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4710 #endif
4711     Q_D(QPainter);
4712
4713     if (!d->engine || pointCount < 2)
4714         return;
4715
4716     if (d->extended) {
4717         d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4718         return;
4719     }
4720
4721     d->updateState(d->state);
4722
4723     uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4724
4725     if (lineEmulation) {
4726         // ###
4727 //         if (lineEmulation == QPaintEngine::PrimitiveTransform
4728 //             && d->state->matrix.type() == QTransform::TxTranslate) {
4729 //         } else {
4730         QPainterPath polylinePath(points[0]);
4731         for (int i=1; i<pointCount; ++i)
4732             polylinePath.lineTo(points[i]);
4733         d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4734 //         }
4735     } else {
4736         d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4737     }
4738 }
4739
4740 /*!
4741     \overload
4742
4743     Draws the polyline defined by the first \a pointCount points in \a
4744     points using the current pen.
4745  */
4746 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4747 {
4748 #ifdef QT_DEBUG_DRAW
4749     if (qt_show_painter_debug_output)
4750         printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4751 #endif
4752     Q_D(QPainter);
4753
4754     if (!d->engine || pointCount < 2)
4755         return;
4756
4757     if (d->extended) {
4758         d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4759         return;
4760     }
4761
4762     d->updateState(d->state);
4763
4764     uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4765
4766     if (lineEmulation) {
4767         // ###
4768 //         if (lineEmulation == QPaintEngine::PrimitiveTransform
4769 //             && d->state->matrix.type() == QTransform::TxTranslate) {
4770 //         } else {
4771         QPainterPath polylinePath(points[0]);
4772         for (int i=1; i<pointCount; ++i)
4773             polylinePath.lineTo(points[i]);
4774         d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4775 //         }
4776     } else {
4777         d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4778     }
4779 }
4780
4781 /*!
4782     \fn void QPainter::drawPolyline(const QPolygonF &points)
4783
4784     \overload
4785
4786     Draws the polyline defined by the given \a points using the
4787     current pen.
4788 */
4789
4790 /*!
4791     \fn void QPainter::drawPolyline(const QPolygon &points)
4792
4793     \overload
4794
4795     Draws the polyline defined by the given \a points using the
4796     current pen.
4797 */
4798
4799 /*!
4800     Draws the polygon defined by the first \a pointCount points in the
4801     array \a points using the current pen and brush.
4802
4803     \table 100%
4804     \row
4805     \li \inlineimage qpainter-polygon.png
4806     \li
4807     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 14
4808     \endtable
4809
4810     The first point is implicitly connected to the last point, and the
4811     polygon is filled with the current brush().
4812
4813     If \a fillRule is Qt::WindingFill, the polygon is filled using the
4814     winding fill algorithm.  If \a fillRule is Qt::OddEvenFill, the
4815     polygon is filled using the odd-even fill algorithm. See
4816     \l{Qt::FillRule} for a more detailed description of these fill
4817     rules.
4818
4819     \sa  drawConvexPolygon(), drawPolyline(), {Coordinate System}
4820 */
4821 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
4822 {
4823 #ifdef QT_DEBUG_DRAW
4824     if (qt_show_painter_debug_output)
4825         printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4826 #endif
4827
4828     Q_D(QPainter);
4829
4830     if (!d->engine || pointCount < 2)
4831         return;
4832
4833     if (d->extended) {
4834         d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4835         return;
4836     }
4837
4838     d->updateState(d->state);
4839
4840     uint emulationSpecifier = d->state->emulationSpecifier;
4841
4842     if (emulationSpecifier) {
4843         QPainterPath polygonPath(points[0]);
4844         for (int i=1; i<pointCount; ++i)
4845             polygonPath.lineTo(points[i]);
4846         polygonPath.closeSubpath();
4847         polygonPath.setFillRule(fillRule);
4848         d->draw_helper(polygonPath);
4849         return;
4850     }
4851
4852     d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4853 }
4854
4855 /*! \overload
4856
4857     Draws the polygon defined by the first \a pointCount points in the
4858     array \a points.
4859 */
4860 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
4861 {
4862 #ifdef QT_DEBUG_DRAW
4863     if (qt_show_painter_debug_output)
4864         printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4865 #endif
4866
4867     Q_D(QPainter);
4868
4869     if (!d->engine || pointCount < 2)
4870         return;
4871
4872     if (d->extended) {
4873         d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4874         return;
4875     }
4876
4877     d->updateState(d->state);
4878
4879     uint emulationSpecifier = d->state->emulationSpecifier;
4880
4881     if (emulationSpecifier) {
4882         QPainterPath polygonPath(points[0]);
4883         for (int i=1; i<pointCount; ++i)
4884             polygonPath.lineTo(points[i]);
4885         polygonPath.closeSubpath();
4886         polygonPath.setFillRule(fillRule);
4887         d->draw_helper(polygonPath);
4888         return;
4889     }
4890
4891     d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4892 }
4893
4894 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
4895
4896     \overload
4897
4898     Draws the polygon defined by the given \a points using the fill
4899     rule \a fillRule.
4900 */
4901
4902 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
4903
4904     \overload
4905
4906     Draws the polygon defined by the given \a points using the fill
4907     rule \a fillRule.
4908 */
4909
4910 /*!
4911     \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4912
4913     Draws the convex polygon defined by the first \a pointCount points
4914     in the array \a points using the current pen.
4915
4916     \table 100%
4917     \row
4918     \li \inlineimage qpainter-polygon.png
4919     \li
4920     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 15
4921     \endtable
4922
4923     The first point is implicitly connected to the last point, and the
4924     polygon is filled with the current brush().  If the supplied
4925     polygon is not convex, i.e. it contains at least one angle larger
4926     than 180 degrees, the results are undefined.
4927
4928     On some platforms (e.g. X11), the drawConvexPolygon() function can
4929     be faster than the drawPolygon() function.
4930
4931     \sa drawPolygon(), drawPolyline(), {Coordinate System}
4932 */
4933
4934 /*!
4935     \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4936     \overload
4937
4938     Draws the convex polygon defined by the first \a pointCount points
4939     in the array \a points using the current pen.
4940 */
4941
4942 /*!
4943     \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
4944
4945     \overload
4946
4947     Draws the convex polygon defined by \a polygon using the current
4948     pen and brush.
4949 */
4950
4951 /*!
4952     \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
4953     \overload
4954
4955     Draws the convex polygon defined by \a polygon using the current
4956     pen and brush.
4957 */
4958
4959 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4960 {
4961 #ifdef QT_DEBUG_DRAW
4962     if (qt_show_painter_debug_output)
4963         printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4964 #endif
4965
4966     Q_D(QPainter);
4967
4968     if (!d->engine || pointCount < 2)
4969         return;
4970
4971     if (d->extended) {
4972         d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4973         return;
4974     }
4975
4976     d->updateState(d->state);
4977
4978     uint emulationSpecifier = d->state->emulationSpecifier;
4979
4980     if (emulationSpecifier) {
4981         QPainterPath polygonPath(points[0]);
4982         for (int i=1; i<pointCount; ++i)
4983             polygonPath.lineTo(points[i]);
4984         polygonPath.closeSubpath();
4985         polygonPath.setFillRule(Qt::WindingFill);
4986         d->draw_helper(polygonPath);
4987         return;
4988     }
4989
4990     d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4991 }
4992
4993 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4994 {
4995 #ifdef QT_DEBUG_DRAW
4996     if (qt_show_painter_debug_output)
4997         printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4998 #endif
4999
5000     Q_D(QPainter);
5001
5002     if (!d->engine || pointCount < 2)
5003         return;
5004
5005     if (d->extended) {
5006         d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5007         return;
5008     }
5009
5010     d->updateState(d->state);
5011
5012     uint emulationSpecifier = d->state->emulationSpecifier;
5013
5014     if (emulationSpecifier) {
5015         QPainterPath polygonPath(points[0]);
5016         for (int i=1; i<pointCount; ++i)
5017             polygonPath.lineTo(points[i]);
5018         polygonPath.closeSubpath();
5019         polygonPath.setFillRule(Qt::WindingFill);
5020         d->draw_helper(polygonPath);
5021         return;
5022     }
5023
5024     d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
5025 }
5026
5027 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5028 {
5029     return m.inverted().map(QPointF(m.map(p).toPoint()));
5030 }
5031
5032 /*!
5033     \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5034
5035     Draws the rectangular portion \a source of the given \a pixmap
5036     into the given \a target in the paint device.
5037
5038     \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5039
5040     \table 100%
5041     \row
5042     \li
5043     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 16
5044     \endtable
5045
5046     If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5047     using the pens color. If backgroundMode is Qt::OpaqueMode, the
5048     "unset" bits are drawn using the color of the background brush; if
5049     backgroundMode is Qt::TransparentMode, the "unset" bits are
5050     transparent. Drawing bitmaps with gradient or texture colors is
5051     not supported.
5052
5053     \sa drawImage()
5054 */
5055 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5056 {
5057 #if defined QT_DEBUG_DRAW
5058     if (qt_show_painter_debug_output)
5059         printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5060                p.x(), p.y(),
5061                pm.width(), pm.height());
5062 #endif
5063
5064     Q_D(QPainter);
5065
5066     if (!d->engine || pm.isNull())
5067         return;
5068
5069 #ifndef QT_NO_DEBUG
5070     qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5071 #endif
5072
5073     if (d->extended) {
5074         d->extended->drawPixmap(p, pm);
5075         return;
5076     }
5077
5078     qreal x = p.x();
5079     qreal y = p.y();
5080
5081     int w = pm.width();
5082     int h = pm.height();
5083
5084     if (w <= 0)
5085         return;
5086
5087     // Emulate opaque background for bitmaps
5088     if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5089         fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5090     }
5091
5092     d->updateState(d->state);
5093
5094     if ((d->state->matrix.type() > QTransform::TxTranslate
5095          && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5096         || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5097         || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5098     {
5099         save();
5100         // If there is no rotation involved we have to make sure we use the
5101         // antialiased and not the aliased coordinate system by rounding the coordinates.
5102         if (d->state->matrix.type() <= QTransform::TxScale) {
5103             const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5104             x = p.x();
5105             y = p.y();
5106         }
5107         translate(x, y);
5108         setBackgroundMode(Qt::TransparentMode);
5109         setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5110         QBrush brush(d->state->pen.color(), pm);
5111         setBrush(brush);
5112         setPen(Qt::NoPen);
5113         setBrushOrigin(QPointF(0, 0));
5114
5115         drawRect(pm.rect());
5116         restore();
5117     } else {
5118         if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5119             x += d->state->matrix.dx();
5120             y += d->state->matrix.dy();
5121         }
5122         d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5123     }
5124 }
5125
5126 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5127 {
5128 #if defined QT_DEBUG_DRAW
5129     if (qt_show_painter_debug_output)
5130         printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5131                r.x(), r.y(), r.width(), r.height(),
5132                pm.width(), pm.height(),
5133                sr.x(), sr.y(), sr.width(), sr.height());
5134 #endif
5135
5136     Q_D(QPainter);
5137     if (!d->engine || pm.isNull())
5138         return;
5139 #ifndef QT_NO_DEBUG
5140     qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5141 #endif
5142
5143     qreal x = r.x();
5144     qreal y = r.y();
5145     qreal w = r.width();
5146     qreal h = r.height();
5147     qreal sx = sr.x();
5148     qreal sy = sr.y();
5149     qreal sw = sr.width();
5150     qreal sh = sr.height();
5151
5152     // Sanity-check clipping
5153     if (sw <= 0)
5154         sw = pm.width() - sx;
5155
5156     if (sh <= 0)
5157         sh = pm.height() - sy;
5158
5159     if (w < 0)
5160         w = sw;
5161     if (h < 0)
5162         h = sh;
5163
5164     if (sx < 0) {
5165         qreal w_ratio = sx * w/sw;
5166         x -= w_ratio;
5167         w += w_ratio;
5168         sw += sx;
5169         sx = 0;
5170     }
5171
5172     if (sy < 0) {
5173         qreal h_ratio = sy * h/sh;
5174         y -= h_ratio;
5175         h += h_ratio;
5176         sh += sy;
5177         sy = 0;
5178     }
5179
5180     if (sw + sx > pm.width()) {
5181         qreal delta = sw - (pm.width() - sx);
5182         qreal w_ratio = delta * w/sw;
5183         sw -= delta;
5184         w -= w_ratio;
5185     }
5186
5187     if (sh + sy > pm.height()) {
5188         qreal delta = sh - (pm.height() - sy);
5189         qreal h_ratio = delta * h/sh;
5190         sh -= delta;
5191         h -= h_ratio;
5192     }
5193
5194     if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5195         return;
5196
5197     if (d->extended) {
5198         d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5199         return;
5200     }
5201
5202     // Emulate opaque background for bitmaps
5203     if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5204         fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5205
5206     d->updateState(d->state);
5207
5208     if ((d->state->matrix.type() > QTransform::TxTranslate
5209          && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5210         || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5211         || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5212         || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5213     {
5214         save();
5215         // If there is no rotation involved we have to make sure we use the
5216         // antialiased and not the aliased coordinate system by rounding the coordinates.
5217         if (d->state->matrix.type() <= QTransform::TxScale) {
5218             const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5219             x = p.x();
5220             y = p.y();
5221         }
5222
5223         if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5224             sx = qRound(sx);
5225             sy = qRound(sy);
5226             sw = qRound(sw);
5227             sh = qRound(sh);
5228         }
5229
5230         translate(x, y);
5231         scale(w / sw, h / sh);
5232         setBackgroundMode(Qt::TransparentMode);
5233         setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5234         QBrush brush;
5235
5236         if (sw == pm.width() && sh == pm.height())
5237             brush = QBrush(d->state->pen.color(), pm);
5238         else
5239             brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5240
5241         setBrush(brush);
5242         setPen(Qt::NoPen);
5243
5244         drawRect(QRectF(0, 0, sw, sh));
5245         restore();
5246     } else {
5247         if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5248             x += d->state->matrix.dx();
5249             y += d->state->matrix.dy();
5250         }
5251         d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5252     }
5253 }
5254
5255
5256 /*!
5257     \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5258                                   const QRect &source)
5259     \overload
5260
5261     Draws the rectangular portion \a source of the given \a pixmap
5262     into the given \a target in the paint device.
5263
5264     \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5265 */
5266
5267 /*!
5268     \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5269                                   const QRectF &source)
5270     \overload
5271
5272     Draws the rectangular portion \a source of the given \a pixmap
5273     with its origin at the given \a point.
5274 */
5275
5276 /*!
5277     \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5278                                   const QRect &source)
5279
5280     \overload
5281
5282     Draws the rectangular portion \a source of the given \a pixmap
5283     with its origin at the given \a point.
5284 */
5285
5286 /*!
5287     \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5288     \overload
5289
5290     Draws the given \a pixmap with its origin at the given \a point.
5291 */
5292
5293 /*!
5294     \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5295     \overload
5296
5297     Draws the given \a pixmap with its origin at the given \a point.
5298 */
5299
5300 /*!
5301     \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5302
5303     \overload
5304
5305     Draws the given \a pixmap at position (\a{x}, \a{y}).
5306 */
5307
5308 /*!
5309     \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5310     \overload
5311
5312     Draws the given \a  pixmap into the given \a rectangle.
5313
5314     \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5315 */
5316
5317 /*!
5318     \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5319     const QPixmap &pixmap)
5320
5321     \overload
5322
5323     Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5324     with  the given \a width and \a height.
5325 */
5326
5327 /*!
5328     \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5329                                   int sx, int sy, int sw, int sh)
5330
5331     \overload
5332
5333     Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5334     width \a sw and height \a sh, of the given \a pixmap , at the
5335     point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5336     If sw or sh are equal to zero the width/height of the pixmap
5337     is used and adjusted by the offset sx/sy;
5338 */
5339
5340 /*!
5341     \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5342                                   int sx, int sy, int sw, int sh)
5343
5344     \overload
5345
5346     Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5347     pixmap into the paint device.
5348
5349     (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5350     to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5351     pixmap that is to be drawn. The default is (0, 0).
5352
5353     (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5354     The default, (0, 0) (and negative) means all the way to the
5355     bottom-right of the pixmap.
5356 */
5357
5358 void QPainter::drawImage(const QPointF &p, const QImage &image)
5359 {
5360     Q_D(QPainter);
5361
5362     if (!d->engine || image.isNull())
5363         return;
5364
5365     if (d->extended) {
5366         d->extended->drawImage(p, image);
5367         return;
5368     }
5369
5370     qreal x = p.x();
5371     qreal y = p.y();
5372
5373     int w = image.width();
5374     int h = image.height();
5375
5376     d->updateState(d->state);
5377
5378     if (((d->state->matrix.type() > QTransform::TxTranslate)
5379          && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5380         || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5381         || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5382     {
5383         save();
5384         // If there is no rotation involved we have to make sure we use the
5385         // antialiased and not the aliased coordinate system by rounding the coordinates.
5386         if (d->state->matrix.type() <= QTransform::TxScale) {
5387             const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5388             x = p.x();
5389             y = p.y();
5390         }
5391         translate(x, y);
5392         setBackgroundMode(Qt::TransparentMode);
5393         setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5394         QBrush brush(image);
5395         setBrush(brush);
5396         setPen(Qt::NoPen);
5397         setBrushOrigin(QPointF(0, 0));
5398
5399         drawRect(image.rect());
5400         restore();
5401         return;
5402     }
5403
5404     if (d->state->matrix.type() == QTransform::TxTranslate
5405         && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5406         x += d->state->matrix.dx();
5407         y += d->state->matrix.dy();
5408     }
5409
5410     d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5411 }
5412
5413 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5414                          Qt::ImageConversionFlags flags)
5415 {
5416     Q_D(QPainter);
5417
5418     if (!d->engine || image.isNull())
5419         return;
5420
5421     qreal x = targetRect.x();
5422     qreal y = targetRect.y();
5423     qreal w = targetRect.width();
5424     qreal h = targetRect.height();
5425     qreal sx = sourceRect.x();
5426     qreal sy = sourceRect.y();
5427     qreal sw = sourceRect.width();
5428     qreal sh = sourceRect.height();
5429
5430     // Sanity-check clipping
5431     if (sw <= 0)
5432         sw = image.width() - sx;
5433
5434     if (sh <= 0)
5435         sh = image.height() - sy;
5436
5437     if (w < 0)
5438         w = sw;
5439     if (h < 0)
5440         h = sh;
5441
5442     if (sx < 0) {
5443         qreal w_ratio = sx * w/sw;
5444         x -= w_ratio;
5445         w += w_ratio;
5446         sw += sx;
5447         sx = 0;
5448     }
5449
5450     if (sy < 0) {
5451         qreal h_ratio = sy * h/sh;
5452         y -= h_ratio;
5453         h += h_ratio;
5454         sh += sy;
5455         sy = 0;
5456     }
5457
5458     if (sw + sx > image.width()) {
5459         qreal delta = sw - (image.width() - sx);
5460         qreal w_ratio = delta * w/sw;
5461         sw -= delta;
5462         w -= w_ratio;
5463     }
5464
5465     if (sh + sy > image.height()) {
5466         qreal delta = sh - (image.height() - sy);
5467         qreal h_ratio = delta * h/sh;
5468         sh -= delta;
5469         h -= h_ratio;
5470     }
5471
5472     if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5473         return;
5474
5475     if (d->extended) {
5476         d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5477         return;
5478     }
5479
5480     d->updateState(d->state);
5481
5482     if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5483          && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5484         || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5485         || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5486     {
5487         save();
5488         // If there is no rotation involved we have to make sure we use the
5489         // antialiased and not the aliased coordinate system by rounding the coordinates.
5490         if (d->state->matrix.type() <= QTransform::TxScale) {
5491             const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5492             x = p.x();
5493             y = p.y();
5494         }
5495
5496         if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5497             sx = qRound(sx);
5498             sy = qRound(sy);
5499             sw = qRound(sw);
5500             sh = qRound(sh);
5501         }
5502         translate(x, y);
5503         scale(w / sw, h / sh);
5504         setBackgroundMode(Qt::TransparentMode);
5505         setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5506         QBrush brush(image);
5507         setBrush(brush);
5508         setPen(Qt::NoPen);
5509         setBrushOrigin(QPointF(-sx, -sy));
5510
5511         drawRect(QRectF(0, 0, sw, sh));
5512         restore();
5513         return;
5514     }
5515
5516     if (d->state->matrix.type() == QTransform::TxTranslate
5517         && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5518         x += d->state->matrix.dx();
5519         y += d->state->matrix.dy();
5520     }
5521
5522     d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5523 }
5524
5525 /*!
5526     \fn void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphs)
5527
5528     Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5529     edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5530     selected on \a glyphs and at offsets given by the positions in \a glyphs.
5531
5532     \since 4.8
5533
5534     \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes()
5535 */
5536 #if !defined(QT_NO_RAWFONT)
5537 void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
5538 {
5539     Q_D(QPainter);
5540
5541     QRawFont font = glyphRun.rawFont();
5542     if (!font.isValid())
5543         return;
5544
5545     QGlyphRunPrivate *glyphRun_d = QGlyphRunPrivate::get(glyphRun);
5546
5547     const quint32 *glyphIndexes = glyphRun_d->glyphIndexData;
5548     const QPointF *glyphPositions = glyphRun_d->glyphPositionData;
5549
5550     int count = qMin(glyphRun_d->glyphIndexDataSize, glyphRun_d->glyphPositionDataSize);
5551     QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5552
5553     QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5554     bool supportsTransformations = d->extended
5555         ? d->extended->supportsTransformations(fontD->fontEngine, d->state->matrix)
5556         : d->engine->type() == QPaintEngine::CoreGraphics || d->state->matrix.isAffine();
5557
5558     for (int i=0; i<count; ++i) {
5559         QPointF processedPosition = position + glyphPositions[i];
5560         if (!supportsTransformations)
5561             processedPosition = d->state->transform().map(processedPosition);
5562         fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5563     }
5564
5565     d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, font, glyphRun.overline(),
5566                   glyphRun.underline(), glyphRun.strikeOut());
5567 }
5568
5569 void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions,
5570                                  int glyphCount,
5571                                  const QRawFont &font, bool overline, bool underline,
5572                                  bool strikeOut)
5573 {
5574     Q_Q(QPainter);
5575
5576     updateState(state);
5577
5578     QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5579     QFontEngine *fontEngine = fontD->fontEngine;
5580
5581     QFixed leftMost;
5582     QFixed rightMost;
5583     QFixed baseLine;
5584     for (int i=0; i<glyphCount; ++i) {
5585         glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5586         if (i == 0 || leftMost > positions[i].x)
5587             leftMost = positions[i].x;
5588
5589         // We don't support glyphs that do not share a common baseline. If this turns out to
5590         // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5591         // and do a drawTextItemDecorations call per cluster.
5592         if (i == 0 || baseLine < positions[i].y)
5593             baseLine = positions[i].y;
5594
5595         // We use the advance rather than the actual bounds to match the algorithm in drawText()
5596         if (i == 0 || rightMost < positions[i].x + gm.xoff)
5597             rightMost = positions[i].x + gm.xoff;
5598     }
5599
5600     QFixed width = rightMost - leftMost;
5601
5602     if (extended != 0 && state->matrix.isAffine()) {
5603         QStaticTextItem staticTextItem;
5604         staticTextItem.color = state->pen.color();
5605         staticTextItem.font = state->font;
5606         staticTextItem.setFontEngine(fontEngine);
5607         staticTextItem.numGlyphs = glyphCount;
5608         staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5609         staticTextItem.glyphPositions = positions;
5610
5611         extended->drawStaticTextItem(&staticTextItem);
5612     } else {
5613         QTextItemInt textItem;
5614         textItem.fontEngine = fontEngine;
5615
5616         QVarLengthArray<QFixed, 128> advances(glyphCount);
5617         QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5618         QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5619         qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5620         qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
5621         qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5622
5623         textItem.glyphs.numGlyphs = glyphCount;
5624         textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5625         textItem.glyphs.offsets = positions;
5626         textItem.glyphs.advances_x = advances.data();
5627         textItem.glyphs.advances_y = advances.data();
5628         textItem.glyphs.justifications = glyphJustifications.data();
5629         textItem.glyphs.attributes = glyphAttributes.data();
5630
5631         engine->drawTextItem(QPointF(0, 0), textItem);
5632     }
5633
5634     QTextItemInt::RenderFlags flags;
5635     if (underline)
5636         flags |= QTextItemInt::Underline;
5637     if (overline)
5638         flags |= QTextItemInt::Overline;
5639     if (strikeOut)
5640         flags |= QTextItemInt::StrikeOut;
5641
5642     drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5643                            fontEngine,
5644                            (underline
5645                               ? QTextCharFormat::SingleUnderline
5646                               : QTextCharFormat::NoUnderline),
5647                            flags, width.toReal(), QTextCharFormat());
5648 }
5649 #endif // QT_NO_RAWFONT
5650
5651 /*!
5652
5653     \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5654     \since 4.7
5655     \overload
5656
5657     Draws the \a staticText at the \a topLeftPosition.
5658
5659     \note The y-position is used as the top of the font.
5660
5661 */
5662
5663 /*!
5664     \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5665     \since 4.7
5666     \overload
5667
5668     Draws the \a staticText at coordinates \a left and \a top.
5669
5670     \note The y-position is used as the top of the font.
5671 */
5672
5673 /*!
5674     \fn void QPainter::drawText(const QPointF &position, const QString &text)
5675
5676     Draws the given \a text with the currently defined text direction,
5677     beginning at the given \a position.
5678
5679     This function does not handle the newline character (\n), as it cannot
5680     break text into multiple lines, and it cannot display the newline character.
5681     Use the QPainter::drawText() overload that takes a rectangle instead
5682     if you want to draw multiple lines of text with the newline character, or
5683     if you want the text to be wrapped.
5684
5685     By default, QPainter draws text anti-aliased.
5686
5687     \note The y-position is used as the baseline of the font.
5688 */
5689
5690 void QPainter::drawText(const QPointF &p, const QString &str)
5691 {
5692     drawText(p, str, 0, 0);
5693 }
5694
5695 /*!
5696     \since 4.7
5697
5698     Draws the given \a staticText at the given \a topLeftPosition.
5699
5700     The text will be drawn using the font and the transformation set on the painter. If the
5701     font and/or transformation set on the painter are different from the ones used to initialize
5702     the layout of the QStaticText, then the layout will have to be recalculated. Use
5703     QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5704     it will later be drawn.
5705
5706     If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5707     last drawn, then there will be a slight overhead when translating the text to its new position.
5708
5709     \note If the painter's transformation is not affine, then \a staticText will be drawn using
5710     regular calls to drawText(), losing any potential for performance improvement.
5711
5712     \note The y-position is used as the top of the font.
5713
5714     \sa QStaticText
5715 */
5716 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5717 {
5718     Q_D(QPainter);
5719     if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5720         return;
5721
5722     QStaticTextPrivate *staticText_d =
5723             const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5724
5725     if (font() != staticText_d->font) {
5726         staticText_d->font = font();
5727         staticText_d->needsRelayout = true;
5728     }
5729
5730     // If we don't have an extended paint engine, or if the painter is projected,
5731     // we go through standard code path
5732     if (d->extended == 0 || !d->state->matrix.isAffine()) {
5733         staticText_d->paintText(topLeftPosition, this);
5734         return;
5735     }
5736
5737     bool supportsTransformations = d->extended->supportsTransformations(staticText_d->font.d->engineForScript(QUnicodeTables::Common),
5738                                                                         d->state->matrix);
5739     if (supportsTransformations && !staticText_d->untransformedCoordinates) {
5740         staticText_d->untransformedCoordinates = true;
5741         staticText_d->needsRelayout = true;
5742     } else if (!supportsTransformations && staticText_d->untransformedCoordinates) {
5743         staticText_d->untransformedCoordinates = false;
5744         staticText_d->needsRelayout = true;
5745     }
5746
5747     // Don't recalculate entire layout because of translation, rather add the dx and dy
5748     // into the position to move each text item the correct distance.
5749     QPointF transformedPosition = topLeftPosition;
5750     if (!staticText_d->untransformedCoordinates)
5751         transformedPosition = transformedPosition * d->state->matrix;
5752     QTransform oldMatrix;
5753
5754     // The translation has been applied to transformedPosition. Remove translation
5755     // component from matrix.
5756     if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
5757         qreal m11 = d->state->matrix.m11();
5758         qreal m12 = d->state->matrix.m12();
5759         qreal m13 = d->state->matrix.m13();
5760         qreal m21 = d->state->matrix.m21();
5761         qreal m22 = d->state->matrix.m22();
5762         qreal m23 = d->state->matrix.m23();
5763         qreal m33 = d->state->matrix.m33();
5764
5765         oldMatrix = d->state->matrix;
5766         d->state->matrix.setMatrix(m11, m12, m13,
5767                                    m21, m22, m23,
5768                                    0.0, 0.0, m33);
5769     }
5770
5771     // If the transform is not identical to the text transform,
5772     // we have to relayout the text (for other transformations than plain translation)
5773     bool staticTextNeedsReinit = staticText_d->needsRelayout;
5774     if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
5775         staticText_d->matrix = d->state->matrix;
5776         staticTextNeedsReinit = true;
5777     }
5778
5779     // Recreate the layout of the static text because the matrix or font has changed
5780     if (staticTextNeedsReinit)
5781         staticText_d->init();
5782
5783     if (transformedPosition != staticText_d->position) { // Translate to actual position
5784         QFixed fx = QFixed::fromReal(transformedPosition.x());
5785         QFixed fy = QFixed::fromReal(transformedPosition.y());
5786         QFixed oldX = QFixed::fromReal(staticText_d->position.x());
5787         QFixed oldY = QFixed::fromReal(staticText_d->position.y());
5788         for (int item=0; item<staticText_d->itemCount;++item) {
5789             QStaticTextItem *textItem = staticText_d->items + item;
5790             for (int i=0; i<textItem->numGlyphs; ++i) {
5791                 textItem->glyphPositions[i].x += fx - oldX;
5792                 textItem->glyphPositions[i].y += fy - oldY;
5793             }
5794             textItem->userDataNeedsUpdate = true;
5795         }
5796
5797         staticText_d->position = transformedPosition;
5798     }
5799
5800     QPen oldPen = d->state->pen;
5801     QColor currentColor = oldPen.color();
5802     for (int i=0; i<staticText_d->itemCount; ++i) {
5803         QStaticTextItem *item = staticText_d->items + i;
5804         if (item->color.isValid() && currentColor != item->color) {
5805             setPen(item->color);
5806             currentColor = item->color;
5807         }
5808         d->extended->drawStaticTextItem(item);
5809
5810         qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
5811                                       item->numGlyphs, item->fontEngine(), staticText_d->font,
5812                                       QTextCharFormat());
5813     }
5814     if (currentColor != oldPen.color())
5815         setPen(oldPen);
5816
5817     if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
5818         d->state->matrix = oldMatrix;
5819 }
5820
5821 /*!
5822    \internal
5823 */
5824 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
5825 {
5826 #ifdef QT_DEBUG_DRAW
5827     if (qt_show_painter_debug_output)
5828         printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
5829 #endif
5830
5831     Q_D(QPainter);
5832
5833     if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
5834         return;
5835
5836     if (tf & Qt::TextBypassShaping) {
5837         // Skip harfbuzz complex shaping, shape using glyph advances only
5838         int len = str.length();
5839         int numGlyphs = len;
5840         QVarLengthGlyphLayoutArray glyphs(len);
5841         QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
5842         if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
5843             glyphs.resize(numGlyphs);
5844             if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
5845                 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
5846         }
5847
5848         QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
5849         drawTextItem(p, gf);
5850         return;
5851     }
5852
5853     QStackTextEngine engine(str, d->state->font);
5854     engine.option.setTextDirection(d->state->layoutDirection);
5855     if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
5856         engine.ignoreBidi = true;
5857         engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
5858     }
5859     engine.itemize();
5860     QScriptLine line;
5861     line.length = str.length();
5862     engine.shapeLine(line);
5863
5864     int nItems = engine.layoutData->items.size();
5865     QVarLengthArray<int> visualOrder(nItems);
5866     QVarLengthArray<uchar> levels(nItems);
5867     for (int i = 0; i < nItems; ++i)
5868         levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
5869     QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
5870
5871     if (justificationPadding > 0) {
5872         engine.option.setAlignment(Qt::AlignJustify);
5873         engine.forceJustification = true;
5874         // this works because justify() is only interested in the difference between width and textWidth
5875         line.width = justificationPadding;
5876         engine.justify(line);
5877     }
5878     QFixed x = QFixed::fromReal(p.x());
5879
5880     for (int i = 0; i < nItems; ++i) {
5881         int item = visualOrder[i];
5882         const QScriptItem &si = engine.layoutData->items.at(item);
5883         if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
5884             x += si.width;
5885             continue;
5886         }
5887         QFont f = engine.font(si);
5888         QTextItemInt gf(si, &f);
5889         gf.glyphs = engine.shapedGlyphs(&si);
5890         gf.chars = engine.layoutData->string.unicode() + si.position;
5891         gf.num_chars = engine.length(item);
5892         if (engine.forceJustification) {
5893             for (int j=0; j<gf.glyphs.numGlyphs; ++j)
5894                 gf.width += gf.glyphs.effectiveAdvance(j);
5895         } else {
5896             gf.width = si.width;
5897         }
5898         gf.logClusters = engine.logClusters(&si);
5899
5900         drawTextItem(QPointF(x.toReal(), p.y()), gf);
5901
5902         x += gf.width;
5903     }
5904 }
5905
5906 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
5907 {
5908 #ifdef QT_DEBUG_DRAW
5909     if (qt_show_painter_debug_output)
5910         printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
5911            r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5912 #endif
5913
5914     Q_D(QPainter);
5915
5916     if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5917         return;
5918
5919     if (!d->extended)
5920         d->updateState(d->state);
5921
5922     QRectF bounds;
5923     qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
5924     if (br)
5925         *br = bounds.toAlignedRect();
5926 }
5927
5928 /*!
5929     \fn void QPainter::drawText(const QPoint &position, const QString &text)
5930
5931     \overload
5932
5933     Draws the given \a text with the currently defined text direction,
5934     beginning at the given \a position.
5935
5936     By default, QPainter draws text anti-aliased.
5937
5938     \note The y-position is used as the baseline of the font.
5939
5940 */
5941
5942 /*!
5943     \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
5944     \overload
5945
5946     Draws the given \a text within the provided \a rectangle.
5947
5948     \table 100%
5949     \row
5950     \li \inlineimage qpainter-text.png
5951     \li
5952     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 17
5953     \endtable
5954
5955     The \a boundingRect (if not null) is set to the what the bounding rectangle
5956     should be in order to enclose the whole text. The \a flags argument is a bitwise
5957     OR of the following flags:
5958
5959     \list
5960     \li Qt::AlignLeft
5961     \li Qt::AlignRight
5962     \li Qt::AlignHCenter
5963     \li Qt::AlignJustify
5964     \li Qt::AlignTop
5965     \li Qt::AlignBottom
5966     \li Qt::AlignVCenter
5967     \li Qt::AlignCenter
5968     \li Qt::TextDontClip
5969     \li Qt::TextSingleLine
5970     \li Qt::TextExpandTabs
5971     \li Qt::TextShowMnemonic
5972     \li Qt::TextWordWrap
5973     \li Qt::TextIncludeTrailingSpaces
5974     \endlist
5975
5976     \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
5977
5978     By default, QPainter draws text anti-aliased.
5979
5980     \note The y-coordinate of \a rectangle is used as the top of the font.
5981 */
5982 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
5983 {
5984 #ifdef QT_DEBUG_DRAW
5985     if (qt_show_painter_debug_output)
5986         printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
5987            r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5988 #endif
5989
5990     Q_D(QPainter);
5991
5992     if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5993         return;
5994
5995     if (!d->extended)
5996         d->updateState(d->state);
5997
5998     qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
5999 }
6000
6001 /*!
6002     \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
6003     \overload
6004
6005     Draws the given \a text within the provided \a rectangle according
6006     to the specified \a flags. The \a boundingRect (if not null) is set to
6007     the what the bounding rectangle should be in order to enclose the whole text.
6008
6009     By default, QPainter draws text anti-aliased.
6010
6011     \note The y-coordinate of \a rectangle is used as the top of the font.
6012 */
6013
6014 /*!
6015     \fn void QPainter::drawText(int x, int y, const QString &text)
6016
6017     \overload
6018
6019     Draws the given \a text at position (\a{x}, \a{y}), using the painter's
6020     currently defined text direction.
6021
6022     By default, QPainter draws text anti-aliased.
6023
6024     \note The y-position is used as the baseline of the font.
6025
6026 */
6027
6028 /*!
6029     \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6030                                 const QString &text, QRect *boundingRect)
6031
6032     \overload
6033
6034     Draws the given \a text within the rectangle with origin (\a{x},
6035     \a{y}), \a width and \a height.
6036
6037     The \a boundingRect (if not null) is set to the actual bounding
6038     rectangle of the output.  The \a flags argument is a bitwise OR of
6039     the following flags:
6040
6041     \list
6042     \li Qt::AlignLeft
6043     \li Qt::AlignRight
6044     \li Qt::AlignHCenter
6045     \li Qt::AlignJustify
6046     \li Qt::AlignTop
6047     \li Qt::AlignBottom
6048     \li Qt::AlignVCenter
6049     \li Qt::AlignCenter
6050     \li Qt::TextSingleLine
6051     \li Qt::TextExpandTabs
6052     \li Qt::TextShowMnemonic
6053     \li Qt::TextWordWrap
6054     \endlist
6055
6056     By default, QPainter draws text anti-aliased.
6057
6058     \note The y-position is used as the top of the font.
6059
6060     \sa Qt::AlignmentFlag, Qt::TextFlag
6061 */
6062
6063 /*!
6064     \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6065         const QTextOption &option)
6066     \overload
6067
6068     Draws the given \a text in the \a rectangle specified using the \a option
6069     to control its positioning and orientation.
6070
6071     By default, QPainter draws text anti-aliased.
6072
6073     \note The y-coordinate of \a rectangle is used as the top of the font.
6074 */
6075 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6076 {
6077 #ifdef QT_DEBUG_DRAW
6078     if (qt_show_painter_debug_output)
6079         printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6080            r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6081 #endif
6082
6083     Q_D(QPainter);
6084
6085     if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6086         return;
6087
6088     if (!d->extended)
6089         d->updateState(d->state);
6090
6091     qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6092 }
6093
6094 /*!
6095     \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6096
6097     \internal
6098     \overload
6099 */
6100
6101 /*!
6102     \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6103
6104     \internal
6105     \overload
6106
6107     Draws the text item \a ti at position \a p.
6108 */
6109
6110 /*!
6111     \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6112
6113     \internal
6114     \since 4.1
6115
6116     Draws the text item \a ti at position \a p.
6117
6118     This method ignores the painters background mode and
6119     color. drawText and qt_format_text have to do it themselves, as
6120     only they know the extents of the complete string.
6121
6122     It ignores the font set on the painter as the text item has one of its own.
6123
6124     The underline and strikeout parameters of the text items font are
6125     ignored aswell. You'll need to pass in the correct flags to get
6126     underlining and strikeout.
6127 */
6128
6129 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6130 {
6131     const qreal radiusBase = qMax(qreal(1), maxRadius);
6132
6133     QString key = QLatin1Literal("WaveUnderline-")
6134                   % pen.color().name()
6135                   % HexString<qreal>(radiusBase);
6136
6137     QPixmap pixmap;
6138     if (QPixmapCache::find(key, pixmap))
6139         return pixmap;
6140
6141     const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6142     const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6143     const int radius = qFloor(radiusBase);
6144
6145     QPainterPath path;
6146
6147     qreal xs = 0;
6148     qreal ys = radius;
6149
6150     while (xs < width) {
6151         xs += halfPeriod;
6152         ys = -ys;
6153         path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6154     }
6155
6156     pixmap = QPixmap(width, radius * 2);
6157     pixmap.fill(Qt::transparent);
6158     {
6159         QPen wavePen = pen;
6160         wavePen.setCapStyle(Qt::SquareCap);
6161
6162         // This is to protect against making the line too fat, as happens on Mac OS X
6163         // due to it having a rather thick width for the regular underline.
6164         const qreal maxPenWidth = .8 * radius;
6165         if (wavePen.widthF() > maxPenWidth)
6166             wavePen.setWidth(maxPenWidth);
6167
6168         QPainter imgPainter(&pixmap);
6169         imgPainter.setPen(wavePen);
6170         imgPainter.setRenderHint(QPainter::Antialiasing);
6171         imgPainter.translate(0, radius);
6172         imgPainter.drawPath(path);
6173     }
6174
6175     QPixmapCache::insert(key, pixmap);
6176
6177     return pixmap;
6178 }
6179
6180 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
6181                                    QTextCharFormat::UnderlineStyle underlineStyle,
6182                                    QTextItem::RenderFlags flags, qreal width,
6183                                    const QTextCharFormat &charFormat)
6184 {
6185     if (underlineStyle == QTextCharFormat::NoUnderline
6186         && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6187         return;
6188
6189     const QPen oldPen = painter->pen();
6190     const QBrush oldBrush = painter->brush();
6191     painter->setBrush(Qt::NoBrush);
6192     QPen pen = oldPen;
6193     pen.setStyle(Qt::SolidLine);
6194     pen.setWidthF(fe->lineThickness().toReal());
6195     pen.setCapStyle(Qt::FlatCap);
6196
6197     QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6198
6199     const qreal underlineOffset = fe->underlinePosition().toReal();
6200     // deliberately ceil the offset to avoid the underline coming too close to
6201     // the text above it.
6202     const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
6203     const qreal underlinePos = pos.y() + qCeil(underlineOffset) - aliasedCoordinateDelta;
6204
6205     if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6206         underlineStyle = QTextCharFormat::SpellCheckUnderline; // ### Qt5 QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle));
6207     }
6208
6209     if (underlineStyle == QTextCharFormat::WaveUnderline) {
6210         painter->save();
6211         painter->translate(0, pos.y() + 1);
6212
6213         QColor uc = charFormat.underlineColor();
6214         if (uc.isValid())
6215             pen.setColor(uc);
6216
6217         // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6218         const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6219         const int descent = (int) fe->descent().toReal();
6220
6221         painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6222         painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6223         painter->restore();
6224     } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6225         QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos);
6226
6227         QColor uc = charFormat.underlineColor();
6228         if (uc.isValid())
6229             pen.setColor(uc);
6230
6231         pen.setStyle((Qt::PenStyle)(underlineStyle));
6232         painter->setPen(pen);
6233         painter->drawLine(underLine);
6234     }
6235
6236     pen.setStyle(Qt::SolidLine);
6237     pen.setColor(oldPen.color());
6238
6239     if (flags & QTextItem::StrikeOut) {
6240         QLineF strikeOutLine = line;
6241         strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6242         painter->setPen(pen);
6243         painter->drawLine(strikeOutLine);
6244     }
6245
6246     if (flags & QTextItem::Overline) {
6247         QLineF overLine = line;
6248         overLine.translate(0., - fe->ascent().toReal());
6249         painter->setPen(pen);
6250         painter->drawLine(overLine);
6251     }
6252
6253     painter->setPen(oldPen);
6254     painter->setBrush(oldBrush);
6255 }
6256
6257 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6258                                                 const QFixedPoint *positions, int glyphCount,
6259                                                 QFontEngine *fontEngine, const QFont &font,
6260                                                 const QTextCharFormat &charFormat)
6261 {
6262     if (!(font.underline() || font.strikeOut() || font.overline()))
6263         return;
6264
6265     QFixed leftMost;
6266     QFixed rightMost;
6267     QFixed baseLine;
6268     for (int i=0; i<glyphCount; ++i) {
6269         glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6270         if (i == 0 || leftMost > positions[i].x)
6271             leftMost = positions[i].x;
6272
6273         // We don't support glyphs that do not share a common baseline. If this turns out to
6274         // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6275         // and do a drawTextItemDecorations call per cluster.
6276         if (i == 0 || baseLine < positions[i].y)
6277             baseLine = positions[i].y;
6278
6279         // We use the advance rather than the actual bounds to match the algorithm in drawText()
6280         if (i == 0 || rightMost < positions[i].x + gm.xoff)
6281             rightMost = positions[i].x + gm.xoff;
6282     }
6283
6284     QFixed width = rightMost - leftMost;
6285     QTextItem::RenderFlags flags = 0;
6286
6287     if (font.underline())
6288         flags |= QTextItem::Underline;
6289     if (font.overline())
6290         flags |= QTextItem::Overline;
6291     if (font.strikeOut())
6292         flags |= QTextItem::StrikeOut;
6293
6294     drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6295                            fontEngine,
6296                            font.underline() ? QTextCharFormat::SingleUnderline
6297                                             : QTextCharFormat::NoUnderline, flags,
6298                            width.toReal(), charFormat);
6299 }
6300
6301 void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
6302 {
6303 #ifdef QT_DEBUG_DRAW
6304     if (qt_show_painter_debug_output)
6305         printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6306                p.x(), p.y(), qPrintable(_ti.text()));
6307 #endif
6308
6309     Q_D(QPainter);
6310
6311     if (!d->engine)
6312         return;
6313
6314 #ifndef QT_NO_DEBUG
6315     qt_painter_thread_test(d->device->devType(),
6316                            "text and fonts",
6317                            QFontDatabase::supportsThreadedFontRendering());
6318 #endif
6319
6320     QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6321
6322     if (!d->extended && d->state->bgMode == Qt::OpaqueMode) {
6323         QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6324         fillRect(rect, d->state->bgBrush);
6325     }
6326
6327     if (pen().style() == Qt::NoPen)
6328         return;
6329
6330     const RenderHints oldRenderHints = d->state->renderHints;
6331     if (!d->state->renderHints & QPainter::Antialiasing && d->state->matrix.type() >= QTransform::TxScale) {
6332         // draw antialias decoration (underline/overline/strikeout) with
6333         // transformed text
6334
6335         bool aa = true;
6336         const QTransform &m = d->state->matrix;
6337         if (d->state->matrix.type() < QTransform::TxShear) {
6338             bool isPlain90DegreeRotation =
6339                 (qFuzzyIsNull(m.m11())
6340                  && qFuzzyIsNull(m.m12() - qreal(1))
6341                  && qFuzzyIsNull(m.m21() + qreal(1))
6342                  && qFuzzyIsNull(m.m22())
6343                     )
6344                 ||
6345                 (qFuzzyIsNull(m.m11() + qreal(1))
6346                  && qFuzzyIsNull(m.m12())
6347                  && qFuzzyIsNull(m.m21())
6348                  && qFuzzyIsNull(m.m22() + qreal(1))
6349                     )
6350                 ||
6351                 (qFuzzyIsNull(m.m11())
6352                  && qFuzzyIsNull(m.m12() + qreal(1))
6353                  && qFuzzyIsNull(m.m21() - qreal(1))
6354                  && qFuzzyIsNull(m.m22())
6355                     )
6356                 ;
6357             aa = !isPlain90DegreeRotation;
6358         }
6359         if (aa)
6360             setRenderHint(QPainter::Antialiasing, true);
6361     }
6362
6363     if (!d->extended)
6364         d->updateState(d->state);
6365
6366     if (!ti.glyphs.numGlyphs) {
6367         // nothing to do
6368     } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6369         QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6370
6371         const QGlyphLayout &glyphs = ti.glyphs;
6372         int which = glyphs.glyphs[0] >> 24;
6373
6374         qreal x = p.x();
6375         qreal y = p.y();
6376
6377         bool rtl = ti.flags & QTextItem::RightToLeft;
6378         if (rtl)
6379             x += ti.width.toReal();
6380
6381         int start = 0;
6382         int end, i;
6383         for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6384             const int e = glyphs.glyphs[end] >> 24;
6385             if (e == which)
6386                 continue;
6387
6388
6389             QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6390             ti2.width = 0;
6391             // set the high byte to zero and calc the width
6392             for (i = start; i < end; ++i) {
6393                 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6394                 ti2.width += ti.glyphs.effectiveAdvance(i);
6395             }
6396
6397             if (rtl)
6398                 x -= ti2.width.toReal();
6399
6400             d->engine->drawTextItem(QPointF(x, y), ti2);
6401
6402             if (!rtl)
6403                 x += ti2.width.toReal();
6404
6405             // reset the high byte for all glyphs and advance to the next sub-string
6406             const int hi = which << 24;
6407             for (i = start; i < end; ++i) {
6408                 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6409             }
6410
6411             // change engine
6412             start = end;
6413             which = e;
6414         }
6415
6416         QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6417         ti2.width = 0;
6418         // set the high byte to zero and calc the width
6419         for (i = start; i < end; ++i) {
6420             glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6421             ti2.width += ti.glyphs.effectiveAdvance(i);
6422         }
6423
6424         if (rtl)
6425             x -= ti2.width.toReal();
6426
6427         if (d->extended)
6428             d->extended->drawTextItem(QPointF(x, y), ti2);
6429         else
6430             d->engine->drawTextItem(QPointF(x,y), ti2);
6431
6432         // reset the high byte for all glyphs
6433         const int hi = which << 24;
6434         for (i = start; i < end; ++i)
6435             glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6436
6437     } else {
6438         if (d->extended)
6439             d->extended->drawTextItem(p, ti);
6440         else
6441             d->engine->drawTextItem(p, ti);
6442     }
6443     drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(),
6444                            ti.charFormat);
6445
6446     if (d->state->renderHints != oldRenderHints) {
6447         d->state->renderHints = oldRenderHints;
6448         if (d->extended)
6449             d->extended->renderHintsChanged();
6450         else
6451             d->state->dirtyFlags |= QPaintEngine::DirtyHints;
6452     }
6453 }
6454
6455 /*!
6456     \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6457
6458     Returns the bounding rectangle of the \a text as it will appear
6459     when drawn inside the given \a rectangle with the specified \a
6460     flags using the currently set font(); i.e the function tells you
6461     where the drawText() function will draw when given the same
6462     arguments.
6463
6464     If the \a text does not fit within the given \a rectangle using
6465     the specified \a flags, the function returns the required
6466     rectangle.
6467
6468     The \a flags argument is a bitwise OR of the following flags:
6469     \list
6470          \li Qt::AlignLeft
6471          \li Qt::AlignRight
6472          \li Qt::AlignHCenter
6473          \li Qt::AlignTop
6474          \li Qt::AlignBottom
6475          \li Qt::AlignVCenter
6476          \li Qt::AlignCenter
6477          \li Qt::TextSingleLine
6478          \li Qt::TextExpandTabs
6479          \li Qt::TextShowMnemonic
6480          \li Qt::TextWordWrap
6481          \li Qt::TextIncludeTrailingSpaces
6482     \endlist
6483     If several of the horizontal or several of the vertical alignment
6484     flags are set, the resulting alignment is undefined.
6485
6486     \sa drawText(), Qt::Alignment, Qt::TextFlag
6487 */
6488
6489 /*!
6490     \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6491                                      const QString &text)
6492
6493     \overload
6494
6495     Returns the bounding rectangle of the \a text as it will appear
6496     when drawn inside the given \a rectangle with the specified \a
6497     flags using the currently set font().
6498 */
6499
6500 /*!
6501     \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6502                                      const QString &text);
6503
6504     \overload
6505
6506     Returns the bounding rectangle of the given \a text as it will
6507     appear when drawn inside the rectangle beginning at the point
6508     (\a{x}, \a{y}) with width \a w and height \a h.
6509 */
6510 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6511 {
6512     if (str.isEmpty())
6513         return QRect(rect.x(),rect.y(), 0,0);
6514     QRect brect;
6515     drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6516     return brect;
6517 }
6518
6519
6520
6521 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6522 {
6523     if (str.isEmpty())
6524         return QRectF(rect.x(),rect.y(), 0,0);
6525     QRectF brect;
6526     drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6527     return brect;
6528 }
6529
6530 /*!
6531     \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6532         const QString &text, const QTextOption &option)
6533
6534     \overload
6535
6536     Instead of specifying flags as a bitwise OR of the
6537     Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6538     an \a option argument. The QTextOption class provides a
6539     description of general rich text properties.
6540
6541     \sa QTextOption
6542 */
6543 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6544 {
6545     Q_D(QPainter);
6546
6547     if (!d->engine || text.length() == 0)
6548         return QRectF(r.x(),r.y(), 0,0);
6549
6550     QRectF br;
6551     qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6552     return br;
6553 }
6554
6555 /*!
6556     \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6557
6558     Draws a tiled \a pixmap, inside the given \a rectangle with its
6559     origin at the given \a position.
6560
6561     Calling drawTiledPixmap() is similar to calling drawPixmap()
6562     several times to fill (tile) an area with a pixmap, but is
6563     potentially much more efficient depending on the underlying window
6564     system.
6565
6566     \sa drawPixmap()
6567 */
6568 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6569 {
6570 #ifdef QT_DEBUG_DRAW
6571     if (qt_show_painter_debug_output)
6572         printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6573                r.x(), r.y(), r.width(), r.height(),
6574                pixmap.width(), pixmap.height(),
6575                sp.x(), sp.y());
6576 #endif
6577
6578     Q_D(QPainter);
6579     if (!d->engine || pixmap.isNull() || r.isEmpty())
6580         return;
6581
6582 #ifndef QT_NO_DEBUG
6583     qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6584 #endif
6585
6586     qreal sw = pixmap.width();
6587     qreal sh = pixmap.height();
6588     qreal sx = sp.x();
6589     qreal sy = sp.y();
6590     if (sx < 0)
6591         sx = qRound(sw) - qRound(-sx) % qRound(sw);
6592     else
6593         sx = qRound(sx) % qRound(sw);
6594     if (sy < 0)
6595         sy = qRound(sh) - -qRound(sy) % qRound(sh);
6596     else
6597         sy = qRound(sy) % qRound(sh);
6598
6599
6600     if (d->extended) {
6601         d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6602         return;
6603     }
6604
6605     if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6606         fillRect(r, d->state->bgBrush);
6607
6608     d->updateState(d->state);
6609     if ((d->state->matrix.type() > QTransform::TxTranslate
6610         && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6611         || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6612     {
6613         save();
6614         setBackgroundMode(Qt::TransparentMode);
6615         setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6616         setBrush(QBrush(d->state->pen.color(), pixmap));
6617         setPen(Qt::NoPen);
6618
6619         // If there is no rotation involved we have to make sure we use the
6620         // antialiased and not the aliased coordinate system by rounding the coordinates.
6621         if (d->state->matrix.type() <= QTransform::TxScale) {
6622             const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6623
6624             if (d->state->matrix.type() <= QTransform::TxTranslate) {
6625                 sx = qRound(sx);
6626                 sy = qRound(sy);
6627             }
6628
6629             setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6630             drawRect(QRectF(p, r.size()));
6631         } else {
6632             setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6633             drawRect(r);
6634         }
6635         restore();
6636         return;
6637     }
6638
6639     qreal x = r.x();
6640     qreal y = r.y();
6641     if (d->state->matrix.type() == QTransform::TxTranslate
6642         && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6643         x += d->state->matrix.dx();
6644         y += d->state->matrix.dy();
6645     }
6646
6647     d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6648 }
6649
6650 /*!
6651     \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6652                                   const QPoint &position = QPoint())
6653     \overload
6654
6655     Draws a tiled \a pixmap, inside the given \a rectangle with its
6656     origin at the given \a position.
6657 */
6658
6659 /*!
6660     \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6661          QPixmap &pixmap, int sx, int sy);
6662     \overload
6663
6664     Draws a tiled \a pixmap in the specified rectangle.
6665
6666     (\a{x}, \a{y}) specifies the top-left point in the paint device
6667     that is to be drawn onto; with the given \a width and \a
6668     height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6669     pixmap that is to be drawn; this defaults to (0, 0).
6670 */
6671
6672 #ifndef QT_NO_PICTURE
6673
6674 /*!
6675     \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6676
6677     Replays the given \a picture at the given \a point.
6678
6679     The QPicture class is a paint device that records and replays
6680     QPainter commands. A picture serializes the painter commands to an
6681     IO device in a platform-independent format. Everything that can be
6682     painted on a widget or pixmap can also be stored in a picture.
6683
6684     This function does exactly the same as QPicture::play() when
6685     called with \a point = QPoint(0, 0).
6686
6687     \table 100%
6688     \row
6689     \li
6690     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 18
6691     \endtable
6692
6693     \sa QPicture::play()
6694 */
6695
6696 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6697 {
6698     Q_D(QPainter);
6699
6700     if (!d->engine)
6701         return;
6702
6703     if (!d->extended)
6704         d->updateState(d->state);
6705
6706     save();
6707     translate(p);
6708     const_cast<QPicture *>(&picture)->play(this);
6709     restore();
6710 }
6711
6712 /*!
6713     \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6714     \overload
6715
6716     Replays the given \a picture at the given \a point.
6717 */
6718
6719 /*!
6720     \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6721     \overload
6722
6723     Draws the given \a picture at point (\a x, \a y).
6724 */
6725
6726 #endif // QT_NO_PICTURE
6727
6728 /*!
6729     \fn void QPainter::eraseRect(const QRectF &rectangle)
6730
6731     Erases the area inside the given \a rectangle. Equivalent to
6732     calling
6733     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 19
6734
6735     \sa fillRect()
6736 */
6737 void QPainter::eraseRect(const QRectF &r)
6738 {
6739     Q_D(QPainter);
6740
6741     fillRect(r, d->state->bgBrush);
6742 }
6743
6744 static inline bool needsResolving(const QBrush &brush)
6745 {
6746     Qt::BrushStyle s = brush.style();
6747     return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
6748              s == Qt::ConicalGradientPattern) &&
6749             brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
6750 }
6751
6752 /*!
6753     \fn void QPainter::eraseRect(const QRect &rectangle)
6754     \overload
6755
6756     Erases the area inside the given  \a rectangle.
6757 */
6758
6759 /*!
6760     \fn void QPainter::eraseRect(int x, int y, int width, int height)
6761     \overload
6762
6763     Erases the area inside the rectangle beginning at (\a x, \a y)
6764     with the given \a width and \a height.
6765 */
6766
6767
6768 /*!
6769     \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
6770     \overload
6771
6772     Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6773     width and \a height, using the brush \a style specified.
6774
6775     \since 4.5
6776 */
6777
6778 /*!
6779     \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
6780     \overload
6781
6782     Fills the given \a rectangle  with the brush \a style specified.
6783
6784     \since 4.5
6785 */
6786
6787 /*!
6788     \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
6789     \overload
6790
6791     Fills the given \a rectangle  with the brush \a style specified.
6792
6793     \since 4.5
6794 */
6795
6796 /*!
6797     \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
6798
6799     Fills the given \a rectangle  with the \a brush specified.
6800
6801     Alternatively, you can specify a QColor instead of a QBrush; the
6802     QBrush constructor (taking a QColor argument) will automatically
6803     create a solid pattern brush.
6804
6805     \sa drawRect()
6806 */
6807 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
6808 {
6809     Q_D(QPainter);
6810
6811     if (!d->engine)
6812         return;
6813
6814     if (d->extended) {
6815         const QGradient *g = brush.gradient();
6816         if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6817             d->extended->fillRect(r, brush);
6818             return;
6819         }
6820     }
6821
6822     QPen oldPen = pen();
6823     QBrush oldBrush = this->brush();
6824     setPen(Qt::NoPen);
6825     if (brush.style() == Qt::SolidPattern) {
6826         d->colorBrush.setStyle(Qt::SolidPattern);
6827         d->colorBrush.setColor(brush.color());
6828         setBrush(d->colorBrush);
6829     } else {
6830         setBrush(brush);
6831     }
6832
6833     drawRect(r);
6834     setBrush(oldBrush);
6835     setPen(oldPen);
6836 }
6837
6838 /*!
6839     \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
6840     \overload
6841
6842     Fills the given \a rectangle with the specified \a brush.
6843 */
6844
6845 void QPainter::fillRect(const QRect &r, const QBrush &brush)
6846 {
6847     Q_D(QPainter);
6848
6849     if (!d->engine)
6850         return;
6851
6852     if (d->extended) {
6853         const QGradient *g = brush.gradient();
6854         if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6855             d->extended->fillRect(r, brush);
6856             return;
6857         }
6858     }
6859
6860     QPen oldPen = pen();
6861     QBrush oldBrush = this->brush();
6862     setPen(Qt::NoPen);
6863     if (brush.style() == Qt::SolidPattern) {
6864         d->colorBrush.setStyle(Qt::SolidPattern);
6865         d->colorBrush.setColor(brush.color());
6866         setBrush(d->colorBrush);
6867     } else {
6868         setBrush(brush);
6869     }
6870
6871     drawRect(r);
6872     setBrush(oldBrush);
6873     setPen(oldPen);
6874 }
6875
6876
6877
6878 /*!
6879     \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
6880     \overload
6881
6882     Fills the given \a rectangle with the \a color specified.
6883
6884     \since 4.5
6885 */
6886 void QPainter::fillRect(const QRect &r, const QColor &color)
6887 {
6888     Q_D(QPainter);
6889
6890     if (!d->engine)
6891         return;
6892
6893     if (d->extended) {
6894         d->extended->fillRect(r, color);
6895         return;
6896     }
6897
6898     fillRect(r, QBrush(color));
6899 }
6900
6901
6902 /*!
6903     \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
6904     \overload
6905
6906     Fills the given \a rectangle with the \a color specified.
6907
6908     \since 4.5
6909 */
6910 void QPainter::fillRect(const QRectF &r, const QColor &color)
6911 {
6912     Q_D(QPainter);
6913
6914     if (!d->engine)
6915         return;
6916
6917     if (d->extended) {
6918         d->extended->fillRect(r, color);
6919         return;
6920     }
6921
6922     fillRect(r, QBrush(color));
6923 }
6924
6925 /*!
6926     \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
6927
6928     \overload
6929
6930     Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6931     width and \a height, using the given \a brush.
6932 */
6933
6934 /*!
6935     \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
6936
6937     \overload
6938
6939     Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6940     width and \a height, using the given \a color.
6941
6942     \since 4.5
6943 */
6944
6945 /*!
6946     \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
6947
6948     \overload
6949
6950     Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6951     width and \a height, using the given \a color.
6952
6953     \since 4.5
6954 */
6955
6956 /*!
6957     \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
6958
6959     \overload
6960
6961     Fills the given \a rectangle with the specified \a color.
6962
6963     \since 4.5
6964 */
6965
6966 /*!
6967     \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
6968
6969     \overload
6970
6971     Fills the given \a rectangle with the specified \a color.
6972
6973     \since 4.5
6974 */
6975
6976 /*!
6977     Sets the given render \a hint on the painter if \a on is true;
6978     otherwise clears the render hint.
6979
6980     \sa setRenderHints(), renderHints(), {QPainter#Rendering
6981     Quality}{Rendering Quality}
6982 */
6983 void QPainter::setRenderHint(RenderHint hint, bool on)
6984 {
6985 #ifdef QT_DEBUG_DRAW
6986     if (qt_show_painter_debug_output)
6987         printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
6988 #endif
6989
6990 #ifndef QT_NO_DEBUG
6991     static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
6992     if (hint == QPainter::Antialiasing && antialiasingDisabled)
6993         return;
6994 #endif
6995
6996     setRenderHints(hint, on);
6997 }
6998
6999 /*!
7000     \since 4.2
7001
7002     Sets the given render \a hints on the painter if \a on is true;
7003     otherwise clears the render hints.
7004
7005     \sa setRenderHint(), renderHints(), {QPainter#Rendering
7006     Quality}{Rendering Quality}
7007 */
7008
7009 void QPainter::setRenderHints(RenderHints hints, bool on)
7010 {
7011     Q_D(QPainter);
7012
7013     if (!d->engine) {
7014         qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7015         return;
7016     }
7017
7018     if (on)
7019         d->state->renderHints |= hints;
7020     else
7021         d->state->renderHints &= ~hints;
7022
7023     if (d->extended)
7024         d->extended->renderHintsChanged();
7025     else
7026         d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7027 }
7028
7029 /*!
7030     Returns a flag that specifies the rendering hints that are set for
7031     this painter.
7032
7033     \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7034 */
7035 QPainter::RenderHints QPainter::renderHints() const
7036 {
7037     Q_D(const QPainter);
7038
7039     if (!d->engine)
7040         return 0;
7041
7042     return d->state->renderHints;
7043 }
7044
7045 /*!
7046     \fn bool QPainter::testRenderHint(RenderHint hint) const
7047     \since 4.3
7048
7049     Returns true if \a hint is set; otherwise returns false.
7050
7051     \sa renderHints(), setRenderHint()
7052 */
7053
7054 /*!
7055     Returns true if view transformation is enabled; otherwise returns
7056     false.
7057
7058     \sa setViewTransformEnabled(), worldTransform()
7059 */
7060
7061 bool QPainter::viewTransformEnabled() const
7062 {
7063     Q_D(const QPainter);
7064     if (!d->engine) {
7065         qWarning("QPainter::viewTransformEnabled: Painter not active");
7066         return false;
7067     }
7068     return d->state->VxF;
7069 }
7070
7071 /*!
7072     \fn void QPainter::setWindow(const QRect &rectangle)
7073
7074     Sets the painter's window to the given \a rectangle, and enables
7075     view transformations.
7076
7077     The window rectangle is part of the view transformation. The
7078     window specifies the logical coordinate system. Its sister, the
7079     viewport(), specifies the device coordinate system.
7080
7081     The default window rectangle is the same as the device's
7082     rectangle.
7083
7084     \sa window(), viewTransformEnabled(), {Coordinate
7085     System#Window-Viewport Conversion}{Window-Viewport Conversion}
7086 */
7087
7088 /*!
7089     \fn void QPainter::setWindow(int x, int y, int width, int height)
7090     \overload
7091
7092     Sets the painter's window to the rectangle beginning at (\a x, \a
7093     y) and the given \a width and \a height.
7094 */
7095
7096 void QPainter::setWindow(const QRect &r)
7097 {
7098 #ifdef QT_DEBUG_DRAW
7099     if (qt_show_painter_debug_output)
7100         printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7101 #endif
7102
7103     Q_D(QPainter);
7104
7105     if (!d->engine) {
7106         qWarning("QPainter::setWindow: Painter not active");
7107         return;
7108     }
7109
7110     d->state->wx = r.x();
7111     d->state->wy = r.y();
7112     d->state->ww = r.width();
7113     d->state->wh = r.height();
7114
7115     d->state->VxF = true;
7116     d->updateMatrix();
7117 }
7118
7119 /*!
7120     Returns the window rectangle.
7121
7122     \sa setWindow(), setViewTransformEnabled()
7123 */
7124
7125 QRect QPainter::window() const
7126 {
7127     Q_D(const QPainter);
7128     if (!d->engine) {
7129         qWarning("QPainter::window: Painter not active");
7130         return QRect();
7131     }
7132     return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7133 }
7134
7135 /*!
7136     \fn void QPainter::setViewport(const QRect &rectangle)
7137
7138     Sets the painter's viewport rectangle to the given \a rectangle,
7139     and enables view transformations.
7140
7141     The viewport rectangle is part of the view transformation. The
7142     viewport specifies the device coordinate system. Its sister, the
7143     window(), specifies the logical coordinate system.
7144
7145     The default viewport rectangle is the same as the device's
7146     rectangle.
7147
7148     \sa viewport(), viewTransformEnabled() {Coordinate
7149     System#Window-Viewport Conversion}{Window-Viewport Conversion}
7150 */
7151
7152 /*!
7153     \fn void QPainter::setViewport(int x, int y, int width, int height)
7154     \overload
7155
7156     Sets the painter's viewport rectangle to be the rectangle
7157     beginning at (\a x, \a y) with the given \a width and \a height.
7158 */
7159
7160 void QPainter::setViewport(const QRect &r)
7161 {
7162 #ifdef QT_DEBUG_DRAW
7163     if (qt_show_painter_debug_output)
7164         printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7165 #endif
7166
7167     Q_D(QPainter);
7168
7169     if (!d->engine) {
7170         qWarning("QPainter::setViewport: Painter not active");
7171         return;
7172     }
7173
7174     d->state->vx = r.x();
7175     d->state->vy = r.y();
7176     d->state->vw = r.width();
7177     d->state->vh = r.height();
7178
7179     d->state->VxF = true;
7180     d->updateMatrix();
7181 }
7182
7183 /*!
7184     Returns the viewport rectangle.
7185
7186     \sa setViewport(), setViewTransformEnabled()
7187 */
7188
7189 QRect QPainter::viewport() const
7190 {
7191     Q_D(const QPainter);
7192     if (!d->engine) {
7193         qWarning("QPainter::viewport: Painter not active");
7194         return QRect();
7195     }
7196     return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7197 }
7198
7199 /*!
7200     Enables view transformations if \a enable is true, or disables
7201     view transformations if \a enable is false.
7202
7203     \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7204     Conversion}{Window-Viewport Conversion}
7205 */
7206
7207 void QPainter::setViewTransformEnabled(bool enable)
7208 {
7209 #ifdef QT_DEBUG_DRAW
7210     if (qt_show_painter_debug_output)
7211         printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7212 #endif
7213
7214     Q_D(QPainter);
7215
7216     if (!d->engine) {
7217         qWarning("QPainter::setViewTransformEnabled: Painter not active");
7218         return;
7219     }
7220
7221     if (enable == d->state->VxF)
7222         return;
7223
7224     d->state->VxF = enable;
7225     d->updateMatrix();
7226 }
7227
7228 /*!
7229     \threadsafe
7230
7231     \obsolete
7232
7233     Please use QWidget::render() instead.
7234
7235     Redirects all paint commands for the given paint \a device, to the
7236     \a replacement device. The optional point \a offset defines an
7237     offset within the source device.
7238
7239     The redirection will not be effective until the begin() function
7240     has been called; make sure to call end() for the given \a
7241     device's painter (if any) before redirecting. Call
7242     restoreRedirected() to restore the previous redirection.
7243
7244     \warning Making use of redirections in the QPainter API implies
7245     that QPainter::begin() and QPaintDevice destructors need to hold
7246     a mutex for a short period. This can impact performance. Use of
7247     QWidget::render is strongly encouraged.
7248
7249     \sa redirected(), restoreRedirected()
7250 */
7251 void QPainter::setRedirected(const QPaintDevice *device,
7252                              QPaintDevice *replacement,
7253                              const QPoint &offset)
7254 {
7255     Q_ASSERT(device != 0);
7256     Q_UNUSED(replacement)
7257     Q_UNUSED(offset)
7258     qWarning("QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7259 }
7260
7261 /*!
7262     \threadsafe
7263
7264     \obsolete
7265
7266     Using QWidget::render() obsoletes the use of this function.
7267
7268     Restores the previous redirection for the given \a device after a
7269     call to setRedirected().
7270
7271     \warning Making use of redirections in the QPainter API implies
7272     that QPainter::begin() and QPaintDevice destructors need to hold
7273     a mutex for a short period. This can impact performance. Use of
7274     QWidget::render is strongly encouraged.
7275
7276     \sa redirected()
7277  */
7278 void QPainter::restoreRedirected(const QPaintDevice *device)
7279 {
7280     Q_UNUSED(device)
7281     qWarning("QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7282 }
7283
7284 /*!
7285     \threadsafe
7286
7287     \obsolete
7288
7289     Using QWidget::render() obsoletes the use of this function.
7290
7291     Returns the replacement for given \a device. The optional out
7292     parameter \a offset returns the offset within the replaced device.
7293
7294     \warning Making use of redirections in the QPainter API implies
7295     that QPainter::begin() and QPaintDevice destructors need to hold
7296     a mutex for a short period. This can impact performance. Use of
7297     QWidget::render is strongly encouraged.
7298
7299     \sa setRedirected(), restoreRedirected()
7300 */
7301 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7302 {
7303     Q_UNUSED(device)
7304     Q_UNUSED(offset)
7305     return 0;
7306 }
7307
7308 void qt_format_text(const QFont &fnt, const QRectF &_r,
7309                     int tf, const QString& str, QRectF *brect,
7310                     int tabstops, int *ta, int tabarraylen,
7311                     QPainter *painter)
7312 {
7313     qt_format_text(fnt, _r,
7314                     tf, 0, str, brect,
7315                     tabstops, ta, tabarraylen,
7316                     painter);
7317 }
7318 void qt_format_text(const QFont &fnt, const QRectF &_r,
7319                     int tf, const QTextOption *option, const QString& str, QRectF *brect,
7320                     int tabstops, int *ta, int tabarraylen,
7321                     QPainter *painter)
7322 {
7323
7324     Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
7325
7326     if (option) {
7327         tf |= option->alignment();
7328         if (option->wrapMode() != QTextOption::NoWrap)
7329             tf |= Qt::TextWordWrap;
7330
7331         if (option->flags() & QTextOption::IncludeTrailingSpaces)
7332             tf |= Qt::TextIncludeTrailingSpaces;
7333
7334         if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
7335             tf |= Qt::TextExpandTabs;
7336     }
7337
7338     // we need to copy r here to protect against the case (&r == brect).
7339     QRectF r(_r);
7340
7341     bool dontclip  = (tf & Qt::TextDontClip);
7342     bool wordwrap  = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
7343     bool singleline = (tf & Qt::TextSingleLine);
7344     bool showmnemonic = (tf & Qt::TextShowMnemonic);
7345     bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
7346
7347     Qt::LayoutDirection layout_direction;
7348     if (tf & Qt::TextForceLeftToRight)
7349         layout_direction = Qt::LeftToRight;
7350     else if (tf & Qt::TextForceRightToLeft)
7351         layout_direction = Qt::RightToLeft;
7352     else if (option)
7353         layout_direction = option->textDirection();
7354     else if (painter)
7355         layout_direction = painter->layoutDirection();
7356     else
7357         layout_direction = Qt::LeftToRight;
7358
7359     tf = QGuiApplicationPrivate::visualAlignment(layout_direction, QFlag(tf));
7360
7361     bool isRightToLeft = layout_direction == Qt::RightToLeft;
7362     bool expandtabs = ((tf & Qt::TextExpandTabs) &&
7363                         (((tf & Qt::AlignLeft) && !isRightToLeft) ||
7364                           ((tf & Qt::AlignRight) && isRightToLeft)));
7365
7366     if (!painter)
7367         tf |= Qt::TextDontPrint;
7368
7369     uint maxUnderlines = 0;
7370     int numUnderlines = 0;
7371     QVarLengthArray<int, 32> underlinePositions(1);
7372
7373     QFontMetricsF fm(fnt);
7374     QString text = str;
7375     int offset = 0;
7376 start_lengthVariant:
7377     bool hasMoreLengthVariants = false;
7378     // compatible behaviour to the old implementation. Replace
7379     // tabs by spaces
7380     int old_offset = offset;
7381     for (; offset < text.length(); offset++) {
7382         QChar chr = text.at(offset);
7383         if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
7384             text[offset] = QLatin1Char(' ');
7385         } else if (chr == QLatin1Char('\n')) {
7386             text[offset] = QChar::LineSeparator;
7387         } else if (chr == QLatin1Char('&')) {
7388             ++maxUnderlines;
7389         } else if (chr == QLatin1Char('\t')) {
7390             if (!expandtabs) {
7391                 text[offset] = QLatin1Char(' ');
7392             } else if (!tabarraylen && !tabstops) {
7393                 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
7394             }
7395         } else if (chr == QChar(ushort(0x9c))) {
7396             // string with multiple length variants
7397             hasMoreLengthVariants = true;
7398             break;
7399         }
7400     }
7401
7402     int length = offset - old_offset;
7403     if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
7404         underlinePositions.resize(maxUnderlines + 1);
7405
7406         QChar *cout = text.data() + old_offset;
7407         QChar *cin = cout;
7408         int l = length;
7409         while (l) {
7410             if (*cin == QLatin1Char('&')) {
7411                 ++cin;
7412                 --length;
7413                 --l;
7414                 if (!l)
7415                     break;
7416                 if (*cin != QLatin1Char('&') && !hidemnmemonic)
7417                     underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
7418             }
7419             *cout = *cin;
7420             ++cout;
7421             ++cin;
7422             --l;
7423         }
7424     }
7425
7426     // no need to do extra work for underlines if we don't paint
7427     if (tf & Qt::TextDontPrint)
7428         numUnderlines = 0;
7429
7430     underlinePositions[numUnderlines] = -1;
7431     qreal height = 0;
7432     qreal width = 0;
7433
7434     QString finalText = text.mid(old_offset, length);
7435     QStackTextEngine engine(finalText, fnt);
7436     if (option) {
7437         engine.option = *option;
7438     }
7439
7440     if (engine.option.tabStop() < 0 && tabstops > 0)
7441         engine.option.setTabStop(tabstops);
7442
7443     if (engine.option.tabs().isEmpty() && ta) {
7444         QList<qreal> tabs;
7445         for (int i = 0; i < tabarraylen; i++)
7446             tabs.append(qreal(ta[i]));
7447         engine.option.setTabArray(tabs);
7448     }
7449
7450     engine.option.setTextDirection(layout_direction);
7451     if (tf & Qt::AlignJustify)
7452         engine.option.setAlignment(Qt::AlignJustify);
7453     else
7454         engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
7455
7456     if (!option && (tf & Qt::TextWrapAnywhere))
7457         engine.option.setWrapMode(QTextOption::WrapAnywhere);
7458
7459     if (tf & Qt::TextJustificationForced)
7460         engine.forceJustification = true;
7461     QTextLayout textLayout(&engine);
7462     textLayout.setCacheEnabled(true);
7463     textLayout.engine()->underlinePositions = underlinePositions.data();
7464
7465     if (finalText.isEmpty()) {
7466         height = fm.height();
7467         width = 0;
7468         tf |= Qt::TextDontPrint;
7469     } else {
7470         qreal lineWidth = 0x01000000;
7471         if (wordwrap || (tf & Qt::TextJustificationForced))
7472             lineWidth = qMax<qreal>(0, r.width());
7473         if(!wordwrap)
7474             tf |= Qt::TextIncludeTrailingSpaces;
7475         textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
7476         textLayout.beginLayout();
7477
7478         qreal leading = fm.leading();
7479         height = -leading;
7480
7481         while (1) {
7482             QTextLine l = textLayout.createLine();
7483             if (!l.isValid())
7484                 break;
7485
7486             l.setLineWidth(lineWidth);
7487             height += leading;
7488             l.setPosition(QPointF(0., height));
7489             height += l.height();
7490             width = qMax(width, l.naturalTextWidth());
7491             if (!dontclip && !brect && height >= r.height())
7492                 break;
7493         }
7494         textLayout.endLayout();
7495     }
7496
7497     qreal yoff = 0;
7498     qreal xoff = 0;
7499     if (tf & Qt::AlignBottom) {
7500         yoff = r.height() - height;
7501     } else if (tf & Qt::AlignVCenter) {
7502         yoff = (r.height() - height)/2;
7503         if (painter) {
7504             QTransform::TransformationType type = painter->transform().type();
7505             if (type <= QTransform::TxScale) {
7506                 // do the rounding manually to work around inconsistencies
7507                 // in the paint engines when drawing on floating point offsets
7508                 const qreal scale = painter->transform().m22();
7509                 if (scale != 0)
7510                     yoff = -qRound(-yoff * scale) / scale;
7511             }
7512         }
7513     }
7514     if (tf & Qt::AlignRight) {
7515         xoff = r.width() - width;
7516     } else if (tf & Qt::AlignHCenter) {
7517         xoff = (r.width() - width)/2;
7518         if (painter) {
7519             QTransform::TransformationType type = painter->transform().type();
7520             if (type <= QTransform::TxScale) {
7521                 // do the rounding manually to work around inconsistencies
7522                 // in the paint engines when drawing on floating point offsets
7523                 const qreal scale = painter->transform().m11();
7524                 if (scale != 0)
7525                     xoff = qRound(xoff * scale) / scale;
7526             }
7527         }
7528     }
7529     QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
7530
7531     if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
7532         offset++;
7533         goto start_lengthVariant;
7534     }
7535     if (brect)
7536         *brect = bounds;
7537
7538     if (!(tf & Qt::TextDontPrint)) {
7539         bool restore = false;
7540         if (!dontclip && !r.contains(bounds)) {
7541             restore = true;
7542             painter->save();
7543             painter->setClipRect(r, Qt::IntersectClip);
7544         }
7545
7546         for (int i = 0; i < textLayout.lineCount(); i++) {
7547             QTextLine line = textLayout.lineAt(i);
7548
7549             qreal advance = line.horizontalAdvance();
7550             xoff = 0;
7551             if (tf & Qt::AlignRight) {
7552                 QTextEngine *eng = textLayout.engine();
7553                 xoff = r.width() - advance -
7554                     eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
7555             }
7556             else if (tf & Qt::AlignHCenter)
7557                 xoff = (r.width() - advance) / 2;
7558
7559             line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
7560         }
7561
7562         if (restore) {
7563             painter->restore();
7564         }
7565     }
7566 }
7567
7568 /*!
7569     Sets the layout direction used by the painter when drawing text,
7570     to the specified \a direction.
7571
7572     The default is Qt::LayoutDirectionAuto, which will implicitly determine the
7573     direction from the text drawn.
7574
7575     \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
7576 */
7577 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
7578 {
7579     Q_D(QPainter);
7580     if (d->state)
7581         d->state->layoutDirection = direction;
7582 }
7583
7584 /*!
7585     Returns the layout direction used by the painter when drawing text.
7586
7587     \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
7588 */
7589 Qt::LayoutDirection QPainter::layoutDirection() const
7590 {
7591     Q_D(const QPainter);
7592     return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
7593 }
7594
7595 QPainterState::QPainterState(const QPainterState *s)
7596     : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
7597       pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
7598       clipRegion(s->clipRegion), clipPath(s->clipPath),
7599       clipOperation(s->clipOperation),
7600       renderHints(s->renderHints), clipInfo(s->clipInfo),
7601       worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
7602       wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
7603       vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
7604       opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
7605       clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
7606       layoutDirection(s->layoutDirection),
7607       composition_mode(s->composition_mode),
7608       emulationSpecifier(s->emulationSpecifier), changeFlags(0)
7609 {
7610     dirtyFlags = s->dirtyFlags;
7611 }
7612
7613 QPainterState::QPainterState()
7614     : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
7615       renderHints(0),
7616       wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
7617       opacity(1), WxF(false), VxF(false), clipEnabled(true),
7618       bgMode(Qt::TransparentMode), painter(0),
7619       layoutDirection(QGuiApplication::layoutDirection()),
7620       composition_mode(QPainter::CompositionMode_SourceOver),
7621       emulationSpecifier(0), changeFlags(0)
7622 {
7623     dirtyFlags = 0;
7624 }
7625
7626 QPainterState::~QPainterState()
7627 {
7628 }
7629
7630 void QPainterState::init(QPainter *p) {
7631     bgBrush = Qt::white;
7632     bgMode = Qt::TransparentMode;
7633     WxF = false;
7634     VxF = false;
7635     clipEnabled = true;
7636     wx = wy = ww = wh = 0;
7637     vx = vy = vw = vh = 0;
7638     painter = p;
7639     pen = QPen();
7640     brushOrigin = QPointF(0, 0);
7641     brush = QBrush();
7642     font = deviceFont = QFont();
7643     clipRegion = QRegion();
7644     clipPath = QPainterPath();
7645     clipOperation = Qt::NoClip;
7646     clipInfo.clear();
7647     worldMatrix.reset();
7648     matrix.reset();
7649     layoutDirection = QGuiApplication::layoutDirection();
7650     composition_mode = QPainter::CompositionMode_SourceOver;
7651     emulationSpecifier = 0;
7652     dirtyFlags = 0;
7653     changeFlags = 0;
7654     renderHints = 0;
7655     opacity = 1;
7656 }
7657
7658 /*!
7659     \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
7660                          Qt::ImageConversionFlags flags)
7661
7662     Draws the rectangular portion \a source of the given \a image
7663     into the \a target rectangle in the paint device.
7664
7665     \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7666
7667     If the image needs to be modified to fit in a lower-resolution
7668     result (e.g. converting from 32-bit to 8-bit), use the \a flags to
7669     specify how you would prefer this to happen.
7670
7671     \table 100%
7672     \row
7673     \li
7674     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 20
7675     \endtable
7676
7677     \sa drawPixmap()
7678 */
7679
7680 /*!
7681     \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
7682                                  Qt::ImageConversionFlags flags)
7683     \overload
7684
7685     Draws the rectangular portion \a source of the given \a image
7686     into the \a target rectangle in the paint device.
7687
7688     \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7689 */
7690
7691 /*!
7692     \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
7693
7694     \overload
7695
7696     Draws the given \a image at the given \a point.
7697 */
7698
7699 /*!
7700     \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
7701
7702     \overload
7703
7704     Draws the given \a image at the given \a point.
7705 */
7706
7707 /*!
7708     \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
7709                                  Qt::ImageConversionFlags flags = 0)
7710
7711     \overload
7712
7713     Draws the rectangular portion \a source of the given \a image with
7714     its origin at the given \a point.
7715 */
7716
7717 /*!
7718     \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
7719                                  Qt::ImageConversionFlags flags = 0)
7720     \overload
7721
7722     Draws the rectangular portion \a source of the given \a image with
7723     its origin at the given \a point.
7724 */
7725
7726 /*!
7727     \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
7728
7729     \overload
7730
7731     Draws the given \a image into the given \a rectangle.
7732
7733     \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7734 */
7735
7736 /*!
7737     \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
7738
7739     \overload
7740
7741     Draws the given \a image into the given \a rectangle.
7742
7743    \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7744 */
7745
7746 /*!
7747     \fn void QPainter::drawImage(int x, int y, const QImage &image,
7748                                  int sx, int sy, int sw, int sh,
7749                                  Qt::ImageConversionFlags flags)
7750     \overload
7751
7752     Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
7753     the paint device.
7754
7755     (\a{x}, \a{y}) specifies the top-left point in the paint device that is
7756     to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
7757     image that is to be drawn. The default is (0, 0).
7758
7759     (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
7760     The default, (0, 0) (and negative) means all the way to the
7761     bottom-right of the image.
7762 */
7763
7764 /*!
7765     \class QPaintEngineState
7766     \since 4.1
7767
7768     \brief The QPaintEngineState class provides information about the
7769     active paint engine's current state.
7770     \reentrant
7771
7772     QPaintEngineState records which properties that have changed since
7773     the last time the paint engine was updated, as well as their
7774     current value.
7775
7776     Which properties that have changed can at any time be retrieved
7777     using the state() function. This function returns an instance of
7778     the QPaintEngine::DirtyFlags type which stores an OR combination
7779     of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
7780     enum defines whether a property has changed since the last update
7781     or not.
7782
7783     If a property is marked with a dirty flag, its current value can
7784     be retrieved using the corresponding get function:
7785
7786     \target GetFunction
7787
7788     \table
7789     \header \li Property Flag \li Current Property Value
7790     \row \li QPaintEngine::DirtyBackground \li backgroundBrush()
7791     \row \li QPaintEngine::DirtyBackgroundMode \li backgroundMode()
7792     \row \li QPaintEngine::DirtyBrush \li brush()
7793     \row \li QPaintEngine::DirtyBrushOrigin \li brushOrigin()
7794     \row \li QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
7795          \li clipOperation()
7796     \row \li QPaintEngine::DirtyClipPath \li clipPath()
7797     \row \li QPaintEngine::DirtyClipRegion \li clipRegion()
7798     \row \li QPaintEngine::DirtyCompositionMode \li compositionMode()
7799     \row \li QPaintEngine::DirtyFont \li font()
7800     \row \li QPaintEngine::DirtyTransform \li transform()
7801     \row \li QPaintEngine::DirtyClipEnabled \li isClipEnabled()
7802     \row \li QPaintEngine::DirtyPen \li pen()
7803     \row \li QPaintEngine::DirtyHints \li renderHints()
7804     \endtable
7805
7806     The QPaintEngineState class also provide the painter() function
7807     which returns a pointer to the painter that is currently updating
7808     the paint engine.
7809
7810     An instance of this class, representing the current state of the
7811     active paint engine, is passed as argument to the
7812     QPaintEngine::updateState() function. The only situation in which
7813     you will have to use this class directly is when implementing your
7814     own paint engine.
7815
7816     \sa QPaintEngine
7817 */
7818
7819
7820 /*!
7821     \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
7822
7823     Returns a combination of flags identifying the set of properties
7824     that need to be updated when updating the paint engine's state
7825     (i.e. during a call to the QPaintEngine::updateState() function).
7826
7827     \sa QPaintEngine::updateState()
7828 */
7829
7830
7831 /*!
7832     Returns the pen in the current paint engine state.
7833
7834     This variable should only be used when the state() returns a
7835     combination which includes the QPaintEngine::DirtyPen flag.
7836
7837     \sa state(), QPaintEngine::updateState()
7838 */
7839
7840 QPen QPaintEngineState::pen() const
7841 {
7842     return static_cast<const QPainterState *>(this)->pen;
7843 }
7844
7845 /*!
7846     Returns the brush in the current paint engine state.
7847
7848     This variable should only be used when the state() returns a
7849     combination which includes the QPaintEngine::DirtyBrush flag.
7850
7851     \sa state(), QPaintEngine::updateState()
7852 */
7853
7854 QBrush QPaintEngineState::brush() const
7855 {
7856     return static_cast<const QPainterState *>(this)->brush;
7857 }
7858
7859 /*!
7860     Returns the brush origin in the current paint engine state.
7861
7862     This variable should only be used when the state() returns a
7863     combination which includes the QPaintEngine::DirtyBrushOrigin flag.
7864
7865     \sa state(), QPaintEngine::updateState()
7866 */
7867
7868 QPointF QPaintEngineState::brushOrigin() const
7869 {
7870     return static_cast<const QPainterState *>(this)->brushOrigin;
7871 }
7872
7873 /*!
7874     Returns the background brush in the current paint engine state.
7875
7876     This variable should only be used when the state() returns a
7877     combination which includes the QPaintEngine::DirtyBackground flag.
7878
7879     \sa state(), QPaintEngine::updateState()
7880 */
7881
7882 QBrush QPaintEngineState::backgroundBrush() const
7883 {
7884     return static_cast<const QPainterState *>(this)->bgBrush;
7885 }
7886
7887 /*!
7888     Returns the background mode in the current paint engine
7889     state.
7890
7891     This variable should only be used when the state() returns a
7892     combination which includes the QPaintEngine::DirtyBackgroundMode flag.
7893
7894     \sa state(), QPaintEngine::updateState()
7895 */
7896
7897 Qt::BGMode QPaintEngineState::backgroundMode() const
7898 {
7899     return static_cast<const QPainterState *>(this)->bgMode;
7900 }
7901
7902 /*!
7903     Returns the font in the current paint engine
7904     state.
7905
7906     This variable should only be used when the state() returns a
7907     combination which includes the QPaintEngine::DirtyFont flag.
7908
7909     \sa state(), QPaintEngine::updateState()
7910 */
7911
7912 QFont QPaintEngineState::font() const
7913 {
7914     return static_cast<const QPainterState *>(this)->font;
7915 }
7916
7917 /*!
7918     \since 4.2
7919     \obsolete
7920
7921     Returns the matrix in the current paint engine
7922     state.
7923
7924     \note It is advisable to use transform() instead of this function to
7925     preserve the properties of perspective transformations.
7926
7927     This variable should only be used when the state() returns a
7928     combination which includes the QPaintEngine::DirtyTransform flag.
7929
7930     \sa state(), QPaintEngine::updateState()
7931 */
7932
7933 QMatrix QPaintEngineState::matrix() const
7934 {
7935     const QPainterState *st = static_cast<const QPainterState *>(this);
7936
7937     return st->matrix.toAffine();
7938 }
7939
7940 /*!
7941     \since 4.3
7942
7943     Returns the matrix in the current paint engine state.
7944
7945     This variable should only be used when the state() returns a
7946     combination which includes the QPaintEngine::DirtyTransform flag.
7947
7948     \sa state(), QPaintEngine::updateState()
7949 */
7950
7951
7952 QTransform QPaintEngineState::transform() const
7953 {
7954     const QPainterState *st = static_cast<const QPainterState *>(this);
7955
7956     return st->matrix;
7957 }
7958
7959
7960 /*!
7961     Returns the clip operation in the current paint engine
7962     state.
7963
7964     This variable should only be used when the state() returns a
7965     combination which includes either the QPaintEngine::DirtyClipPath
7966     or the QPaintEngine::DirtyClipRegion flag.
7967
7968     \sa state(), QPaintEngine::updateState()
7969 */
7970
7971 Qt::ClipOperation QPaintEngineState::clipOperation() const
7972 {
7973     return static_cast<const QPainterState *>(this)->clipOperation;
7974 }
7975
7976 /*!
7977     \since 4.3
7978
7979     Returns whether the coordinate of the fill have been specified
7980     as bounded by the current rendering operation and have to be
7981     resolved (about the currently rendered primitive).
7982 */
7983 bool QPaintEngineState::brushNeedsResolving() const
7984 {
7985     const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
7986     return needsResolving(brush);
7987 }
7988
7989
7990 /*!
7991     \since 4.3
7992
7993     Returns whether the coordinate of the stroke have been specified
7994     as bounded by the current rendering operation and have to be
7995     resolved (about the currently rendered primitive).
7996 */
7997 bool QPaintEngineState::penNeedsResolving() const
7998 {
7999     const QPen &pen = static_cast<const QPainterState *>(this)->pen;
8000     return needsResolving(pen.brush());
8001 }
8002
8003 /*!
8004     Returns the clip region in the current paint engine state.
8005
8006     This variable should only be used when the state() returns a
8007     combination which includes the QPaintEngine::DirtyClipRegion flag.
8008
8009     \sa state(), QPaintEngine::updateState()
8010 */
8011
8012 QRegion QPaintEngineState::clipRegion() const
8013 {
8014     return static_cast<const QPainterState *>(this)->clipRegion;
8015 }
8016
8017 /*!
8018     Returns the clip path in the current paint engine state.
8019
8020     This variable should only be used when the state() returns a
8021     combination which includes the QPaintEngine::DirtyClipPath flag.
8022
8023     \sa state(), QPaintEngine::updateState()
8024 */
8025
8026 QPainterPath QPaintEngineState::clipPath() const
8027 {
8028     return static_cast<const QPainterState *>(this)->clipPath;
8029 }
8030
8031 /*!
8032     Returns whether clipping is enabled or not in the current paint
8033     engine state.
8034
8035     This variable should only be used when the state() returns a
8036     combination which includes the QPaintEngine::DirtyClipEnabled
8037     flag.
8038
8039     \sa state(), QPaintEngine::updateState()
8040 */
8041
8042 bool QPaintEngineState::isClipEnabled() const
8043 {
8044     return static_cast<const QPainterState *>(this)->clipEnabled;
8045 }
8046
8047 /*!
8048     Returns the render hints in the current paint engine state.
8049
8050     This variable should only be used when the state() returns a
8051     combination which includes the QPaintEngine::DirtyHints
8052     flag.
8053
8054     \sa state(), QPaintEngine::updateState()
8055 */
8056
8057 QPainter::RenderHints QPaintEngineState::renderHints() const
8058 {
8059     return static_cast<const QPainterState *>(this)->renderHints;
8060 }
8061
8062 /*!
8063     Returns the composition mode in the current paint engine state.
8064
8065     This variable should only be used when the state() returns a
8066     combination which includes the QPaintEngine::DirtyCompositionMode
8067     flag.
8068
8069     \sa state(), QPaintEngine::updateState()
8070 */
8071
8072 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8073 {
8074     return static_cast<const QPainterState *>(this)->composition_mode;
8075 }
8076
8077
8078 /*!
8079     Returns a pointer to the painter currently updating the paint
8080     engine.
8081 */
8082
8083 QPainter *QPaintEngineState::painter() const
8084 {
8085     return static_cast<const QPainterState *>(this)->painter;
8086 }
8087
8088
8089 /*!
8090     \since 4.2
8091
8092     Returns the opacity in the current paint engine state.
8093 */
8094
8095 qreal QPaintEngineState::opacity() const
8096 {
8097     return static_cast<const QPainterState *>(this)->opacity;
8098 }
8099
8100 /*!
8101     \since 4.3
8102
8103     Sets the world transformation matrix.
8104     If \a combine is true, the specified \a transform is combined with
8105     the current matrix; otherwise it replaces the current matrix.
8106
8107     \sa transform() setWorldTransform()
8108 */
8109
8110 void QPainter::setTransform(const QTransform &transform, bool combine )
8111 {
8112     setWorldTransform(transform, combine);
8113 }
8114
8115 /*!
8116     Returns the world transformation matrix.
8117
8118     \sa worldTransform()
8119 */
8120
8121 const QTransform & QPainter::transform() const
8122 {
8123     return worldTransform();
8124 }
8125
8126
8127 /*!
8128     Returns the matrix that transforms from logical coordinates to
8129     device coordinates of the platform dependent paint device.
8130
8131     This function is \e only needed when using platform painting
8132     commands on the platform dependent handle (Qt::HANDLE), and the
8133     platform does not do transformations nativly.
8134
8135     The QPaintEngine::PaintEngineFeature enum can be queried to
8136     determine whether the platform performs the transformations or
8137     not.
8138
8139     \sa worldTransform(), QPaintEngine::hasFeature(),
8140 */
8141
8142 const QTransform & QPainter::deviceTransform() const
8143 {
8144     Q_D(const QPainter);
8145     if (!d->engine) {
8146         qWarning("QPainter::deviceTransform: Painter not active");
8147         return d->fakeState()->transform;
8148     }
8149     return d->state->matrix;
8150 }
8151
8152
8153 /*!
8154     Resets any transformations that were made using translate(),
8155     scale(), shear(), rotate(), setWorldTransform(), setViewport()
8156     and setWindow().
8157
8158     \sa {Coordinate Transformations}
8159 */
8160
8161 void QPainter::resetTransform()
8162 {
8163      Q_D(QPainter);
8164 #ifdef QT_DEBUG_DRAW
8165     if (qt_show_painter_debug_output)
8166         printf("QPainter::resetMatrix()\n");
8167 #endif
8168     if (!d->engine) {
8169         qWarning("QPainter::resetMatrix: Painter not active");
8170         return;
8171     }
8172
8173     d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0;                        // default view origins
8174     d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
8175     d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
8176     d->state->worldMatrix = QTransform();
8177     setMatrixEnabled(false);
8178     setViewTransformEnabled(false);
8179     if (d->extended)
8180         d->extended->transformChanged();
8181     else
8182         d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
8183 }
8184
8185 /*!
8186     Sets the world transformation matrix.
8187     If \a combine is true, the specified \a matrix is combined with the current matrix;
8188     otherwise it replaces the current matrix.
8189
8190     \sa transform(), setTransform()
8191 */
8192
8193 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
8194 {
8195     Q_D(QPainter);
8196
8197     if (!d->engine) {
8198         qWarning("QPainter::setWorldTransform: Painter not active");
8199         return;
8200     }
8201
8202     if (combine)
8203         d->state->worldMatrix = matrix * d->state->worldMatrix;                        // combines
8204     else
8205         d->state->worldMatrix = matrix;                                // set new matrix
8206
8207     d->state->WxF = true;
8208     d->updateMatrix();
8209 }
8210
8211 /*!
8212     Returns the world transformation matrix.
8213 */
8214
8215 const QTransform & QPainter::worldTransform() const
8216 {
8217     Q_D(const QPainter);
8218     if (!d->engine) {
8219         qWarning("QPainter::worldTransform: Painter not active");
8220         return d->fakeState()->transform;
8221     }
8222     return d->state->worldMatrix;
8223 }
8224
8225 /*!
8226     Returns the transformation matrix combining the current
8227     window/viewport and world transformation.
8228
8229     \sa setWorldTransform(), setWindow(), setViewport()
8230 */
8231
8232 QTransform QPainter::combinedTransform() const
8233 {
8234     Q_D(const QPainter);
8235     if (!d->engine) {
8236         qWarning("QPainter::combinedTransform: Painter not active");
8237         return QTransform();
8238     }
8239     return d->state->worldMatrix * d->viewTransform();
8240 }
8241
8242 /*!
8243     \since 4.7
8244
8245     This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
8246     at multiple positions with different scale, rotation and opacity. \a
8247     fragments is an array of \a fragmentCount elements specifying the
8248     parameters used to draw each pixmap fragment. The \a hints
8249     parameter can be used to pass in drawing hints.
8250
8251     This function is potentially faster than multiple calls to drawPixmap(),
8252     since the backend can optimize state changes.
8253
8254     \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
8255 */
8256
8257 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
8258                                    const QPixmap &pixmap, PixmapFragmentHints hints)
8259 {
8260     Q_D(QPainter);
8261
8262     if (!d->engine || pixmap.isNull())
8263         return;
8264
8265 #ifndef QT_NO_DEBUG
8266     for (int i = 0; i < fragmentCount; ++i) {
8267         QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8268                           fragments[i].width, fragments[i].height);
8269         if (!(QRectF(pixmap.rect()).contains(sourceRect)))
8270             qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
8271     }
8272 #endif
8273
8274     if (d->engine->isExtended()) {
8275         d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
8276     } else {
8277         qreal oldOpacity = opacity();
8278         QTransform oldTransform = transform();
8279
8280         for (int i = 0; i < fragmentCount; ++i) {
8281             QTransform transform = oldTransform;
8282             qreal xOffset = 0;
8283             qreal yOffset = 0;
8284             if (fragments[i].rotation == 0) {
8285                 xOffset = fragments[i].x;
8286                 yOffset = fragments[i].y;
8287             } else {
8288                 transform.translate(fragments[i].x, fragments[i].y);
8289                 transform.rotate(fragments[i].rotation);
8290             }
8291             setOpacity(oldOpacity * fragments[i].opacity);
8292             setTransform(transform);
8293
8294             qreal w = fragments[i].scaleX * fragments[i].width;
8295             qreal h = fragments[i].scaleY * fragments[i].height;
8296             QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8297                               fragments[i].width, fragments[i].height);
8298             drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
8299         }
8300
8301         setOpacity(oldOpacity);
8302         setTransform(oldTransform);
8303     }
8304 }
8305
8306 /*!
8307     \since 4.7
8308     \class QPainter::PixmapFragment
8309
8310     \brief This class is used in conjunction with the
8311     QPainter::drawPixmapFragments() function to specify how a pixmap, or
8312     sub-rect of a pixmap, is drawn.
8313
8314     The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
8315     as a source rectangle within the pixmap passed into the
8316     QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
8317     width and \a height are used to calculate the target rectangle that is
8318     drawn. \a x and \a y denotes the center of the target rectangle. The \a
8319     width and \a height in the target rectangle is scaled by the \a scaleX and
8320     \a scaleY values. The resulting target rectangle is then rotated \a
8321     rotation degrees around the \a x, \a y center point.
8322
8323     \sa QPainter::drawPixmapFragments()
8324 */
8325
8326 /*!
8327     \since 4.7
8328
8329     This is a convenience function that returns a QPainter::PixmapFragment that is
8330     initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
8331     rotation, \a opacity parameters.
8332 */
8333
8334 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
8335                                               qreal scaleX, qreal scaleY, qreal rotation,
8336                                               qreal opacity)
8337 {
8338     PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
8339                                sourceRect.height(), scaleX, scaleY, rotation, opacity};
8340     return fragment;
8341 }
8342
8343 /*!
8344     \variable QPainter::PixmapFragment::x
8345     \brief the x coordinate of center point in the target rectangle.
8346 */
8347
8348 /*!
8349     \variable QPainter::PixmapFragment::y
8350     \brief the y coordinate of the center point in the target rectangle.
8351 */
8352
8353 /*!
8354     \variable QPainter::PixmapFragment::sourceLeft
8355     \brief the left coordinate of the source rectangle.
8356 */
8357
8358 /*!
8359     \variable QPainter::PixmapFragment::sourceTop
8360     \brief the top coordinate of the source rectangle.
8361 */
8362
8363 /*!
8364     \variable QPainter::PixmapFragment::width
8365
8366     \brief the width of the source rectangle and is used to calculate the width
8367     of the target rectangle.
8368 */
8369
8370 /*!
8371     \variable QPainter::PixmapFragment::height
8372
8373     \brief the height of the source rectangle and is used to calculate the
8374     height of the target rectangle.
8375 */
8376
8377 /*!
8378     \variable QPainter::PixmapFragment::scaleX
8379     \brief the horizontal scale of the target rectangle.
8380 */
8381
8382 /*!
8383     \variable QPainter::PixmapFragment::scaleY
8384     \brief the vertical scale of the target rectangle.
8385 */
8386
8387 /*!
8388     \variable QPainter::PixmapFragment::rotation
8389
8390     \brief the rotation of the target rectangle in degrees. The target
8391     rectangle is rotated after it has been scaled.
8392 */
8393
8394 /*!
8395     \variable QPainter::PixmapFragment::opacity
8396
8397     \brief the opacity of the target rectangle, where 0.0 is fully transparent
8398     and 1.0 is fully opaque.
8399 */
8400
8401 /*!
8402     \since 4.7
8403
8404     \enum QPainter::PixmapFragmentHint
8405
8406     \value OpaqueHint Indicates that the pixmap fragments to be drawn are
8407     opaque. Opaque fragments are potentially faster to draw.
8408
8409     \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
8410 */
8411
8412 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
8413 {
8414     p->draw_helper(path, operation);
8415 }
8416
8417 QT_END_NAMESPACE