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