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