Fix font engine dependent text transformation
[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 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 code/src_gui_painting_qpainter.cpp 1
1450
1451     The same example using this constructor:
1452     \snippet 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 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 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 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 Transformations}
3089 */
3090
3091 void QPainter::scale(qreal sx, qreal sy)
3092 {
3093 #ifdef QT_DEBUG_DRAW
3094     if (qt_show_painter_debug_output)
3095         printf("QPainter::scale(), sx=%f, sy=%f\n", sx, sy);
3096 #endif
3097     Q_D(QPainter);
3098     if (!d->engine) {
3099         qWarning("QPainter::scale: Painter not active");
3100         return;
3101     }
3102
3103     d->state->worldMatrix.scale(sx,sy);
3104     d->state->WxF = true;
3105     d->updateMatrix();
3106 }
3107
3108 /*!
3109     Shears the coordinate system by (\a{sh}, \a{sv}).
3110
3111     \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3112 */
3113
3114 void QPainter::shear(qreal sh, qreal sv)
3115 {
3116 #ifdef QT_DEBUG_DRAW
3117     if (qt_show_painter_debug_output)
3118         printf("QPainter::shear(), sh=%f, sv=%f\n", sh, sv);
3119 #endif
3120     Q_D(QPainter);
3121     if (!d->engine) {
3122         qWarning("QPainter::shear: Painter not active");
3123         return;
3124     }
3125
3126     d->state->worldMatrix.shear(sh, sv);
3127     d->state->WxF = true;
3128     d->updateMatrix();
3129 }
3130
3131 /*!
3132     \fn void QPainter::rotate(qreal angle)
3133
3134     Rotates the coordinate system the given \a angle clockwise.
3135
3136     \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3137 */
3138
3139 void QPainter::rotate(qreal a)
3140 {
3141 #ifdef QT_DEBUG_DRAW
3142     if (qt_show_painter_debug_output)
3143         printf("QPainter::rotate(), angle=%f\n", a);
3144 #endif
3145     Q_D(QPainter);
3146     if (!d->engine) {
3147         qWarning("QPainter::rotate: Painter not active");
3148         return;
3149     }
3150
3151     d->state->worldMatrix.rotate(a);
3152     d->state->WxF = true;
3153     d->updateMatrix();
3154 }
3155
3156 /*!
3157     Translates the coordinate system by the given \a offset; i.e. the
3158     given \a offset is added to points.
3159
3160     \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate Transformations}
3161 */
3162 void QPainter::translate(const QPointF &offset)
3163 {
3164     qreal dx = offset.x();
3165     qreal dy = offset.y();
3166 #ifdef QT_DEBUG_DRAW
3167     if (qt_show_painter_debug_output)
3168         printf("QPainter::translate(), dx=%f, dy=%f\n", dx, dy);
3169 #endif
3170     Q_D(QPainter);
3171     if (!d->engine) {
3172         qWarning("QPainter::translate: Painter not active");
3173         return;
3174     }
3175
3176     d->state->worldMatrix.translate(dx, dy);
3177     d->state->WxF = true;
3178     d->updateMatrix();
3179 }
3180
3181 /*!
3182     \fn void QPainter::translate(const QPoint &offset)
3183     \overload
3184
3185     Translates the coordinate system by the given \a offset.
3186 */
3187
3188 /*!
3189     \fn void QPainter::translate(qreal dx, qreal dy)
3190     \overload
3191
3192     Translates the coordinate system by the vector (\a dx, \a dy).
3193 */
3194
3195 /*!
3196     \fn void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation operation)
3197
3198     Enables clipping, and sets the clip path for the painter to the
3199     given \a path, with the clip \a operation.
3200
3201     Note that the clip path is specified in logical (painter)
3202     coordinates.
3203
3204     \sa clipPath(), clipRegion(), {QPainter#Clipping}{Clipping}
3205
3206 */
3207 void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
3208 {
3209 #ifdef QT_DEBUG_DRAW
3210     if (qt_show_painter_debug_output) {
3211         QRectF b = path.boundingRect();
3212         printf("QPainter::setClipPath(), size=%d, op=%d, bounds=[%.2f,%.2f,%.2f,%.2f]\n",
3213                path.elementCount(), op, b.x(), b.y(), b.width(), b.height());
3214     }
3215 #endif
3216     Q_D(QPainter);
3217
3218     if (!d->engine) {
3219         qWarning("QPainter::setClipPath: Painter not active");
3220         return;
3221     }
3222
3223     if ((!d->state->clipEnabled && op != Qt::NoClip))
3224         op = Qt::ReplaceClip;
3225
3226     if (d->extended) {
3227         d->state->clipEnabled = true;
3228         d->extended->clip(path, op);
3229         if (op == Qt::NoClip || op == Qt::ReplaceClip)
3230             d->state->clipInfo.clear();
3231         d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3232         d->state->clipOperation = op;
3233         return;
3234     }
3235
3236     if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
3237         op = Qt::ReplaceClip;
3238
3239     d->state->clipPath = path;
3240     d->state->clipOperation = op;
3241     if (op == Qt::NoClip || op == Qt::ReplaceClip)
3242         d->state->clipInfo.clear();
3243     d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
3244     d->state->clipEnabled = true;
3245     d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
3246     d->updateState(d->state);
3247 }
3248
3249 /*!
3250     Draws the outline (strokes) the path \a path with the pen specified
3251     by \a pen
3252
3253     \sa fillPath(), {QPainter#Drawing}{Drawing}
3254 */
3255 void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
3256 {
3257     Q_D(QPainter);
3258
3259     if (!d->engine) {
3260         qWarning("QPainter::strokePath: Painter not active");
3261         return;
3262     }
3263
3264     if (path.isEmpty())
3265         return;
3266
3267     if (d->extended) {
3268         const QGradient *g = qpen_brush(pen).gradient();
3269         if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3270             d->extended->stroke(qtVectorPathForPath(path), pen);
3271             return;
3272         }
3273     }
3274
3275     QBrush oldBrush = d->state->brush;
3276     QPen oldPen = d->state->pen;
3277
3278     setPen(pen);
3279     setBrush(Qt::NoBrush);
3280
3281     drawPath(path);
3282
3283     // Reset old state
3284     setPen(oldPen);
3285     setBrush(oldBrush);
3286 }
3287
3288 /*!
3289     Fills the given \a path using the given \a brush. The outline is
3290     not drawn.
3291
3292     Alternatively, you can specify a QColor instead of a QBrush; the
3293     QBrush constructor (taking a QColor argument) will automatically
3294     create a solid pattern brush.
3295
3296     \sa drawPath()
3297 */
3298 void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
3299 {
3300     Q_D(QPainter);
3301
3302     if (!d->engine) {
3303         qWarning("QPainter::fillPath: Painter not active");
3304         return;
3305     }
3306
3307     if (path.isEmpty())
3308         return;
3309
3310     if (d->extended) {
3311         const QGradient *g = brush.gradient();
3312         if (!g || g->coordinateMode() == QGradient::LogicalMode) {
3313             d->extended->fill(qtVectorPathForPath(path), brush);
3314             return;
3315         }
3316     }
3317
3318     QBrush oldBrush = d->state->brush;
3319     QPen oldPen = d->state->pen;
3320
3321     setPen(Qt::NoPen);
3322     setBrush(brush);
3323
3324     drawPath(path);
3325
3326     // Reset old state
3327     setPen(oldPen);
3328     setBrush(oldBrush);
3329 }
3330
3331 /*!
3332     Draws the given painter \a path using the current pen for outline
3333     and the current brush for filling.
3334
3335     \table 100%
3336     \row
3337     \li \inlineimage qpainter-path.png
3338     \li
3339     \snippet code/src_gui_painting_qpainter.cpp 5
3340     \endtable
3341
3342     \sa {painting/painterpaths}{the Painter Paths
3343     example},{painting/deform}{the Vector Deformation example}
3344 */
3345 void QPainter::drawPath(const QPainterPath &path)
3346 {
3347 #ifdef QT_DEBUG_DRAW
3348     QRectF pathBounds = path.boundingRect();
3349     if (qt_show_painter_debug_output)
3350         printf("QPainter::drawPath(), size=%d, [%.2f,%.2f,%.2f,%.2f]\n",
3351                path.elementCount(),
3352                pathBounds.x(), pathBounds.y(), pathBounds.width(), pathBounds.height());
3353 #endif
3354
3355     Q_D(QPainter);
3356
3357     if (!d->engine) {
3358         qWarning("QPainter::drawPath: Painter not active");
3359         return;
3360     }
3361
3362     if (d->extended) {
3363         d->extended->drawPath(path);
3364         return;
3365     }
3366     d->updateState(d->state);
3367
3368     if (d->engine->hasFeature(QPaintEngine::PainterPaths) && d->state->emulationSpecifier == 0) {
3369         d->engine->drawPath(path);
3370     } else {
3371         d->draw_helper(path);
3372     }
3373 }
3374
3375 /*!
3376     \fn void QPainter::drawLine(const QLineF &line)
3377
3378     Draws a line defined by \a line.
3379
3380     \table 100%
3381     \row
3382     \li \inlineimage qpainter-line.png
3383     \li
3384     \snippet code/src_gui_painting_qpainter.cpp 6
3385     \endtable
3386
3387     \sa drawLines(), drawPolyline(), {Coordinate System}
3388 */
3389
3390 /*!
3391     \fn void QPainter::drawLine(const QLine &line)
3392     \overload
3393
3394     Draws a line defined by \a line.
3395 */
3396
3397 /*!
3398     \fn void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
3399     \overload
3400
3401     Draws a line from \a p1 to \a p2.
3402 */
3403
3404 /*!
3405     \fn void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
3406     \overload
3407
3408     Draws a line from \a p1 to \a p2.
3409 */
3410
3411 /*!
3412     \fn void QPainter::drawLine(int x1, int y1, int x2, int y2)
3413     \overload
3414
3415     Draws a line from (\a x1, \a y1) to (\a x2, \a y2) and sets the
3416     current pen position to (\a x2, \a y2).
3417 */
3418
3419 /*!
3420     \fn void QPainter::drawRect(const QRectF &rectangle)
3421
3422     Draws the current \a rectangle with the current pen and brush.
3423
3424     A filled rectangle has a size of \a{rectangle}.size(). A stroked
3425     rectangle has a size of \a{rectangle}.size() plus the pen width.
3426
3427     \table 100%
3428     \row
3429     \li \inlineimage qpainter-rectangle.png
3430     \li
3431     \snippet code/src_gui_painting_qpainter.cpp 7
3432     \endtable
3433
3434     \sa drawRects(), drawPolygon(), {Coordinate System}
3435 */
3436
3437 /*!
3438     \fn void QPainter::drawRect(const QRect &rectangle)
3439
3440     \overload
3441
3442     Draws the current \a rectangle with the current pen and brush.
3443 */
3444
3445 /*!
3446     \fn void QPainter::drawRect(int x, int y, int width, int height)
3447
3448     \overload
3449
3450     Draws a rectangle with upper left corner at (\a{x}, \a{y}) and
3451     with the given \a width and \a height.
3452 */
3453
3454 /*!
3455     \fn void QPainter::drawRects(const QRectF *rectangles, int rectCount)
3456
3457     Draws the first \a rectCount of the given \a rectangles using the
3458     current pen and brush.
3459
3460     \sa drawRect()
3461 */
3462 void QPainter::drawRects(const QRectF *rects, int rectCount)
3463 {
3464 #ifdef QT_DEBUG_DRAW
3465     if (qt_show_painter_debug_output)
3466         printf("QPainter::drawRects(), count=%d\n", rectCount);
3467 #endif
3468     Q_D(QPainter);
3469
3470     if (!d->engine) {
3471         qWarning("QPainter::drawRects: Painter not active");
3472         return;
3473     }
3474
3475     if (rectCount <= 0)
3476         return;
3477
3478     if (d->extended) {
3479         d->extended->drawRects(rects, rectCount);
3480         return;
3481     }
3482
3483     d->updateState(d->state);
3484
3485     if (!d->state->emulationSpecifier) {
3486         d->engine->drawRects(rects, rectCount);
3487         return;
3488     }
3489
3490     if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3491         && d->state->matrix.type() == QTransform::TxTranslate) {
3492         for (int i=0; i<rectCount; ++i) {
3493             QRectF r(rects[i].x() + d->state->matrix.dx(),
3494                      rects[i].y() + d->state->matrix.dy(),
3495                      rects[i].width(),
3496                      rects[i].height());
3497             d->engine->drawRects(&r, 1);
3498         }
3499     } else {
3500         if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3501             for (int i=0; i<rectCount; ++i) {
3502                 QPainterPath rectPath;
3503                 rectPath.addRect(rects[i]);
3504                 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3505             }
3506         } else {
3507             QPainterPath rectPath;
3508             for (int i=0; i<rectCount; ++i)
3509                 rectPath.addRect(rects[i]);
3510             d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3511         }
3512     }
3513 }
3514
3515 /*!
3516     \fn void QPainter::drawRects(const QRect *rectangles, int rectCount)
3517     \overload
3518
3519     Draws the first \a rectCount of the given \a rectangles using the
3520     current pen and brush.
3521 */
3522 void QPainter::drawRects(const QRect *rects, int rectCount)
3523 {
3524 #ifdef QT_DEBUG_DRAW
3525     if (qt_show_painter_debug_output)
3526         printf("QPainter::drawRects(), count=%d\n", rectCount);
3527 #endif
3528     Q_D(QPainter);
3529
3530     if (!d->engine) {
3531         qWarning("QPainter::drawRects: Painter not active");
3532         return;
3533     }
3534
3535     if (rectCount <= 0)
3536         return;
3537
3538     if (d->extended) {
3539         d->extended->drawRects(rects, rectCount);
3540         return;
3541     }
3542
3543     d->updateState(d->state);
3544
3545     if (!d->state->emulationSpecifier) {
3546         d->engine->drawRects(rects, rectCount);
3547         return;
3548     }
3549
3550     if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3551         && d->state->matrix.type() == QTransform::TxTranslate) {
3552         for (int i=0; i<rectCount; ++i) {
3553             QRectF r(rects[i].x() + d->state->matrix.dx(),
3554                      rects[i].y() + d->state->matrix.dy(),
3555                      rects[i].width(),
3556                      rects[i].height());
3557
3558             d->engine->drawRects(&r, 1);
3559         }
3560     } else {
3561         if (d->state->brushNeedsResolving() || d->state->penNeedsResolving()) {
3562             for (int i=0; i<rectCount; ++i) {
3563                 QPainterPath rectPath;
3564                 rectPath.addRect(rects[i]);
3565                 d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3566             }
3567         } else {
3568             QPainterPath rectPath;
3569             for (int i=0; i<rectCount; ++i)
3570                 rectPath.addRect(rects[i]);
3571
3572             d->draw_helper(rectPath, QPainterPrivate::StrokeAndFillDraw);
3573         }
3574     }
3575 }
3576
3577 /*!
3578     \fn void QPainter::drawRects(const QVector<QRectF> &rectangles)
3579     \overload
3580
3581     Draws the given \a rectangles using the current pen and brush.
3582 */
3583
3584 /*!
3585     \fn void QPainter::drawRects(const QVector<QRect> &rectangles)
3586
3587     \overload
3588
3589     Draws the given \a rectangles using the current pen and brush.
3590 */
3591
3592 /*!
3593   \fn void QPainter::drawPoint(const QPointF &position)
3594
3595     Draws a single point at the given \a position using the current
3596     pen's color.
3597
3598     \sa {Coordinate System}
3599 */
3600
3601 /*!
3602     \fn void QPainter::drawPoint(const QPoint &position)
3603     \overload
3604
3605     Draws a single point at the given \a position using the current
3606     pen's color.
3607 */
3608
3609 /*! \fn void QPainter::drawPoint(int x, int y)
3610
3611     \overload
3612
3613     Draws a single point at position (\a x, \a y).
3614 */
3615
3616 /*!
3617     Draws the first \a pointCount points in the array \a points using
3618     the current pen's color.
3619
3620     \sa {Coordinate System}
3621 */
3622 void QPainter::drawPoints(const QPointF *points, int pointCount)
3623 {
3624 #ifdef QT_DEBUG_DRAW
3625     if (qt_show_painter_debug_output)
3626         printf("QPainter::drawPoints(), count=%d\n", pointCount);
3627 #endif
3628     Q_D(QPainter);
3629
3630     if (!d->engine) {
3631         qWarning("QPainter::drawPoints: Painter not active");
3632         return;
3633     }
3634
3635     if (pointCount <= 0)
3636         return;
3637
3638     if (d->extended) {
3639         d->extended->drawPoints(points, pointCount);
3640         return;
3641     }
3642
3643     d->updateState(d->state);
3644
3645     if (!d->state->emulationSpecifier) {
3646         d->engine->drawPoints(points, pointCount);
3647         return;
3648     }
3649
3650     if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3651         && d->state->matrix.type() == QTransform::TxTranslate) {
3652         // ### use drawPoints function
3653         for (int i=0; i<pointCount; ++i) {
3654             QPointF pt(points[i].x() + d->state->matrix.dx(),
3655                        points[i].y() + d->state->matrix.dy());
3656             d->engine->drawPoints(&pt, 1);
3657         }
3658     } else {
3659         QPen pen = d->state->pen;
3660         bool flat_pen = pen.capStyle() == Qt::FlatCap;
3661         if (flat_pen) {
3662             save();
3663             pen.setCapStyle(Qt::SquareCap);
3664             setPen(pen);
3665         }
3666         QPainterPath path;
3667         for (int i=0; i<pointCount; ++i) {
3668             path.moveTo(points[i].x(), points[i].y());
3669             path.lineTo(points[i].x() + 0.0001, points[i].y());
3670         }
3671         d->draw_helper(path, QPainterPrivate::StrokeDraw);
3672         if (flat_pen)
3673             restore();
3674     }
3675 }
3676
3677 /*!
3678     \overload
3679
3680     Draws the first \a pointCount points in the array \a points using
3681     the current pen's color.
3682 */
3683
3684 void QPainter::drawPoints(const QPoint *points, int pointCount)
3685 {
3686 #ifdef QT_DEBUG_DRAW
3687     if (qt_show_painter_debug_output)
3688         printf("QPainter::drawPoints(), count=%d\n", pointCount);
3689 #endif
3690     Q_D(QPainter);
3691
3692     if (!d->engine) {
3693         qWarning("QPainter::drawPoints: Painter not active");
3694         return;
3695     }
3696
3697     if (pointCount <= 0)
3698         return;
3699
3700     if (d->extended) {
3701         d->extended->drawPoints(points, pointCount);
3702         return;
3703     }
3704
3705     d->updateState(d->state);
3706
3707     if (!d->state->emulationSpecifier) {
3708         d->engine->drawPoints(points, pointCount);
3709         return;
3710     }
3711
3712     if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
3713         && d->state->matrix.type() == QTransform::TxTranslate) {
3714         // ### use drawPoints function
3715         for (int i=0; i<pointCount; ++i) {
3716             QPointF pt(points[i].x() + d->state->matrix.dx(),
3717                        points[i].y() + d->state->matrix.dy());
3718             d->engine->drawPoints(&pt, 1);
3719         }
3720     } else {
3721         QPen pen = d->state->pen;
3722         bool flat_pen = (pen.capStyle() == Qt::FlatCap);
3723         if (flat_pen) {
3724             save();
3725             pen.setCapStyle(Qt::SquareCap);
3726             setPen(pen);
3727         }
3728         QPainterPath path;
3729         for (int i=0; i<pointCount; ++i) {
3730             path.moveTo(points[i].x(), points[i].y());
3731             path.lineTo(points[i].x() + 0.0001, points[i].y());
3732         }
3733         d->draw_helper(path, QPainterPrivate::StrokeDraw);
3734         if (flat_pen)
3735             restore();
3736     }
3737 }
3738
3739 /*!
3740     \fn void QPainter::drawPoints(const QPolygonF &points)
3741
3742     \overload
3743
3744     Draws the points in the vector  \a points.
3745 */
3746
3747 /*!
3748     \fn void QPainter::drawPoints(const QPolygon &points)
3749
3750     \overload
3751
3752     Draws the points in the vector  \a points.
3753 */
3754
3755 /*!
3756     Sets the background mode of the painter to the given \a mode
3757
3758     Qt::TransparentMode (the default) draws stippled lines and text
3759     without setting the background pixels.  Qt::OpaqueMode fills these
3760     space with the current background color.
3761
3762     Note that in order to draw a bitmap or pixmap transparently, you
3763     must use QPixmap::setMask().
3764
3765     \sa backgroundMode(), setBackground(),
3766     {QPainter#Settings}{Settings}
3767 */
3768
3769 void QPainter::setBackgroundMode(Qt::BGMode mode)
3770 {
3771 #ifdef QT_DEBUG_DRAW
3772     if (qt_show_painter_debug_output)
3773         printf("QPainter::setBackgroundMode(), mode=%d\n", mode);
3774 #endif
3775
3776     Q_D(QPainter);
3777     if (!d->engine) {
3778         qWarning("QPainter::setBackgroundMode: Painter not active");
3779         return;
3780     }
3781     if (d->state->bgMode == mode)
3782         return;
3783
3784     d->state->bgMode = mode;
3785     if (d->extended) {
3786         d->checkEmulation();
3787     } else {
3788         d->state->dirtyFlags |= QPaintEngine::DirtyBackgroundMode;
3789     }
3790 }
3791
3792 /*!
3793     Returns the current background mode.
3794
3795     \sa setBackgroundMode(), {QPainter#Settings}{Settings}
3796 */
3797 Qt::BGMode QPainter::backgroundMode() const
3798 {
3799     Q_D(const QPainter);
3800     if (!d->engine) {
3801         qWarning("QPainter::backgroundMode: Painter not active");
3802         return Qt::TransparentMode;
3803     }
3804     return d->state->bgMode;
3805 }
3806
3807
3808 /*!
3809     \overload
3810
3811     Sets the painter's pen to have style Qt::SolidLine, width 0 and the
3812     specified \a color.
3813 */
3814
3815 void QPainter::setPen(const QColor &color)
3816 {
3817 #ifdef QT_DEBUG_DRAW
3818     if (qt_show_painter_debug_output)
3819         printf("QPainter::setPen(), color=%04x\n", color.rgb());
3820 #endif
3821     Q_D(QPainter);
3822     if (!d->engine) {
3823         qWarning("QPainter::setPen: Painter not active");
3824         return;
3825     }
3826
3827     if (d->state->pen.style() == Qt::SolidLine
3828         && d->state->pen.widthF() == 0
3829         && d->state->pen.isSolid()
3830         && d->state->pen.color() == color)
3831         return;
3832
3833     QPen pen(color.isValid() ? color : QColor(Qt::black), 0, Qt::SolidLine);
3834
3835     d->state->pen = pen;
3836     if (d->extended)
3837         d->extended->penChanged();
3838     else
3839         d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3840 }
3841
3842 /*!
3843     Sets the painter's pen to be the given \a pen.
3844
3845     The \a pen defines how to draw lines and outlines, and it also
3846     defines the text color.
3847
3848     \sa pen(), {QPainter#Settings}{Settings}
3849 */
3850
3851 void QPainter::setPen(const QPen &pen)
3852 {
3853
3854 #ifdef QT_DEBUG_DRAW
3855     if (qt_show_painter_debug_output)
3856         printf("QPainter::setPen(), color=%04x, (brushStyle=%d) style=%d, cap=%d, join=%d\n",
3857            pen.color().rgb(), pen.brush().style(), pen.style(), pen.capStyle(), pen.joinStyle());
3858 #endif
3859     Q_D(QPainter);
3860     if (!d->engine) {
3861         qWarning("QPainter::setPen: Painter not active");
3862         return;
3863     }
3864
3865     if (d->state->pen == pen)
3866         return;
3867
3868     d->state->pen = pen;
3869
3870     if (d->extended) {
3871         d->checkEmulation();
3872         d->extended->penChanged();
3873         return;
3874     }
3875
3876     d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3877 }
3878
3879 /*!
3880     \overload
3881
3882     Sets the painter's pen to have the given \a style, width 0 and
3883     black color.
3884 */
3885
3886 void QPainter::setPen(Qt::PenStyle style)
3887 {
3888     Q_D(QPainter);
3889     if (!d->engine) {
3890         qWarning("QPainter::setPen: Painter not active");
3891         return;
3892     }
3893
3894     if (d->state->pen.style() == style
3895         && (style == Qt::NoPen || (d->state->pen.widthF() == 0
3896                                    && d->state->pen.isSolid()
3897                                    && d->state->pen.color() == QColor(Qt::black))))
3898         return;
3899
3900     // QPen(Qt::NoPen) is to avoid creating QPenData, including its brush (from the color)
3901     // Note that this works well as long as QPen(Qt::NoPen) returns a black, zero-width pen
3902     d->state->pen = (style == Qt::NoPen) ? QPen(Qt::NoPen) : QPen(Qt::black, 0, style);
3903
3904     if (d->extended)
3905         d->extended->penChanged();
3906     else
3907         d->state->dirtyFlags |= QPaintEngine::DirtyPen;
3908
3909 }
3910
3911 /*!
3912     Returns the painter's current pen.
3913
3914     \sa setPen(), {QPainter#Settings}{Settings}
3915 */
3916
3917 const QPen &QPainter::pen() const
3918 {
3919     Q_D(const QPainter);
3920     if (!d->engine) {
3921         qWarning("QPainter::pen: Painter not active");
3922         return d->fakeState()->pen;
3923     }
3924     return d->state->pen;
3925 }
3926
3927
3928 /*!
3929     Sets the painter's brush to the given \a brush.
3930
3931     The painter's brush defines how shapes are filled.
3932
3933     \sa brush(), {QPainter#Settings}{Settings}
3934 */
3935
3936 void QPainter::setBrush(const QBrush &brush)
3937 {
3938 #ifdef QT_DEBUG_DRAW
3939     if (qt_show_painter_debug_output)
3940         printf("QPainter::setBrush(), color=%04x, style=%d\n", brush.color().rgb(), brush.style());
3941 #endif
3942     Q_D(QPainter);
3943     if (!d->engine) {
3944         qWarning("QPainter::setBrush: Painter not active");
3945         return;
3946     }
3947
3948     if (d->state->brush.d == brush.d)
3949         return;
3950
3951     if (d->extended) {
3952         d->state->brush = brush;
3953         d->checkEmulation();
3954         d->extended->brushChanged();
3955         return;
3956     }
3957
3958     d->state->brush = brush;
3959     d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
3960 }
3961
3962
3963 /*!
3964     \overload
3965
3966     Sets the painter's brush to black color and the specified \a
3967     style.
3968 */
3969
3970 void QPainter::setBrush(Qt::BrushStyle style)
3971 {
3972     Q_D(QPainter);
3973     if (!d->engine) {
3974         qWarning("QPainter::setBrush: Painter not active");
3975         return;
3976     }
3977     if (d->state->brush.style() == style &&
3978         (style == Qt::NoBrush
3979          || (style == Qt::SolidPattern && d->state->brush.color() == QColor(0, 0, 0))))
3980         return;
3981     d->state->brush = QBrush(Qt::black, style);
3982     if (d->extended)
3983         d->extended->brushChanged();
3984     else
3985         d->state->dirtyFlags |= QPaintEngine::DirtyBrush;
3986 }
3987
3988 /*!
3989     Returns the painter's current brush.
3990
3991     \sa QPainter::setBrush(), {QPainter#Settings}{Settings}
3992 */
3993
3994 const QBrush &QPainter::brush() const
3995 {
3996     Q_D(const QPainter);
3997     if (!d->engine) {
3998         qWarning("QPainter::brush: Painter not active");
3999         return d->fakeState()->brush;
4000     }
4001     return d->state->brush;
4002 }
4003
4004 /*!
4005     \fn void QPainter::setBackground(const QBrush &brush)
4006
4007     Sets the background brush of the painter to the given \a brush.
4008
4009     The background brush is the brush that is filled in when drawing
4010     opaque text, stippled lines and bitmaps. The background brush has
4011     no effect in transparent background mode (which is the default).
4012
4013     \sa background(), setBackgroundMode(),
4014     {QPainter#Settings}{Settings}
4015 */
4016
4017 void QPainter::setBackground(const QBrush &bg)
4018 {
4019 #ifdef QT_DEBUG_DRAW
4020     if (qt_show_painter_debug_output)
4021         printf("QPainter::setBackground(), color=%04x, style=%d\n", bg.color().rgb(), bg.style());
4022 #endif
4023
4024     Q_D(QPainter);
4025     if (!d->engine) {
4026         qWarning("QPainter::setBackground: Painter not active");
4027         return;
4028     }
4029     d->state->bgBrush = bg;
4030     if (!d->extended)
4031         d->state->dirtyFlags |= QPaintEngine::DirtyBackground;
4032 }
4033
4034 /*!
4035     Sets the painter's font to the given \a font.
4036
4037     This font is used by subsequent drawText() functions. The text
4038     color is the same as the pen color.
4039
4040     If you set a font that isn't available, Qt finds a close match.
4041     font() will return what you set using setFont() and fontInfo() returns the
4042     font actually being used (which may be the same).
4043
4044     \sa font(), drawText(), {QPainter#Settings}{Settings}
4045 */
4046
4047 void QPainter::setFont(const QFont &font)
4048 {
4049     Q_D(QPainter);
4050
4051 #ifdef QT_DEBUG_DRAW
4052     if (qt_show_painter_debug_output)
4053         printf("QPainter::setFont(), family=%s, pointSize=%d\n", font.family().toLatin1().constData(), font.pointSize());
4054 #endif
4055
4056     if (!d->engine) {
4057         qWarning("QPainter::setFont: Painter not active");
4058         return;
4059     }
4060
4061     d->state->font = QFont(font.resolve(d->state->deviceFont), device());
4062     if (!d->extended)
4063         d->state->dirtyFlags |= QPaintEngine::DirtyFont;
4064 }
4065
4066 /*!
4067     Returns the currently set font used for drawing text.
4068
4069     \sa setFont(), drawText(), {QPainter#Settings}{Settings}
4070 */
4071 const QFont &QPainter::font() const
4072 {
4073     Q_D(const QPainter);
4074     if (!d->engine) {
4075         qWarning("QPainter::font: Painter not active");
4076         return d->fakeState()->font;
4077     }
4078     return d->state->font;
4079 }
4080
4081 /*!
4082     \since 4.4
4083
4084     Draws the given rectangle \a rect with rounded corners.
4085
4086     The \a xRadius and \a yRadius arguments specify the radii
4087     of the ellipses defining the corners of the rounded rectangle.
4088     When \a mode is Qt::RelativeSize, \a xRadius and
4089     \a yRadius are specified in percentage of half the rectangle's
4090     width and height respectively, and should be in the range
4091     0.0 to 100.0.
4092
4093     A filled rectangle has a size of rect.size(). A stroked rectangle
4094     has a size of rect.size() plus the pen width.
4095
4096     \table 100%
4097     \row
4098     \li \inlineimage qpainter-roundrect.png
4099     \li
4100     \snippet code/src_gui_painting_qpainter.cpp 8
4101     \endtable
4102
4103     \sa drawRect(), QPen
4104 */
4105 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
4106 {
4107 #ifdef QT_DEBUG_DRAW
4108     if (qt_show_painter_debug_output)
4109         printf("QPainter::drawRoundedRect(), [%.2f,%.2f,%.2f,%.2f]\n", rect.x(), rect.y(), rect.width(), rect.height());
4110 #endif
4111     Q_D(QPainter);
4112
4113     if (!d->engine)
4114         return;
4115
4116     if (xRadius <= 0 || yRadius <= 0) {             // draw normal rectangle
4117         drawRect(rect);
4118         return;
4119     }
4120
4121     if (d->extended) {
4122         d->extended->drawRoundedRect(rect, xRadius, yRadius, mode);
4123         return;
4124     }
4125
4126     QPainterPath path;
4127     path.addRoundedRect(rect, xRadius, yRadius, mode);
4128     drawPath(path);
4129 }
4130
4131 /*!
4132     \fn void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius,
4133                                        Qt::SizeMode mode = Qt::AbsoluteSize);
4134     \since 4.4
4135     \overload
4136
4137     Draws the given rectangle \a rect with rounded corners.
4138 */
4139
4140 /*!
4141     \fn void QPainter::drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius,
4142                                        Qt::SizeMode mode = Qt::AbsoluteSize);
4143     \since 4.4
4144     \overload
4145
4146     Draws the given rectangle \a x, \a y, \a w, \a h with rounded corners.
4147 */
4148
4149 /*!
4150     \obsolete
4151
4152     Draws a rectangle \a r with rounded corners.
4153
4154     The \a xRnd and \a yRnd arguments specify how rounded the corners
4155     should be. 0 is angled corners, 99 is maximum roundedness.
4156
4157     A filled rectangle has a size of r.size(). A stroked rectangle
4158     has a size of r.size() plus the pen width.
4159
4160     \sa drawRoundedRect()
4161 */
4162 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd)
4163 {
4164     drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize);
4165 }
4166
4167
4168 /*!
4169     \fn void QPainter::drawRoundRect(const QRect &r, int xRnd = 25, int yRnd = 25)
4170
4171     \overload
4172     \obsolete
4173
4174     Draws the rectangle \a r with rounded corners.
4175 */
4176
4177 /*!
4178     \obsolete
4179
4180     \fn QPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd)
4181
4182     \overload
4183
4184     Draws the rectangle \a x, \a y, \a w, \a h with rounded corners.
4185 */
4186
4187 /*!
4188     \fn void QPainter::drawEllipse(const QRectF &rectangle)
4189
4190     Draws the ellipse defined by the given \a rectangle.
4191
4192     A filled ellipse has a size of \a{rectangle}.\l
4193     {QRect::size()}{size()}. A stroked ellipse has a size of
4194     \a{rectangle}.\l {QRect::size()}{size()} plus the pen width.
4195
4196     \table 100%
4197     \row
4198     \li \inlineimage qpainter-ellipse.png
4199     \li
4200     \snippet code/src_gui_painting_qpainter.cpp 9
4201     \endtable
4202
4203     \sa drawPie(), {Coordinate System}
4204 */
4205 void QPainter::drawEllipse(const QRectF &r)
4206 {
4207 #ifdef QT_DEBUG_DRAW
4208     if (qt_show_painter_debug_output)
4209         printf("QPainter::drawEllipse(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height());
4210 #endif
4211     Q_D(QPainter);
4212
4213     if (!d->engine)
4214         return;
4215
4216     QRectF rect(r.normalized());
4217
4218     if (d->extended) {
4219         d->extended->drawEllipse(rect);
4220         return;
4221     }
4222
4223     d->updateState(d->state);
4224     if (d->state->emulationSpecifier) {
4225         if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4226             && d->state->matrix.type() == QTransform::TxTranslate) {
4227             rect.translate(QPointF(d->state->matrix.dx(), d->state->matrix.dy()));
4228         } else {
4229             QPainterPath path;
4230             path.addEllipse(rect);
4231             d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4232             return;
4233         }
4234     }
4235
4236     d->engine->drawEllipse(rect);
4237 }
4238
4239 /*!
4240     \fn QPainter::drawEllipse(const QRect &rectangle)
4241
4242     \overload
4243
4244     Draws the ellipse defined by the given \a rectangle.
4245 */
4246 void QPainter::drawEllipse(const QRect &r)
4247 {
4248 #ifdef QT_DEBUG_DRAW
4249     if (qt_show_painter_debug_output)
4250         printf("QPainter::drawEllipse(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
4251 #endif
4252     Q_D(QPainter);
4253
4254     if (!d->engine)
4255         return;
4256
4257     QRect rect(r.normalized());
4258
4259     if (d->extended) {
4260         d->extended->drawEllipse(rect);
4261         return;
4262     }
4263
4264     d->updateState(d->state);
4265
4266     if (d->state->emulationSpecifier) {
4267         if (d->state->emulationSpecifier == QPaintEngine::PrimitiveTransform
4268             && d->state->matrix.type() == QTransform::TxTranslate) {
4269             rect.translate(QPoint(qRound(d->state->matrix.dx()), qRound(d->state->matrix.dy())));
4270         } else {
4271             QPainterPath path;
4272             path.addEllipse(rect);
4273             d->draw_helper(path, QPainterPrivate::StrokeAndFillDraw);
4274             return;
4275         }
4276     }
4277
4278     d->engine->drawEllipse(rect);
4279 }
4280
4281 /*!
4282     \fn QPainter::drawEllipse(int x, int y, int width, int height)
4283
4284     \overload
4285
4286     Draws the ellipse defined by the rectangle beginning at (\a{x},
4287     \a{y}) with the given \a width and \a height.
4288 */
4289
4290 /*!
4291     \since 4.4
4292
4293     \fn QPainter::drawEllipse(const QPointF &center, qreal rx, qreal ry)
4294
4295     \overload
4296
4297     Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4298 */
4299
4300 /*!
4301     \since 4.4
4302
4303     \fn QPainter::drawEllipse(const QPoint &center, int rx, int ry)
4304
4305     \overload
4306
4307     Draws the ellipse positioned at \a{center} with radii \a{rx} and \a{ry}.
4308 */
4309
4310 /*!
4311     \fn void QPainter::drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
4312
4313     Draws the arc defined by the given \a rectangle, \a startAngle and
4314     \a spanAngle.
4315
4316     The \a startAngle and \a spanAngle must be specified in 1/16th of
4317     a degree, i.e. a full circle equals 5760 (16 * 360). Positive
4318     values for the angles mean counter-clockwise while negative values
4319     mean the clockwise direction. Zero degrees is at the 3 o'clock
4320     position.
4321
4322     \table 100%
4323     \row
4324     \li \inlineimage qpainter-arc.png
4325     \li
4326     \snippet code/src_gui_painting_qpainter.cpp 10
4327     \endtable
4328
4329     \sa drawPie(), drawChord(), {Coordinate System}
4330 */
4331
4332 void QPainter::drawArc(const QRectF &r, int a, int alen)
4333 {
4334 #ifdef QT_DEBUG_DRAW
4335     if (qt_show_painter_debug_output)
4336         printf("QPainter::drawArc(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4337            r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4338 #endif
4339     Q_D(QPainter);
4340
4341     if (!d->engine)
4342         return;
4343
4344     QRectF rect = r.normalized();
4345
4346     QPainterPath path;
4347     path.arcMoveTo(rect, a/16.0);
4348     path.arcTo(rect, a/16.0, alen/16.0);
4349     strokePath(path, d->state->pen);
4350 }
4351
4352 /*! \fn void QPainter::drawArc(const QRect &rectangle, int startAngle,
4353                                int spanAngle)
4354
4355     \overload
4356
4357     Draws the arc defined by the given \a rectangle, \a startAngle and
4358     \a spanAngle.
4359 */
4360
4361 /*!
4362     \fn void QPainter::drawArc(int x, int y, int width, int height,
4363                                int startAngle, int spanAngle)
4364
4365     \overload
4366
4367     Draws the arc defined by the rectangle beginning at (\a x, \a y)
4368     with the specified \a width and \a height, and the given \a
4369     startAngle and \a spanAngle.
4370 */
4371
4372 /*!
4373     \fn void QPainter::drawPie(const QRectF &rectangle, int startAngle, int spanAngle)
4374
4375     Draws a pie defined by the given \a rectangle, \a startAngle and
4376     and \a spanAngle.
4377
4378     The pie is filled with the current brush().
4379
4380     The startAngle and spanAngle must be specified in 1/16th of a
4381     degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4382     for the angles mean counter-clockwise while negative values mean
4383     the clockwise direction. Zero degrees is at the 3 o'clock
4384     position.
4385
4386     \table 100%
4387     \row
4388     \li \inlineimage qpainter-pie.png
4389     \li
4390     \snippet code/src_gui_painting_qpainter.cpp 11
4391     \endtable
4392
4393     \sa drawEllipse(), drawChord(), {Coordinate System}
4394 */
4395 void QPainter::drawPie(const QRectF &r, int a, int alen)
4396 {
4397 #ifdef QT_DEBUG_DRAW
4398     if (qt_show_painter_debug_output)
4399         printf("QPainter::drawPie(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4400            r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4401 #endif
4402     Q_D(QPainter);
4403
4404     if (!d->engine)
4405         return;
4406
4407     if (a > (360*16)) {
4408         a = a % (360*16);
4409     } else if (a < 0) {
4410         a = a % (360*16);
4411         if (a < 0) a += (360*16);
4412     }
4413
4414     QRectF rect = r.normalized();
4415
4416     QPainterPath path;
4417     path.moveTo(rect.center());
4418     path.arcTo(rect.x(), rect.y(), rect.width(), rect.height(), a/16.0, alen/16.0);
4419     path.closeSubpath();
4420     drawPath(path);
4421
4422 }
4423
4424 /*!
4425     \fn void QPainter::drawPie(const QRect &rectangle, int startAngle, int spanAngle)
4426     \overload
4427
4428     Draws a pie defined by the given \a rectangle, \a startAngle and
4429     and \a spanAngle.
4430 */
4431
4432 /*!
4433     \fn void QPainter::drawPie(int x, int y, int width, int height, int
4434     startAngle, int spanAngle)
4435
4436     \overload
4437
4438     Draws the pie defined by the rectangle beginning at (\a x, \a y) with
4439     the specified \a width and \a height, and the given \a startAngle and
4440     \a spanAngle.
4441 */
4442
4443 /*!
4444     \fn void QPainter::drawChord(const QRectF &rectangle, int startAngle, int spanAngle)
4445
4446     Draws the chord defined by the given \a rectangle, \a startAngle and
4447     \a spanAngle.  The chord is filled with the current brush().
4448
4449     The startAngle and spanAngle must be specified in 1/16th of a
4450     degree, i.e. a full circle equals 5760 (16 * 360). Positive values
4451     for the angles mean counter-clockwise while negative values mean
4452     the clockwise direction. Zero degrees is at the 3 o'clock
4453     position.
4454
4455     \table 100%
4456     \row
4457     \li \inlineimage qpainter-chord.png
4458     \li
4459     \snippet code/src_gui_painting_qpainter.cpp 12
4460     \endtable
4461
4462     \sa drawArc(), drawPie(), {Coordinate System}
4463 */
4464 void QPainter::drawChord(const QRectF &r, int a, int alen)
4465 {
4466 #ifdef QT_DEBUG_DRAW
4467     if (qt_show_painter_debug_output)
4468         printf("QPainter::drawChord(), [%.2f,%.2f,%.2f,%.2f], angle=%d, sweep=%d\n",
4469            r.x(), r.y(), r.width(), r.height(), a/16, alen/16);
4470 #endif
4471     Q_D(QPainter);
4472
4473     if (!d->engine)
4474         return;
4475
4476     QRectF rect = r.normalized();
4477
4478     QPainterPath path;
4479     path.arcMoveTo(rect, a/16.0);
4480     path.arcTo(rect, a/16.0, alen/16.0);
4481     path.closeSubpath();
4482     drawPath(path);
4483 }
4484 /*!
4485     \fn void QPainter::drawChord(const QRect &rectangle, int startAngle, int spanAngle)
4486
4487     \overload
4488
4489     Draws the chord defined by the given \a rectangle, \a startAngle and
4490     \a spanAngle.
4491 */
4492
4493 /*!
4494     \fn void QPainter::drawChord(int x, int y, int width, int height, int
4495     startAngle, int spanAngle)
4496
4497     \overload
4498
4499    Draws the chord defined by the rectangle beginning at (\a x, \a y)
4500    with the specified \a width and \a height, and the given \a
4501    startAngle and \a spanAngle.
4502 */
4503
4504
4505 /*!
4506     Draws the first \a lineCount lines in the array \a lines
4507     using the current pen.
4508
4509     \sa drawLine(), drawPolyline()
4510 */
4511 void QPainter::drawLines(const QLineF *lines, int lineCount)
4512 {
4513 #ifdef QT_DEBUG_DRAW
4514     if (qt_show_painter_debug_output)
4515         printf("QPainter::drawLines(), line count=%d\n", lineCount);
4516 #endif
4517
4518     Q_D(QPainter);
4519
4520     if (!d->engine || lineCount < 1)
4521         return;
4522
4523     if (d->extended) {
4524         d->extended->drawLines(lines, lineCount);
4525         return;
4526     }
4527
4528     d->updateState(d->state);
4529
4530     uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4531
4532     if (lineEmulation) {
4533         if (lineEmulation == QPaintEngine::PrimitiveTransform
4534             && d->state->matrix.type() == QTransform::TxTranslate) {
4535             for (int i = 0; i < lineCount; ++i) {
4536                 QLineF line = lines[i];
4537                 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4538                 d->engine->drawLines(&line, 1);
4539             }
4540         } else {
4541             QPainterPath linePath;
4542             for (int i = 0; i < lineCount; ++i) {
4543                 linePath.moveTo(lines[i].p1());
4544                 linePath.lineTo(lines[i].p2());
4545             }
4546             d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4547         }
4548         return;
4549     }
4550     d->engine->drawLines(lines, lineCount);
4551 }
4552
4553 /*!
4554     \fn void QPainter::drawLines(const QLine *lines, int lineCount)
4555     \overload
4556
4557     Draws the first \a lineCount lines in the array \a lines
4558     using the current pen.
4559 */
4560 void QPainter::drawLines(const QLine *lines, int lineCount)
4561 {
4562 #ifdef QT_DEBUG_DRAW
4563     if (qt_show_painter_debug_output)
4564         printf("QPainter::drawLine(), line count=%d\n", lineCount);
4565 #endif
4566
4567     Q_D(QPainter);
4568
4569     if (!d->engine || lineCount < 1)
4570         return;
4571
4572     if (d->extended) {
4573         d->extended->drawLines(lines, lineCount);
4574         return;
4575     }
4576
4577     d->updateState(d->state);
4578
4579     uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4580
4581     if (lineEmulation) {
4582         if (lineEmulation == QPaintEngine::PrimitiveTransform
4583             && d->state->matrix.type() == QTransform::TxTranslate) {
4584             for (int i = 0; i < lineCount; ++i) {
4585                 QLineF line = lines[i];
4586                 line.translate(d->state->matrix.dx(), d->state->matrix.dy());
4587                 d->engine->drawLines(&line, 1);
4588             }
4589         } else {
4590             QPainterPath linePath;
4591             for (int i = 0; i < lineCount; ++i) {
4592                 linePath.moveTo(lines[i].p1());
4593                 linePath.lineTo(lines[i].p2());
4594             }
4595             d->draw_helper(linePath, QPainterPrivate::StrokeDraw);
4596         }
4597         return;
4598     }
4599     d->engine->drawLines(lines, lineCount);
4600 }
4601
4602 /*!
4603     \overload
4604
4605     Draws the first \a lineCount lines in the array \a pointPairs
4606     using the current pen.  The lines are specified as pairs of points
4607     so the number of entries in \a pointPairs must be at least \a
4608     lineCount * 2.
4609 */
4610 void QPainter::drawLines(const QPointF *pointPairs, int lineCount)
4611 {
4612     Q_ASSERT(sizeof(QLineF) == 2*sizeof(QPointF));
4613
4614     drawLines((QLineF*)pointPairs, lineCount);
4615 }
4616
4617 /*!
4618     \overload
4619
4620     Draws the first \a lineCount lines in the array \a pointPairs
4621     using the current pen.
4622 */
4623 void QPainter::drawLines(const QPoint *pointPairs, int lineCount)
4624 {
4625     Q_ASSERT(sizeof(QLine) == 2*sizeof(QPoint));
4626
4627     drawLines((QLine*)pointPairs, lineCount);
4628 }
4629
4630
4631 /*!
4632     \fn void QPainter::drawLines(const QVector<QPointF> &pointPairs)
4633     \overload
4634
4635     Draws a line for each pair of points in the vector \a pointPairs
4636     using the current pen. If there is an odd number of points in the
4637     array, the last point will be ignored.
4638 */
4639
4640 /*!
4641     \fn void QPainter::drawLines(const QVector<QPoint> &pointPairs)
4642     \overload
4643
4644     Draws a line for each pair of points in the vector \a pointPairs
4645     using the current pen.
4646 */
4647
4648 /*!
4649     \fn void QPainter::drawLines(const QVector<QLineF> &lines)
4650     \overload
4651
4652     Draws the set of lines defined by the list \a lines using the
4653     current pen and brush.
4654 */
4655
4656 /*!
4657     \fn void QPainter::drawLines(const QVector<QLine> &lines)
4658     \overload
4659
4660     Draws the set of lines defined by the list \a lines using the
4661     current pen and brush.
4662 */
4663
4664 /*!
4665     Draws the polyline defined by the first \a pointCount points in \a
4666     points using the current pen.
4667
4668     Note that unlike the drawPolygon() function the last point is \e
4669     not connected to the first, neither is the polyline filled.
4670
4671     \table 100%
4672     \row
4673     \li
4674     \snippet code/src_gui_painting_qpainter.cpp 13
4675     \endtable
4676
4677     \sa drawLines(), drawPolygon(), {Coordinate System}
4678 */
4679 void QPainter::drawPolyline(const QPointF *points, int pointCount)
4680 {
4681 #ifdef QT_DEBUG_DRAW
4682     if (qt_show_painter_debug_output)
4683         printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4684 #endif
4685     Q_D(QPainter);
4686
4687     if (!d->engine || pointCount < 2)
4688         return;
4689
4690     if (d->extended) {
4691         d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4692         return;
4693     }
4694
4695     d->updateState(d->state);
4696
4697     uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4698
4699     if (lineEmulation) {
4700         // ###
4701 //         if (lineEmulation == QPaintEngine::PrimitiveTransform
4702 //             && d->state->matrix.type() == QTransform::TxTranslate) {
4703 //         } else {
4704         QPainterPath polylinePath(points[0]);
4705         for (int i=1; i<pointCount; ++i)
4706             polylinePath.lineTo(points[i]);
4707         d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4708 //         }
4709     } else {
4710         d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4711     }
4712 }
4713
4714 /*!
4715     \overload
4716
4717     Draws the polyline defined by the first \a pointCount points in \a
4718     points using the current pen.
4719  */
4720 void QPainter::drawPolyline(const QPoint *points, int pointCount)
4721 {
4722 #ifdef QT_DEBUG_DRAW
4723     if (qt_show_painter_debug_output)
4724         printf("QPainter::drawPolyline(), count=%d\n", pointCount);
4725 #endif
4726     Q_D(QPainter);
4727
4728     if (!d->engine || pointCount < 2)
4729         return;
4730
4731     if (d->extended) {
4732         d->extended->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4733         return;
4734     }
4735
4736     d->updateState(d->state);
4737
4738     uint lineEmulation = line_emulation(d->state->emulationSpecifier);
4739
4740     if (lineEmulation) {
4741         // ###
4742 //         if (lineEmulation == QPaintEngine::PrimitiveTransform
4743 //             && d->state->matrix.type() == QTransform::TxTranslate) {
4744 //         } else {
4745         QPainterPath polylinePath(points[0]);
4746         for (int i=1; i<pointCount; ++i)
4747             polylinePath.lineTo(points[i]);
4748         d->draw_helper(polylinePath, QPainterPrivate::StrokeDraw);
4749 //         }
4750     } else {
4751         d->engine->drawPolygon(points, pointCount, QPaintEngine::PolylineMode);
4752     }
4753 }
4754
4755 /*!
4756     \fn void QPainter::drawPolyline(const QPolygonF &points)
4757
4758     \overload
4759
4760     Draws the polyline defined by the given \a points using the
4761     current pen.
4762 */
4763
4764 /*!
4765     \fn void QPainter::drawPolyline(const QPolygon &points)
4766
4767     \overload
4768
4769     Draws the polyline defined by the given \a points using the
4770     current pen.
4771 */
4772
4773 /*!
4774     Draws the polygon defined by the first \a pointCount points in the
4775     array \a points using the current pen and brush.
4776
4777     \table 100%
4778     \row
4779     \li \inlineimage qpainter-polygon.png
4780     \li
4781     \snippet code/src_gui_painting_qpainter.cpp 14
4782     \endtable
4783
4784     The first point is implicitly connected to the last point, and the
4785     polygon is filled with the current brush().
4786
4787     If \a fillRule is Qt::WindingFill, the polygon is filled using the
4788     winding fill algorithm.  If \a fillRule is Qt::OddEvenFill, the
4789     polygon is filled using the odd-even fill algorithm. See
4790     \l{Qt::FillRule} for a more detailed description of these fill
4791     rules.
4792
4793     \sa drawConvexPolygon(), drawPolyline(), {Coordinate System}
4794 */
4795 void QPainter::drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
4796 {
4797 #ifdef QT_DEBUG_DRAW
4798     if (qt_show_painter_debug_output)
4799         printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4800 #endif
4801
4802     Q_D(QPainter);
4803
4804     if (!d->engine || pointCount < 2)
4805         return;
4806
4807     if (d->extended) {
4808         d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4809         return;
4810     }
4811
4812     d->updateState(d->state);
4813
4814     uint emulationSpecifier = d->state->emulationSpecifier;
4815
4816     if (emulationSpecifier) {
4817         QPainterPath polygonPath(points[0]);
4818         for (int i=1; i<pointCount; ++i)
4819             polygonPath.lineTo(points[i]);
4820         polygonPath.closeSubpath();
4821         polygonPath.setFillRule(fillRule);
4822         d->draw_helper(polygonPath);
4823         return;
4824     }
4825
4826     d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4827 }
4828
4829 /*! \overload
4830
4831     Draws the polygon defined by the first \a pointCount points in the
4832     array \a points.
4833 */
4834 void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule)
4835 {
4836 #ifdef QT_DEBUG_DRAW
4837     if (qt_show_painter_debug_output)
4838         printf("QPainter::drawPolygon(), count=%d\n", pointCount);
4839 #endif
4840
4841     Q_D(QPainter);
4842
4843     if (!d->engine || pointCount < 2)
4844         return;
4845
4846     if (d->extended) {
4847         d->extended->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4848         return;
4849     }
4850
4851     d->updateState(d->state);
4852
4853     uint emulationSpecifier = d->state->emulationSpecifier;
4854
4855     if (emulationSpecifier) {
4856         QPainterPath polygonPath(points[0]);
4857         for (int i=1; i<pointCount; ++i)
4858             polygonPath.lineTo(points[i]);
4859         polygonPath.closeSubpath();
4860         polygonPath.setFillRule(fillRule);
4861         d->draw_helper(polygonPath);
4862         return;
4863     }
4864
4865     d->engine->drawPolygon(points, pointCount, QPaintEngine::PolygonDrawMode(fillRule));
4866 }
4867
4868 /*! \fn void QPainter::drawPolygon(const QPolygonF &points, Qt::FillRule fillRule)
4869
4870     \overload
4871
4872     Draws the polygon defined by the given \a points using the fill
4873     rule \a fillRule.
4874 */
4875
4876 /*! \fn void QPainter::drawPolygon(const QPolygon &points, Qt::FillRule fillRule)
4877
4878     \overload
4879
4880     Draws the polygon defined by the given \a points using the fill
4881     rule \a fillRule.
4882 */
4883
4884 /*!
4885     \fn void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4886
4887     Draws the convex polygon defined by the first \a pointCount points
4888     in the array \a points using the current pen.
4889
4890     \table 100%
4891     \row
4892     \li \inlineimage qpainter-polygon.png
4893     \li
4894     \snippet code/src_gui_painting_qpainter.cpp 15
4895     \endtable
4896
4897     The first point is implicitly connected to the last point, and the
4898     polygon is filled with the current brush().  If the supplied
4899     polygon is not convex, i.e. it contains at least one angle larger
4900     than 180 degrees, the results are undefined.
4901
4902     On some platforms (e.g. X11), the drawConvexPolygon() function can
4903     be faster than the drawPolygon() function.
4904
4905     \sa drawPolygon(), drawPolyline(), {Coordinate System}
4906 */
4907
4908 /*!
4909     \fn void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4910     \overload
4911
4912     Draws the convex polygon defined by the first \a pointCount points
4913     in the array \a points using the current pen.
4914 */
4915
4916 /*!
4917     \fn void QPainter::drawConvexPolygon(const QPolygonF &polygon)
4918
4919     \overload
4920
4921     Draws the convex polygon defined by \a polygon using the current
4922     pen and brush.
4923 */
4924
4925 /*!
4926     \fn void QPainter::drawConvexPolygon(const QPolygon &polygon)
4927     \overload
4928
4929     Draws the convex polygon defined by \a polygon using the current
4930     pen and brush.
4931 */
4932
4933 void QPainter::drawConvexPolygon(const QPoint *points, int pointCount)
4934 {
4935 #ifdef QT_DEBUG_DRAW
4936     if (qt_show_painter_debug_output)
4937         printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4938 #endif
4939
4940     Q_D(QPainter);
4941
4942     if (!d->engine || pointCount < 2)
4943         return;
4944
4945     if (d->extended) {
4946         d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4947         return;
4948     }
4949
4950     d->updateState(d->state);
4951
4952     uint emulationSpecifier = d->state->emulationSpecifier;
4953
4954     if (emulationSpecifier) {
4955         QPainterPath polygonPath(points[0]);
4956         for (int i=1; i<pointCount; ++i)
4957             polygonPath.lineTo(points[i]);
4958         polygonPath.closeSubpath();
4959         polygonPath.setFillRule(Qt::WindingFill);
4960         d->draw_helper(polygonPath);
4961         return;
4962     }
4963
4964     d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4965 }
4966
4967 void QPainter::drawConvexPolygon(const QPointF *points, int pointCount)
4968 {
4969 #ifdef QT_DEBUG_DRAW
4970     if (qt_show_painter_debug_output)
4971         printf("QPainter::drawConvexPolygon(), count=%d\n", pointCount);
4972 #endif
4973
4974     Q_D(QPainter);
4975
4976     if (!d->engine || pointCount < 2)
4977         return;
4978
4979     if (d->extended) {
4980         d->extended->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4981         return;
4982     }
4983
4984     d->updateState(d->state);
4985
4986     uint emulationSpecifier = d->state->emulationSpecifier;
4987
4988     if (emulationSpecifier) {
4989         QPainterPath polygonPath(points[0]);
4990         for (int i=1; i<pointCount; ++i)
4991             polygonPath.lineTo(points[i]);
4992         polygonPath.closeSubpath();
4993         polygonPath.setFillRule(Qt::WindingFill);
4994         d->draw_helper(polygonPath);
4995         return;
4996     }
4997
4998     d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode);
4999 }
5000
5001 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m)
5002 {
5003     return m.inverted().map(QPointF(m.map(p).toPoint()));
5004 }
5005
5006 /*!
5007     \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
5008
5009     Draws the rectangular portion \a source of the given \a pixmap
5010     into the given \a target in the paint device.
5011
5012     \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5013
5014     \table 100%
5015     \row
5016     \li
5017     \snippet code/src_gui_painting_qpainter.cpp 16
5018     \endtable
5019
5020     If \a pixmap is a QBitmap it is drawn with the bits that are "set"
5021     using the pens color. If backgroundMode is Qt::OpaqueMode, the
5022     "unset" bits are drawn using the color of the background brush; if
5023     backgroundMode is Qt::TransparentMode, the "unset" bits are
5024     transparent. Drawing bitmaps with gradient or texture colors is
5025     not supported.
5026
5027     \sa drawImage()
5028 */
5029 void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
5030 {
5031 #if defined QT_DEBUG_DRAW
5032     if (qt_show_painter_debug_output)
5033         printf("QPainter::drawPixmap(), p=[%.2f,%.2f], pix=[%d,%d]\n",
5034                p.x(), p.y(),
5035                pm.width(), pm.height());
5036 #endif
5037
5038     Q_D(QPainter);
5039
5040     if (!d->engine || pm.isNull())
5041         return;
5042
5043 #ifndef QT_NO_DEBUG
5044     qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5045 #endif
5046
5047     if (d->extended) {
5048         d->extended->drawPixmap(p, pm);
5049         return;
5050     }
5051
5052     qreal x = p.x();
5053     qreal y = p.y();
5054
5055     int w = pm.width();
5056     int h = pm.height();
5057
5058     if (w <= 0)
5059         return;
5060
5061     // Emulate opaque background for bitmaps
5062     if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) {
5063         fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5064     }
5065
5066     d->updateState(d->state);
5067
5068     if ((d->state->matrix.type() > QTransform::TxTranslate
5069          && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5070         || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5071         || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5072     {
5073         save();
5074         // If there is no rotation involved we have to make sure we use the
5075         // antialiased and not the aliased coordinate system by rounding the coordinates.
5076         if (d->state->matrix.type() <= QTransform::TxScale) {
5077             const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5078             x = p.x();
5079             y = p.y();
5080         }
5081         translate(x, y);
5082         setBackgroundMode(Qt::TransparentMode);
5083         setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5084         QBrush brush(d->state->pen.color(), pm);
5085         setBrush(brush);
5086         setPen(Qt::NoPen);
5087         setBrushOrigin(QPointF(0, 0));
5088
5089         drawRect(pm.rect());
5090         restore();
5091     } else {
5092         if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5093             x += d->state->matrix.dx();
5094             y += d->state->matrix.dy();
5095         }
5096         d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
5097     }
5098 }
5099
5100 void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
5101 {
5102 #if defined QT_DEBUG_DRAW
5103     if (qt_show_painter_debug_output)
5104         printf("QPainter::drawPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], source=[%.2f,%.2f,%.2f,%.2f]\n",
5105                r.x(), r.y(), r.width(), r.height(),
5106                pm.width(), pm.height(),
5107                sr.x(), sr.y(), sr.width(), sr.height());
5108 #endif
5109
5110     Q_D(QPainter);
5111     if (!d->engine || pm.isNull())
5112         return;
5113 #ifndef QT_NO_DEBUG
5114     qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
5115 #endif
5116
5117     qreal x = r.x();
5118     qreal y = r.y();
5119     qreal w = r.width();
5120     qreal h = r.height();
5121     qreal sx = sr.x();
5122     qreal sy = sr.y();
5123     qreal sw = sr.width();
5124     qreal sh = sr.height();
5125
5126     // Sanity-check clipping
5127     if (sw <= 0)
5128         sw = pm.width() - sx;
5129
5130     if (sh <= 0)
5131         sh = pm.height() - sy;
5132
5133     if (w < 0)
5134         w = sw;
5135     if (h < 0)
5136         h = sh;
5137
5138     if (sx < 0) {
5139         qreal w_ratio = sx * w/sw;
5140         x -= w_ratio;
5141         w += w_ratio;
5142         sw += sx;
5143         sx = 0;
5144     }
5145
5146     if (sy < 0) {
5147         qreal h_ratio = sy * h/sh;
5148         y -= h_ratio;
5149         h += h_ratio;
5150         sh += sy;
5151         sy = 0;
5152     }
5153
5154     if (sw + sx > pm.width()) {
5155         qreal delta = sw - (pm.width() - sx);
5156         qreal w_ratio = delta * w/sw;
5157         sw -= delta;
5158         w -= w_ratio;
5159     }
5160
5161     if (sh + sy > pm.height()) {
5162         qreal delta = sh - (pm.height() - sy);
5163         qreal h_ratio = delta * h/sh;
5164         sh -= delta;
5165         h -= h_ratio;
5166     }
5167
5168     if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5169         return;
5170
5171     if (d->extended) {
5172         d->extended->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5173         return;
5174     }
5175
5176     // Emulate opaque background for bitmaps
5177     if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap())
5178         fillRect(QRectF(x, y, w, h), d->state->bgBrush.color());
5179
5180     d->updateState(d->state);
5181
5182     if ((d->state->matrix.type() > QTransform::TxTranslate
5183          && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5184         || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5185         || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))
5186         || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform)))
5187     {
5188         save();
5189         // If there is no rotation involved we have to make sure we use the
5190         // antialiased and not the aliased coordinate system by rounding the coordinates.
5191         if (d->state->matrix.type() <= QTransform::TxScale) {
5192             const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5193             x = p.x();
5194             y = p.y();
5195         }
5196
5197         if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5198             sx = qRound(sx);
5199             sy = qRound(sy);
5200             sw = qRound(sw);
5201             sh = qRound(sh);
5202         }
5203
5204         translate(x, y);
5205         scale(w / sw, h / sh);
5206         setBackgroundMode(Qt::TransparentMode);
5207         setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5208         QBrush brush;
5209
5210         if (sw == pm.width() && sh == pm.height())
5211             brush = QBrush(d->state->pen.color(), pm);
5212         else
5213             brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
5214
5215         setBrush(brush);
5216         setPen(Qt::NoPen);
5217
5218         drawRect(QRectF(0, 0, sw, sh));
5219         restore();
5220     } else {
5221         if (!d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5222             x += d->state->matrix.dx();
5223             y += d->state->matrix.dy();
5224         }
5225         d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
5226     }
5227 }
5228
5229
5230 /*!
5231     \fn void QPainter::drawPixmap(const QRect &target, const QPixmap &pixmap,
5232                                   const QRect &source)
5233     \overload
5234
5235     Draws the rectangular portion \a source of the given \a pixmap
5236     into the given \a target in the paint device.
5237
5238     \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5239 */
5240
5241 /*!
5242     \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap,
5243                                   const QRectF &source)
5244     \overload
5245
5246     Draws the rectangular portion \a source of the given \a pixmap
5247     with its origin at the given \a point.
5248 */
5249
5250 /*!
5251     \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap,
5252                                   const QRect &source)
5253
5254     \overload
5255
5256     Draws the rectangular portion \a source of the given \a pixmap
5257     with its origin at the given \a point.
5258 */
5259
5260 /*!
5261     \fn void QPainter::drawPixmap(const QPointF &point, const QPixmap &pixmap)
5262     \overload
5263
5264     Draws the given \a pixmap with its origin at the given \a point.
5265 */
5266
5267 /*!
5268     \fn void QPainter::drawPixmap(const QPoint &point, const QPixmap &pixmap)
5269     \overload
5270
5271     Draws the given \a pixmap with its origin at the given \a point.
5272 */
5273
5274 /*!
5275     \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap)
5276
5277     \overload
5278
5279     Draws the given \a pixmap at position (\a{x}, \a{y}).
5280 */
5281
5282 /*!
5283     \fn void QPainter::drawPixmap(const QRect &rectangle, const QPixmap &pixmap)
5284     \overload
5285
5286     Draws the given \a  pixmap into the given \a rectangle.
5287
5288     \note The pixmap is scaled to fit the rectangle, if both the pixmap and rectangle size disagree.
5289 */
5290
5291 /*!
5292     \fn void QPainter::drawPixmap(int x, int y, int width, int height,
5293     const QPixmap &pixmap)
5294
5295     \overload
5296
5297     Draws the \a pixmap into the rectangle at position (\a{x}, \a{y})
5298     with  the given \a width and \a height.
5299 */
5300
5301 /*!
5302     \fn void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap,
5303                                   int sx, int sy, int sw, int sh)
5304
5305     \overload
5306
5307     Draws the rectangular portion with the origin (\a{sx}, \a{sy}),
5308     width \a sw and height \a sh, of the given \a pixmap , at the
5309     point (\a{x}, \a{y}), with a width of \a w and a height of \a h.
5310     If sw or sh are equal to zero the width/height of the pixmap
5311     is used and adjusted by the offset sx/sy;
5312 */
5313
5314 /*!
5315     \fn void QPainter::drawPixmap(int x, int y, const QPixmap &pixmap,
5316                                   int sx, int sy, int sw, int sh)
5317
5318     \overload
5319
5320     Draws a pixmap at (\a{x}, \a{y}) by copying a part of the given \a
5321     pixmap into the paint device.
5322
5323     (\a{x}, \a{y}) specifies the top-left point in the paint device that is
5324     to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
5325     pixmap that is to be drawn. The default is (0, 0).
5326
5327     (\a{sw}, \a{sh}) specifies the size of the pixmap that is to be drawn.
5328     The default, (0, 0) (and negative) means all the way to the
5329     bottom-right of the pixmap.
5330 */
5331
5332 void QPainter::drawImage(const QPointF &p, const QImage &image)
5333 {
5334     Q_D(QPainter);
5335
5336     if (!d->engine || image.isNull())
5337         return;
5338
5339     if (d->extended) {
5340         d->extended->drawImage(p, image);
5341         return;
5342     }
5343
5344     qreal x = p.x();
5345     qreal y = p.y();
5346
5347     int w = image.width();
5348     int h = image.height();
5349
5350     d->updateState(d->state);
5351
5352     if (((d->state->matrix.type() > QTransform::TxTranslate)
5353          && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5354         || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5355         || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5356     {
5357         save();
5358         // If there is no rotation involved we have to make sure we use the
5359         // antialiased and not the aliased coordinate system by rounding the coordinates.
5360         if (d->state->matrix.type() <= QTransform::TxScale) {
5361             const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5362             x = p.x();
5363             y = p.y();
5364         }
5365         translate(x, y);
5366         setBackgroundMode(Qt::TransparentMode);
5367         setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5368         QBrush brush(image);
5369         setBrush(brush);
5370         setPen(Qt::NoPen);
5371         setBrushOrigin(QPointF(0, 0));
5372
5373         drawRect(image.rect());
5374         restore();
5375         return;
5376     }
5377
5378     if (d->state->matrix.type() == QTransform::TxTranslate
5379         && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5380         x += d->state->matrix.dx();
5381         y += d->state->matrix.dy();
5382     }
5383
5384     d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
5385 }
5386
5387 void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
5388                          Qt::ImageConversionFlags flags)
5389 {
5390     Q_D(QPainter);
5391
5392     if (!d->engine || image.isNull())
5393         return;
5394
5395     qreal x = targetRect.x();
5396     qreal y = targetRect.y();
5397     qreal w = targetRect.width();
5398     qreal h = targetRect.height();
5399     qreal sx = sourceRect.x();
5400     qreal sy = sourceRect.y();
5401     qreal sw = sourceRect.width();
5402     qreal sh = sourceRect.height();
5403
5404     // Sanity-check clipping
5405     if (sw <= 0)
5406         sw = image.width() - sx;
5407
5408     if (sh <= 0)
5409         sh = image.height() - sy;
5410
5411     if (w < 0)
5412         w = sw;
5413     if (h < 0)
5414         h = sh;
5415
5416     if (sx < 0) {
5417         qreal w_ratio = sx * w/sw;
5418         x -= w_ratio;
5419         w += w_ratio;
5420         sw += sx;
5421         sx = 0;
5422     }
5423
5424     if (sy < 0) {
5425         qreal h_ratio = sy * h/sh;
5426         y -= h_ratio;
5427         h += h_ratio;
5428         sh += sy;
5429         sy = 0;
5430     }
5431
5432     if (sw + sx > image.width()) {
5433         qreal delta = sw - (image.width() - sx);
5434         qreal w_ratio = delta * w/sw;
5435         sw -= delta;
5436         w -= w_ratio;
5437     }
5438
5439     if (sh + sy > image.height()) {
5440         qreal delta = sh - (image.height() - sy);
5441         qreal h_ratio = delta * h/sh;
5442         sh -= delta;
5443         h -= h_ratio;
5444     }
5445
5446     if (w == 0 || h == 0 || sw <= 0 || sh <= 0)
5447         return;
5448
5449     if (d->extended) {
5450         d->extended->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5451         return;
5452     }
5453
5454     d->updateState(d->state);
5455
5456     if (((d->state->matrix.type() > QTransform::TxTranslate || (sw != w || sh != h))
5457          && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
5458         || (!d->state->matrix.isAffine() && !d->engine->hasFeature(QPaintEngine::PerspectiveTransform))
5459         || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
5460     {
5461         save();
5462         // If there is no rotation involved we have to make sure we use the
5463         // antialiased and not the aliased coordinate system by rounding the coordinates.
5464         if (d->state->matrix.type() <= QTransform::TxScale) {
5465             const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix);
5466             x = p.x();
5467             y = p.y();
5468         }
5469
5470         if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) {
5471             sx = qRound(sx);
5472             sy = qRound(sy);
5473             sw = qRound(sw);
5474             sh = qRound(sh);
5475         }
5476         translate(x, y);
5477         scale(w / sw, h / sh);
5478         setBackgroundMode(Qt::TransparentMode);
5479         setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
5480         QBrush brush(image);
5481         setBrush(brush);
5482         setPen(Qt::NoPen);
5483         setBrushOrigin(QPointF(-sx, -sy));
5484
5485         drawRect(QRectF(0, 0, sw, sh));
5486         restore();
5487         return;
5488     }
5489
5490     if (d->state->matrix.type() == QTransform::TxTranslate
5491         && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
5492         x += d->state->matrix.dx();
5493         y += d->state->matrix.dy();
5494     }
5495
5496     d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
5497 }
5498
5499 /*!
5500     \fn void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphs)
5501
5502     Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
5503     edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
5504     selected on \a glyphs and at offsets given by the positions in \a glyphs.
5505
5506     \since 4.8
5507
5508     \sa QGlyphRun::setRawFont(), QGlyphRun::setPositions(), QGlyphRun::setGlyphIndexes()
5509 */
5510 #if !defined(QT_NO_RAWFONT)
5511 void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun)
5512 {
5513     Q_D(QPainter);
5514
5515     QRawFont font = glyphRun.rawFont();
5516     if (!font.isValid())
5517         return;
5518
5519     QGlyphRunPrivate *glyphRun_d = QGlyphRunPrivate::get(glyphRun);
5520
5521     const quint32 *glyphIndexes = glyphRun_d->glyphIndexData;
5522     const QPointF *glyphPositions = glyphRun_d->glyphPositionData;
5523
5524     int count = qMin(glyphRun_d->glyphIndexDataSize, glyphRun_d->glyphPositionDataSize);
5525     QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
5526
5527     QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5528     bool supportsTransformations = d->extended
5529         ? d->extended->supportsTransformations(fontD->fontEngine, d->state->matrix)
5530         : d->engine->type() == QPaintEngine::CoreGraphics || d->state->matrix.isAffine();
5531
5532     for (int i=0; i<count; ++i) {
5533         QPointF processedPosition = position + glyphPositions[i];
5534         if (!supportsTransformations)
5535             processedPosition = d->state->transform().map(processedPosition);
5536         fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
5537     }
5538
5539     d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, font, glyphRun.overline(),
5540                   glyphRun.underline(), glyphRun.strikeOut());
5541 }
5542
5543 void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions,
5544                                  int glyphCount,
5545                                  const QRawFont &font, bool overline, bool underline,
5546                                  bool strikeOut)
5547 {
5548     Q_Q(QPainter);
5549
5550     updateState(state);
5551
5552     QRawFontPrivate *fontD = QRawFontPrivate::get(font);
5553     QFontEngine *fontEngine = fontD->fontEngine;
5554
5555     QFixed leftMost;
5556     QFixed rightMost;
5557     QFixed baseLine;
5558     for (int i=0; i<glyphCount; ++i) {
5559         glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
5560         if (i == 0 || leftMost > positions[i].x)
5561             leftMost = positions[i].x;
5562
5563         // We don't support glyphs that do not share a common baseline. If this turns out to
5564         // be a relevant use case, then we need to find clusters of glyphs that share a baseline
5565         // and do a drawTextItemDecorations call per cluster.
5566         if (i == 0 || baseLine < positions[i].y)
5567             baseLine = positions[i].y;
5568
5569         // We use the advance rather than the actual bounds to match the algorithm in drawText()
5570         if (i == 0 || rightMost < positions[i].x + gm.xoff)
5571             rightMost = positions[i].x + gm.xoff;
5572     }
5573
5574     QFixed width = rightMost - leftMost;
5575
5576     if (extended != 0 && state->matrix.isAffine()) {
5577         QStaticTextItem staticTextItem;
5578         staticTextItem.color = state->pen.color();
5579         staticTextItem.font = state->font;
5580         staticTextItem.setFontEngine(fontEngine);
5581         staticTextItem.numGlyphs = glyphCount;
5582         staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
5583         staticTextItem.glyphPositions = positions;
5584
5585         extended->drawStaticTextItem(&staticTextItem);
5586     } else {
5587         QTextItemInt textItem;
5588         textItem.fontEngine = fontEngine;
5589
5590         QVarLengthArray<QFixed, 128> advances(glyphCount);
5591         QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
5592         QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
5593         memset(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
5594         memset(advances.data(), 0, advances.size() * sizeof(QFixed));
5595         memset(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
5596
5597         textItem.glyphs.numGlyphs = glyphCount;
5598         textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
5599         textItem.glyphs.offsets = positions;
5600         textItem.glyphs.advances_x = advances.data();
5601         textItem.glyphs.advances_y = advances.data();
5602         textItem.glyphs.justifications = glyphJustifications.data();
5603         textItem.glyphs.attributes = glyphAttributes.data();
5604
5605         engine->drawTextItem(QPointF(0, 0), textItem);
5606     }
5607
5608     QTextItemInt::RenderFlags flags;
5609     if (underline)
5610         flags |= QTextItemInt::Underline;
5611     if (overline)
5612         flags |= QTextItemInt::Overline;
5613     if (strikeOut)
5614         flags |= QTextItemInt::StrikeOut;
5615
5616     drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
5617                            fontEngine,
5618                            0, // textEngine
5619                            (underline
5620                               ? QTextCharFormat::SingleUnderline
5621                               : QTextCharFormat::NoUnderline),
5622                            flags, width.toReal(), QTextCharFormat());
5623 }
5624 #endif // QT_NO_RAWFONT
5625
5626 /*!
5627
5628     \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
5629     \since 4.7
5630     \overload
5631
5632     Draws the \a staticText at the \a topLeftPosition.
5633
5634     \note The y-position is used as the top of the font.
5635
5636 */
5637
5638 /*!
5639     \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
5640     \since 4.7
5641     \overload
5642
5643     Draws the \a staticText at coordinates \a left and \a top.
5644
5645     \note The y-position is used as the top of the font.
5646 */
5647
5648 /*!
5649     \fn void QPainter::drawText(const QPointF &position, const QString &text)
5650
5651     Draws the given \a text with the currently defined text direction,
5652     beginning at the given \a position.
5653
5654     This function does not handle the newline character (\n), as it cannot
5655     break text into multiple lines, and it cannot display the newline character.
5656     Use the QPainter::drawText() overload that takes a rectangle instead
5657     if you want to draw multiple lines of text with the newline character, or
5658     if you want the text to be wrapped.
5659
5660     By default, QPainter draws text anti-aliased.
5661
5662     \note The y-position is used as the baseline of the font.
5663 */
5664
5665 void QPainter::drawText(const QPointF &p, const QString &str)
5666 {
5667     drawText(p, str, 0, 0);
5668 }
5669
5670 /*!
5671     \since 4.7
5672
5673     Draws the given \a staticText at the given \a topLeftPosition.
5674
5675     The text will be drawn using the font and the transformation set on the painter. If the
5676     font and/or transformation set on the painter are different from the ones used to initialize
5677     the layout of the QStaticText, then the layout will have to be recalculated. Use
5678     QStaticText::prepare() to initialize \a staticText with the font and transformation with which
5679     it will later be drawn.
5680
5681     If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
5682     last drawn, then there will be a slight overhead when translating the text to its new position.
5683
5684     \note If the painter's transformation is not affine, then \a staticText will be drawn using
5685     regular calls to drawText(), losing any potential for performance improvement.
5686
5687     \note The y-position is used as the top of the font.
5688
5689     \sa QStaticText
5690 */
5691 void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
5692 {
5693     Q_D(QPainter);
5694     if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
5695         return;
5696
5697     QStaticTextPrivate *staticText_d =
5698             const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
5699
5700     if (font() != staticText_d->font) {
5701         staticText_d->font = font();
5702         staticText_d->needsRelayout = true;
5703     }
5704
5705     // If we don't have an extended paint engine, or if the painter is projected,
5706     // we go through standard code path
5707     if (d->extended == 0 || !d->state->matrix.isAffine()) {
5708         staticText_d->paintText(topLeftPosition, this);
5709         return;
5710     }
5711
5712     QFontEngine *fe = staticText_d->font.d->engineForScript(QUnicodeTables::Common);
5713     if (fe->type() == QFontEngine::Multi)
5714         fe = static_cast<QFontEngineMulti *>(fe)->engine(0);
5715     bool supportsTransformations = d->extended->supportsTransformations(fe,
5716                                                                         d->state->matrix);
5717     if (supportsTransformations && !staticText_d->untransformedCoordinates) {
5718         staticText_d->untransformedCoordinates = true;
5719         staticText_d->needsRelayout = true;
5720     } else if (!supportsTransformations && staticText_d->untransformedCoordinates) {
5721         staticText_d->untransformedCoordinates = false;
5722         staticText_d->needsRelayout = true;
5723     }
5724
5725     // Don't recalculate entire layout because of translation, rather add the dx and dy
5726     // into the position to move each text item the correct distance.
5727     QPointF transformedPosition = topLeftPosition;
5728     if (!staticText_d->untransformedCoordinates)
5729         transformedPosition = transformedPosition * d->state->matrix;
5730     QTransform oldMatrix;
5731
5732     // The translation has been applied to transformedPosition. Remove translation
5733     // component from matrix.
5734     if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) {
5735         qreal m11 = d->state->matrix.m11();
5736         qreal m12 = d->state->matrix.m12();
5737         qreal m13 = d->state->matrix.m13();
5738         qreal m21 = d->state->matrix.m21();
5739         qreal m22 = d->state->matrix.m22();
5740         qreal m23 = d->state->matrix.m23();
5741         qreal m33 = d->state->matrix.m33();
5742
5743         oldMatrix = d->state->matrix;
5744         d->state->matrix.setMatrix(m11, m12, m13,
5745                                    m21, m22, m23,
5746                                    0.0, 0.0, m33);
5747     }
5748
5749     // If the transform is not identical to the text transform,
5750     // we have to relayout the text (for other transformations than plain translation)
5751     bool staticTextNeedsReinit = staticText_d->needsRelayout;
5752     if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) {
5753         staticText_d->matrix = d->state->matrix;
5754         staticTextNeedsReinit = true;
5755     }
5756
5757     // Recreate the layout of the static text because the matrix or font has changed
5758     if (staticTextNeedsReinit)
5759         staticText_d->init();
5760
5761     if (transformedPosition != staticText_d->position) { // Translate to actual position
5762         QFixed fx = QFixed::fromReal(transformedPosition.x());
5763         QFixed fy = QFixed::fromReal(transformedPosition.y());
5764         QFixed oldX = QFixed::fromReal(staticText_d->position.x());
5765         QFixed oldY = QFixed::fromReal(staticText_d->position.y());
5766         for (int item=0; item<staticText_d->itemCount;++item) {
5767             QStaticTextItem *textItem = staticText_d->items + item;
5768             for (int i=0; i<textItem->numGlyphs; ++i) {
5769                 textItem->glyphPositions[i].x += fx - oldX;
5770                 textItem->glyphPositions[i].y += fy - oldY;
5771             }
5772             textItem->userDataNeedsUpdate = true;
5773         }
5774
5775         staticText_d->position = transformedPosition;
5776     }
5777
5778     QPen oldPen = d->state->pen;
5779     QColor currentColor = oldPen.color();
5780     for (int i=0; i<staticText_d->itemCount; ++i) {
5781         QStaticTextItem *item = staticText_d->items + i;
5782         if (item->color.isValid() && currentColor != item->color) {
5783             setPen(item->color);
5784             currentColor = item->color;
5785         }
5786         d->extended->drawStaticTextItem(item);
5787
5788         qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
5789                                       item->numGlyphs, item->fontEngine(), staticText_d->font,
5790                                       QTextCharFormat());
5791     }
5792     if (currentColor != oldPen.color())
5793         setPen(oldPen);
5794
5795     if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating())
5796         d->state->matrix = oldMatrix;
5797 }
5798
5799 /*!
5800    \internal
5801 */
5802 void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justificationPadding)
5803 {
5804 #ifdef QT_DEBUG_DRAW
5805     if (qt_show_painter_debug_output)
5806         printf("QPainter::drawText(), pos=[%.2f,%.2f], str='%s'\n", p.x(), p.y(), str.toLatin1().constData());
5807 #endif
5808
5809     Q_D(QPainter);
5810
5811     if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
5812         return;
5813
5814     if (tf & Qt::TextBypassShaping) {
5815         // Skip harfbuzz complex shaping, shape using glyph advances only
5816         int len = str.length();
5817         int numGlyphs = len;
5818         QVarLengthGlyphLayoutArray glyphs(len);
5819         QFontEngine *fontEngine = d->state->font.d->engineForScript(QUnicodeTables::Common);
5820         if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
5821             glyphs.resize(numGlyphs);
5822             if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
5823                 Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
5824         }
5825
5826         QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
5827         drawTextItem(p, gf);
5828         return;
5829     }
5830
5831     QStackTextEngine engine(str, d->state->font);
5832     engine.option.setTextDirection(d->state->layoutDirection);
5833     if (tf & (Qt::TextForceLeftToRight|Qt::TextForceRightToLeft)) {
5834         engine.ignoreBidi = true;
5835         engine.option.setTextDirection((tf & Qt::TextForceLeftToRight) ? Qt::LeftToRight : Qt::RightToLeft);
5836     }
5837     engine.itemize();
5838     QScriptLine line;
5839     line.length = str.length();
5840     engine.shapeLine(line);
5841
5842     int nItems = engine.layoutData->items.size();
5843     QVarLengthArray<int> visualOrder(nItems);
5844     QVarLengthArray<uchar> levels(nItems);
5845     for (int i = 0; i < nItems; ++i)
5846         levels[i] = engine.layoutData->items[i].analysis.bidiLevel;
5847     QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
5848
5849     if (justificationPadding > 0) {
5850         engine.option.setAlignment(Qt::AlignJustify);
5851         engine.forceJustification = true;
5852         // this works because justify() is only interested in the difference between width and textWidth
5853         line.width = justificationPadding;
5854         engine.justify(line);
5855     }
5856     QFixed x = QFixed::fromReal(p.x());
5857
5858     for (int i = 0; i < nItems; ++i) {
5859         int item = visualOrder[i];
5860         const QScriptItem &si = engine.layoutData->items.at(item);
5861         if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
5862             x += si.width;
5863             continue;
5864         }
5865         QFont f = engine.font(si);
5866         QTextItemInt gf(si, &f);
5867         gf.glyphs = engine.shapedGlyphs(&si);
5868         gf.chars = engine.layoutData->string.unicode() + si.position;
5869         gf.num_chars = engine.length(item);
5870         if (engine.forceJustification) {
5871             for (int j=0; j<gf.glyphs.numGlyphs; ++j)
5872                 gf.width += gf.glyphs.effectiveAdvance(j);
5873         } else {
5874             gf.width = si.width;
5875         }
5876         gf.logClusters = engine.logClusters(&si);
5877
5878         drawTextItem(QPointF(x.toReal(), p.y()), gf);
5879
5880         x += gf.width;
5881     }
5882 }
5883
5884 void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br)
5885 {
5886 #ifdef QT_DEBUG_DRAW
5887     if (qt_show_painter_debug_output)
5888         printf("QPainter::drawText(), r=[%d,%d,%d,%d], flags=%d, str='%s'\n",
5889            r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5890 #endif
5891
5892     Q_D(QPainter);
5893
5894     if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5895         return;
5896
5897     if (!d->extended)
5898         d->updateState(d->state);
5899
5900     QRectF bounds;
5901     qt_format_text(d->state->font, r, flags, 0, str, br ? &bounds : 0, 0, 0, 0, this);
5902     if (br)
5903         *br = bounds.toAlignedRect();
5904 }
5905
5906 /*!
5907     \fn void QPainter::drawText(const QPoint &position, const QString &text)
5908
5909     \overload
5910
5911     Draws the given \a text with the currently defined text direction,
5912     beginning at the given \a position.
5913
5914     By default, QPainter draws text anti-aliased.
5915
5916     \note The y-position is used as the baseline of the font.
5917
5918 */
5919
5920 /*!
5921     \fn void QPainter::drawText(const QRectF &rectangle, int flags, const QString &text, QRectF *boundingRect)
5922     \overload
5923
5924     Draws the given \a text within the provided \a rectangle.
5925
5926     \table 100%
5927     \row
5928     \li \inlineimage qpainter-text.png
5929     \li
5930     \snippet code/src_gui_painting_qpainter.cpp 17
5931     \endtable
5932
5933     The \a boundingRect (if not null) is set to the what the bounding rectangle
5934     should be in order to enclose the whole text. The \a flags argument is a bitwise
5935     OR of the following flags:
5936
5937     \list
5938     \li Qt::AlignLeft
5939     \li Qt::AlignRight
5940     \li Qt::AlignHCenter
5941     \li Qt::AlignJustify
5942     \li Qt::AlignTop
5943     \li Qt::AlignBottom
5944     \li Qt::AlignVCenter
5945     \li Qt::AlignCenter
5946     \li Qt::TextDontClip
5947     \li Qt::TextSingleLine
5948     \li Qt::TextExpandTabs
5949     \li Qt::TextShowMnemonic
5950     \li Qt::TextWordWrap
5951     \li Qt::TextIncludeTrailingSpaces
5952     \endlist
5953
5954     \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection()
5955
5956     By default, QPainter draws text anti-aliased.
5957
5958     \note The y-coordinate of \a rectangle is used as the top of the font.
5959 */
5960 void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *br)
5961 {
5962 #ifdef QT_DEBUG_DRAW
5963     if (qt_show_painter_debug_output)
5964         printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], flags=%d, str='%s'\n",
5965            r.x(), r.y(), r.width(), r.height(), flags, str.toLatin1().constData());
5966 #endif
5967
5968     Q_D(QPainter);
5969
5970     if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
5971         return;
5972
5973     if (!d->extended)
5974         d->updateState(d->state);
5975
5976     qt_format_text(d->state->font, r, flags, 0, str, br, 0, 0, 0, this);
5977 }
5978
5979 /*!
5980     \fn void QPainter::drawText(const QRect &rectangle, int flags, const QString &text, QRect *boundingRect)
5981     \overload
5982
5983     Draws the given \a text within the provided \a rectangle according
5984     to the specified \a flags. The \a boundingRect (if not null) is set to
5985     the what the bounding rectangle should be in order to enclose the whole text.
5986
5987     By default, QPainter draws text anti-aliased.
5988
5989     \note The y-coordinate of \a rectangle is used as the top of the font.
5990 */
5991
5992 /*!
5993     \fn void QPainter::drawText(int x, int y, const QString &text)
5994
5995     \overload
5996
5997     Draws the given \a text at position (\a{x}, \a{y}), using the painter's
5998     currently defined text direction.
5999
6000     By default, QPainter draws text anti-aliased.
6001
6002     \note The y-position is used as the baseline of the font.
6003
6004 */
6005
6006 /*!
6007     \fn void QPainter::drawText(int x, int y, int width, int height, int flags,
6008                                 const QString &text, QRect *boundingRect)
6009
6010     \overload
6011
6012     Draws the given \a text within the rectangle with origin (\a{x},
6013     \a{y}), \a width and \a height.
6014
6015     The \a boundingRect (if not null) is set to the actual bounding
6016     rectangle of the output.  The \a flags argument is a bitwise OR of
6017     the following flags:
6018
6019     \list
6020     \li Qt::AlignLeft
6021     \li Qt::AlignRight
6022     \li Qt::AlignHCenter
6023     \li Qt::AlignJustify
6024     \li Qt::AlignTop
6025     \li Qt::AlignBottom
6026     \li Qt::AlignVCenter
6027     \li Qt::AlignCenter
6028     \li Qt::TextSingleLine
6029     \li Qt::TextExpandTabs
6030     \li Qt::TextShowMnemonic
6031     \li Qt::TextWordWrap
6032     \endlist
6033
6034     By default, QPainter draws text anti-aliased.
6035
6036     \note The y-position is used as the top of the font.
6037
6038     \sa Qt::AlignmentFlag, Qt::TextFlag
6039 */
6040
6041 /*!
6042     \fn void QPainter::drawText(const QRectF &rectangle, const QString &text,
6043         const QTextOption &option)
6044     \overload
6045
6046     Draws the given \a text in the \a rectangle specified using the \a option
6047     to control its positioning and orientation.
6048
6049     By default, QPainter draws text anti-aliased.
6050
6051     \note The y-coordinate of \a rectangle is used as the top of the font.
6052 */
6053 void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption &o)
6054 {
6055 #ifdef QT_DEBUG_DRAW
6056     if (qt_show_painter_debug_output)
6057         printf("QPainter::drawText(), r=[%.2f,%.2f,%.2f,%.2f], str='%s'\n",
6058            r.x(), r.y(), r.width(), r.height(), text.toLatin1().constData());
6059 #endif
6060
6061     Q_D(QPainter);
6062
6063     if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
6064         return;
6065
6066     if (!d->extended)
6067         d->updateState(d->state);
6068
6069     qt_format_text(d->state->font, r, 0, &o, text, 0, 0, 0, 0, this);
6070 }
6071
6072 /*!
6073     \fn void QPainter::drawTextItem(int x, int y, const QTextItem &ti)
6074
6075     \internal
6076     \overload
6077 */
6078
6079 /*!
6080     \fn void QPainter::drawTextItem(const QPoint &p, const QTextItem &ti)
6081
6082     \internal
6083     \overload
6084
6085     Draws the text item \a ti at position \a p.
6086 */
6087
6088 /*!
6089     \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6090
6091     \internal
6092     \since 4.1
6093
6094     Draws the text item \a ti at position \a p.
6095
6096     This method ignores the painters background mode and
6097     color. drawText and qt_format_text have to do it themselves, as
6098     only they know the extents of the complete string.
6099
6100     It ignores the font set on the painter as the text item has one of its own.
6101
6102     The underline and strikeout parameters of the text items font are
6103     ignored aswell. You'll need to pass in the correct flags to get
6104     underlining and strikeout.
6105 */
6106
6107 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
6108 {
6109     const qreal radiusBase = qMax(qreal(1), maxRadius);
6110
6111     QString key = QLatin1String("WaveUnderline-")
6112                   % pen.color().name()
6113                   % HexString<qreal>(radiusBase);
6114
6115     QPixmap pixmap;
6116     if (QPixmapCache::find(key, pixmap))
6117         return pixmap;
6118
6119     const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio
6120     const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod);
6121     const int radius = qFloor(radiusBase);
6122
6123     QPainterPath path;
6124
6125     qreal xs = 0;
6126     qreal ys = radius;
6127
6128     while (xs < width) {
6129         xs += halfPeriod;
6130         ys = -ys;
6131         path.quadTo(xs - halfPeriod / 2, ys, xs, 0);
6132     }
6133
6134     pixmap = QPixmap(width, radius * 2);
6135     pixmap.fill(Qt::transparent);
6136     {
6137         QPen wavePen = pen;
6138         wavePen.setCapStyle(Qt::SquareCap);
6139
6140         // This is to protect against making the line too fat, as happens on Mac OS X
6141         // due to it having a rather thick width for the regular underline.
6142         const qreal maxPenWidth = .8 * radius;
6143         if (wavePen.widthF() > maxPenWidth)
6144             wavePen.setWidth(maxPenWidth);
6145
6146         QPainter imgPainter(&pixmap);
6147         imgPainter.setPen(wavePen);
6148         imgPainter.setRenderHint(QPainter::Antialiasing);
6149         imgPainter.translate(0, radius);
6150         imgPainter.drawPath(path);
6151     }
6152
6153     QPixmapCache::insert(key, pixmap);
6154
6155     return pixmap;
6156 }
6157
6158 static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine,
6159                                    QTextCharFormat::UnderlineStyle underlineStyle,
6160                                    QTextItem::RenderFlags flags, qreal width,
6161                                    const QTextCharFormat &charFormat)
6162 {
6163     if (underlineStyle == QTextCharFormat::NoUnderline
6164         && !(flags & (QTextItem::StrikeOut | QTextItem::Overline)))
6165         return;
6166
6167     const QPen oldPen = painter->pen();
6168     const QBrush oldBrush = painter->brush();
6169     painter->setBrush(Qt::NoBrush);
6170     QPen pen = oldPen;
6171     pen.setStyle(Qt::SolidLine);
6172     pen.setWidthF(fe->lineThickness().toReal());
6173     pen.setCapStyle(Qt::FlatCap);
6174
6175     QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
6176
6177     const qreal underlineOffset = fe->underlinePosition().toReal();
6178     // deliberately ceil the offset to avoid the underline coming too close to
6179     // the text above it.
6180     const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
6181     const qreal underlinePos = pos.y() + qCeil(underlineOffset) - aliasedCoordinateDelta;
6182
6183     if (underlineStyle == QTextCharFormat::SpellCheckUnderline) {
6184         underlineStyle = QTextCharFormat::SpellCheckUnderline; // ### Qt5 QTextCharFormat::UnderlineStyle(QApplication::style()->styleHint(QStyle::SH_SpellCheckUnderlineStyle));
6185     }
6186
6187     if (underlineStyle == QTextCharFormat::WaveUnderline) {
6188         painter->save();
6189         painter->translate(0, pos.y() + 1);
6190
6191         QColor uc = charFormat.underlineColor();
6192         if (uc.isValid())
6193             pen.setColor(uc);
6194
6195         // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms
6196         const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen);
6197         const int descent = (int) fe->descent().toReal();
6198
6199         painter->setBrushOrigin(painter->brushOrigin().x(), 0);
6200         painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave);
6201         painter->restore();
6202     } else if (underlineStyle != QTextCharFormat::NoUnderline) {
6203         QColor uc = charFormat.underlineColor();
6204         if (uc.isValid())
6205             pen.setColor(uc);
6206
6207         pen.setStyle((Qt::PenStyle)(underlineStyle));
6208         painter->setPen(pen);
6209         QLineF underline(line.x1(), underlinePos, line.x2(), underlinePos);
6210         if (textEngine)
6211             textEngine->addUnderline(painter, underline);
6212         else
6213             painter->drawLine(underline);
6214     }
6215
6216     pen.setStyle(Qt::SolidLine);
6217     pen.setColor(oldPen.color());
6218
6219     if (flags & QTextItem::StrikeOut) {
6220         QLineF strikeOutLine = line;
6221         strikeOutLine.translate(0., - fe->ascent().toReal() / 3.);
6222         painter->setPen(pen);
6223         if (textEngine)
6224             textEngine->addStrikeOut(painter, strikeOutLine);
6225         else
6226             painter->drawLine(strikeOutLine);
6227     }
6228
6229     if (flags & QTextItem::Overline) {
6230         QLineF overline = line;
6231         overline.translate(0., - fe->ascent().toReal());
6232         painter->setPen(pen);
6233         if (textEngine)
6234             textEngine->addOverline(painter, overline);
6235         else
6236             painter->drawLine(overline);
6237     }
6238
6239     painter->setPen(oldPen);
6240     painter->setBrush(oldBrush);
6241 }
6242
6243 Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
6244                                                 const QFixedPoint *positions, int glyphCount,
6245                                                 QFontEngine *fontEngine, const QFont &font,
6246                                                 const QTextCharFormat &charFormat)
6247 {
6248     if (!(font.underline() || font.strikeOut() || font.overline()))
6249         return;
6250
6251     QFixed leftMost;
6252     QFixed rightMost;
6253     QFixed baseLine;
6254     for (int i=0; i<glyphCount; ++i) {
6255         glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
6256         if (i == 0 || leftMost > positions[i].x)
6257             leftMost = positions[i].x;
6258
6259         // We don't support glyphs that do not share a common baseline. If this turns out to
6260         // be a relevant use case, then we need to find clusters of glyphs that share a baseline
6261         // and do a drawTextItemDecoration call per cluster.
6262         if (i == 0 || baseLine < positions[i].y)
6263             baseLine = positions[i].y;
6264
6265         // We use the advance rather than the actual bounds to match the algorithm in drawText()
6266         if (i == 0 || rightMost < positions[i].x + gm.xoff)
6267             rightMost = positions[i].x + gm.xoff;
6268     }
6269
6270     QFixed width = rightMost - leftMost;
6271     QTextItem::RenderFlags flags = 0;
6272
6273     if (font.underline())
6274         flags |= QTextItem::Underline;
6275     if (font.overline())
6276         flags |= QTextItem::Overline;
6277     if (font.strikeOut())
6278         flags |= QTextItem::StrikeOut;
6279
6280     drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()),
6281                            fontEngine,
6282                            0, // textEngine
6283                            font.underline() ? QTextCharFormat::SingleUnderline
6284                                             : QTextCharFormat::NoUnderline, flags,
6285                            width.toReal(), charFormat);
6286 }
6287
6288 void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti)
6289 {
6290     Q_D(QPainter);
6291
6292     d->drawTextItem(p, ti, static_cast<QTextEngine *>(0));
6293 }
6294
6295 void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine)
6296 {
6297 #ifdef QT_DEBUG_DRAW
6298     if (qt_show_painter_debug_output)
6299         printf("QPainter::drawTextItem(), pos=[%.f,%.f], str='%s'\n",
6300                p.x(), p.y(), qPrintable(_ti.text()));
6301 #endif
6302
6303     Q_Q(QPainter);
6304
6305     if (!engine)
6306         return;
6307
6308 #ifndef QT_NO_DEBUG
6309     qt_painter_thread_test(device->devType(),
6310                            "text and fonts",
6311                            QFontDatabase::supportsThreadedFontRendering());
6312 #endif
6313
6314     QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti));
6315
6316     if (!extended && state->bgMode == Qt::OpaqueMode) {
6317         QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
6318         q->fillRect(rect, state->bgBrush);
6319     }
6320
6321     if (q->pen().style() == Qt::NoPen)
6322         return;
6323
6324     const QPainter::RenderHints oldRenderHints = state->renderHints;
6325     if (!state->renderHints & QPainter::Antialiasing && state->matrix.type() >= QTransform::TxScale) {
6326         // draw antialias decoration (underline/overline/strikeout) with
6327         // transformed text
6328
6329         bool aa = true;
6330         const QTransform &m = state->matrix;
6331         if (state->matrix.type() < QTransform::TxShear) {
6332             bool isPlain90DegreeRotation =
6333                 (qFuzzyIsNull(m.m11())
6334                  && qFuzzyIsNull(m.m12() - qreal(1))
6335                  && qFuzzyIsNull(m.m21() + qreal(1))
6336                  && qFuzzyIsNull(m.m22())
6337                     )
6338                 ||
6339                 (qFuzzyIsNull(m.m11() + qreal(1))
6340                  && qFuzzyIsNull(m.m12())
6341                  && qFuzzyIsNull(m.m21())
6342                  && qFuzzyIsNull(m.m22() + qreal(1))
6343                     )
6344                 ||
6345                 (qFuzzyIsNull(m.m11())
6346                  && qFuzzyIsNull(m.m12() + qreal(1))
6347                  && qFuzzyIsNull(m.m21() - qreal(1))
6348                  && qFuzzyIsNull(m.m22())
6349                     )
6350                 ;
6351             aa = !isPlain90DegreeRotation;
6352         }
6353         if (aa)
6354             q->setRenderHint(QPainter::Antialiasing, true);
6355     }
6356
6357     if (!extended)
6358         updateState(state);
6359
6360     if (!ti.glyphs.numGlyphs) {
6361         // nothing to do
6362     } else if (ti.fontEngine->type() == QFontEngine::Multi) {
6363         QFontEngineMulti *multi = static_cast<QFontEngineMulti *>(ti.fontEngine);
6364
6365         const QGlyphLayout &glyphs = ti.glyphs;
6366         int which = glyphs.glyphs[0] >> 24;
6367
6368         qreal x = p.x();
6369         qreal y = p.y();
6370
6371         bool rtl = ti.flags & QTextItem::RightToLeft;
6372         if (rtl)
6373             x += ti.width.toReal();
6374
6375         int start = 0;
6376         int end, i;
6377         for (end = 0; end < ti.glyphs.numGlyphs; ++end) {
6378             const int e = glyphs.glyphs[end] >> 24;
6379             if (e == which)
6380                 continue;
6381
6382
6383             QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6384             ti2.width = 0;
6385             // set the high byte to zero and calc the width
6386             for (i = start; i < end; ++i) {
6387                 glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6388                 ti2.width += ti.glyphs.effectiveAdvance(i);
6389             }
6390
6391             if (rtl)
6392                 x -= ti2.width.toReal();
6393
6394             engine->drawTextItem(QPointF(x, y), ti2);
6395
6396             if (!rtl)
6397                 x += ti2.width.toReal();
6398
6399             // reset the high byte for all glyphs and advance to the next sub-string
6400             const int hi = which << 24;
6401             for (i = start; i < end; ++i) {
6402                 glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6403             }
6404
6405             // change engine
6406             start = end;
6407             which = e;
6408         }
6409
6410         QTextItemInt ti2 = ti.midItem(multi->engine(which), start, end - start);
6411         ti2.width = 0;
6412         // set the high byte to zero and calc the width
6413         for (i = start; i < end; ++i) {
6414             glyphs.glyphs[i] = glyphs.glyphs[i] & 0xffffff;
6415             ti2.width += ti.glyphs.effectiveAdvance(i);
6416         }
6417
6418         if (rtl)
6419             x -= ti2.width.toReal();
6420
6421         if (extended)
6422             extended->drawTextItem(QPointF(x, y), ti2);
6423         else
6424             engine->drawTextItem(QPointF(x,y), ti2);
6425
6426         // reset the high byte for all glyphs
6427         const int hi = which << 24;
6428         for (i = start; i < end; ++i)
6429             glyphs.glyphs[i] = hi | glyphs.glyphs[i];
6430
6431     } else {
6432         if (extended)
6433             extended->drawTextItem(p, ti);
6434         else
6435             engine->drawTextItem(p, ti);
6436     }
6437     drawTextItemDecoration(q, p, ti.fontEngine, textEngine, ti.underlineStyle,
6438                            ti.flags, ti.width.toReal(), ti.charFormat);
6439
6440     if (state->renderHints != oldRenderHints) {
6441         state->renderHints = oldRenderHints;
6442         if (extended)
6443             extended->renderHintsChanged();
6444         else
6445             state->dirtyFlags |= QPaintEngine::DirtyHints;
6446     }
6447 }
6448
6449 /*!
6450     \fn QRectF QPainter::boundingRect(const QRectF &rectangle, int flags, const QString &text)
6451
6452     Returns the bounding rectangle of the \a text as it will appear
6453     when drawn inside the given \a rectangle with the specified \a
6454     flags using the currently set font(); i.e the function tells you
6455     where the drawText() function will draw when given the same
6456     arguments.
6457
6458     If the \a text does not fit within the given \a rectangle using
6459     the specified \a flags, the function returns the required
6460     rectangle.
6461
6462     The \a flags argument is a bitwise OR of the following flags:
6463     \list
6464          \li Qt::AlignLeft
6465          \li Qt::AlignRight
6466          \li Qt::AlignHCenter
6467          \li Qt::AlignTop
6468          \li Qt::AlignBottom
6469          \li Qt::AlignVCenter
6470          \li Qt::AlignCenter
6471          \li Qt::TextSingleLine
6472          \li Qt::TextExpandTabs
6473          \li Qt::TextShowMnemonic
6474          \li Qt::TextWordWrap
6475          \li Qt::TextIncludeTrailingSpaces
6476     \endlist
6477     If several of the horizontal or several of the vertical alignment
6478     flags are set, the resulting alignment is undefined.
6479
6480     \sa drawText(), Qt::Alignment, Qt::TextFlag
6481 */
6482
6483 /*!
6484     \fn QRect QPainter::boundingRect(const QRect &rectangle, int flags,
6485                                      const QString &text)
6486
6487     \overload
6488
6489     Returns the bounding rectangle of the \a text as it will appear
6490     when drawn inside the given \a rectangle with the specified \a
6491     flags using the currently set font().
6492 */
6493
6494 /*!
6495     \fn QRect QPainter::boundingRect(int x, int y, int w, int h, int flags,
6496                                      const QString &text);
6497
6498     \overload
6499
6500     Returns the bounding rectangle of the given \a text as it will
6501     appear when drawn inside the rectangle beginning at the point
6502     (\a{x}, \a{y}) with width \a w and height \a h.
6503 */
6504 QRect QPainter::boundingRect(const QRect &rect, int flags, const QString &str)
6505 {
6506     if (str.isEmpty())
6507         return QRect(rect.x(),rect.y(), 0,0);
6508     QRect brect;
6509     drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6510     return brect;
6511 }
6512
6513
6514
6515 QRectF QPainter::boundingRect(const QRectF &rect, int flags, const QString &str)
6516 {
6517     if (str.isEmpty())
6518         return QRectF(rect.x(),rect.y(), 0,0);
6519     QRectF brect;
6520     drawText(rect, flags | Qt::TextDontPrint, str, &brect);
6521     return brect;
6522 }
6523
6524 /*!
6525     \fn QRectF QPainter::boundingRect(const QRectF &rectangle,
6526         const QString &text, const QTextOption &option)
6527
6528     \overload
6529
6530     Instead of specifying flags as a bitwise OR of the
6531     Qt::AlignmentFlag and Qt::TextFlag, this overloaded function takes
6532     an \a option argument. The QTextOption class provides a
6533     description of general rich text properties.
6534
6535     \sa QTextOption
6536 */
6537 QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextOption &o)
6538 {
6539     Q_D(QPainter);
6540
6541     if (!d->engine || text.length() == 0)
6542         return QRectF(r.x(),r.y(), 0,0);
6543
6544     QRectF br;
6545     qt_format_text(d->state->font, r, Qt::TextDontPrint, &o, text, &br, 0, 0, 0, this);
6546     return br;
6547 }
6548
6549 /*!
6550     \fn void QPainter::drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
6551
6552     Draws a tiled \a pixmap, inside the given \a rectangle with its
6553     origin at the given \a position.
6554
6555     Calling drawTiledPixmap() is similar to calling drawPixmap()
6556     several times to fill (tile) an area with a pixmap, but is
6557     potentially much more efficient depending on the underlying window
6558     system.
6559
6560     \sa drawPixmap()
6561 */
6562 void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
6563 {
6564 #ifdef QT_DEBUG_DRAW
6565     if (qt_show_painter_debug_output)
6566         printf("QPainter::drawTiledPixmap(), target=[%.2f,%.2f,%.2f,%.2f], pix=[%d,%d], offset=[%.2f,%.2f]\n",
6567                r.x(), r.y(), r.width(), r.height(),
6568                pixmap.width(), pixmap.height(),
6569                sp.x(), sp.y());
6570 #endif
6571
6572     Q_D(QPainter);
6573     if (!d->engine || pixmap.isNull() || r.isEmpty())
6574         return;
6575
6576 #ifndef QT_NO_DEBUG
6577     qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
6578 #endif
6579
6580     qreal sw = pixmap.width();
6581     qreal sh = pixmap.height();
6582     qreal sx = sp.x();
6583     qreal sy = sp.y();
6584     if (sx < 0)
6585         sx = qRound(sw) - qRound(-sx) % qRound(sw);
6586     else
6587         sx = qRound(sx) % qRound(sw);
6588     if (sy < 0)
6589         sy = qRound(sh) - -qRound(sy) % qRound(sh);
6590     else
6591         sy = qRound(sy) % qRound(sh);
6592
6593
6594     if (d->extended) {
6595         d->extended->drawTiledPixmap(r, pixmap, QPointF(sx, sy));
6596         return;
6597     }
6598
6599     if (d->state->bgMode == Qt::OpaqueMode && pixmap.isQBitmap())
6600         fillRect(r, d->state->bgBrush);
6601
6602     d->updateState(d->state);
6603     if ((d->state->matrix.type() > QTransform::TxTranslate
6604         && !d->engine->hasFeature(QPaintEngine::PixmapTransform))
6605         || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity)))
6606     {
6607         save();
6608         setBackgroundMode(Qt::TransparentMode);
6609         setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
6610         setBrush(QBrush(d->state->pen.color(), pixmap));
6611         setPen(Qt::NoPen);
6612
6613         // If there is no rotation involved we have to make sure we use the
6614         // antialiased and not the aliased coordinate system by rounding the coordinates.
6615         if (d->state->matrix.type() <= QTransform::TxScale) {
6616             const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix);
6617
6618             if (d->state->matrix.type() <= QTransform::TxTranslate) {
6619                 sx = qRound(sx);
6620                 sy = qRound(sy);
6621             }
6622
6623             setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6624             drawRect(QRectF(p, r.size()));
6625         } else {
6626             setBrushOrigin(QPointF(r.x()-sx, r.y()-sy));
6627             drawRect(r);
6628         }
6629         restore();
6630         return;
6631     }
6632
6633     qreal x = r.x();
6634     qreal y = r.y();
6635     if (d->state->matrix.type() == QTransform::TxTranslate
6636         && !d->engine->hasFeature(QPaintEngine::PixmapTransform)) {
6637         x += d->state->matrix.dx();
6638         y += d->state->matrix.dy();
6639     }
6640
6641     d->engine->drawTiledPixmap(QRectF(x, y, r.width(), r.height()), pixmap, QPointF(sx, sy));
6642 }
6643
6644 /*!
6645     \fn QPainter::drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
6646                                   const QPoint &position = QPoint())
6647     \overload
6648
6649     Draws a tiled \a pixmap, inside the given \a rectangle with its
6650     origin at the given \a position.
6651 */
6652
6653 /*!
6654     \fn void QPainter::drawTiledPixmap(int x, int y, int width, int height, const
6655          QPixmap &pixmap, int sx, int sy);
6656     \overload
6657
6658     Draws a tiled \a pixmap in the specified rectangle.
6659
6660     (\a{x}, \a{y}) specifies the top-left point in the paint device
6661     that is to be drawn onto; with the given \a width and \a
6662     height. (\a{sx}, \a{sy}) specifies the top-left point in the \a
6663     pixmap that is to be drawn; this defaults to (0, 0).
6664 */
6665
6666 #ifndef QT_NO_PICTURE
6667
6668 /*!
6669     \fn void QPainter::drawPicture(const QPointF &point, const QPicture &picture)
6670
6671     Replays the given \a picture at the given \a point.
6672
6673     The QPicture class is a paint device that records and replays
6674     QPainter commands. A picture serializes the painter commands to an
6675     IO device in a platform-independent format. Everything that can be
6676     painted on a widget or pixmap can also be stored in a picture.
6677
6678     This function does exactly the same as QPicture::play() when
6679     called with \a point = QPoint(0, 0).
6680
6681     \table 100%
6682     \row
6683     \li
6684     \snippet code/src_gui_painting_qpainter.cpp 18
6685     \endtable
6686
6687     \sa QPicture::play()
6688 */
6689
6690 void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
6691 {
6692     Q_D(QPainter);
6693
6694     if (!d->engine)
6695         return;
6696
6697     if (!d->extended)
6698         d->updateState(d->state);
6699
6700     save();
6701     translate(p);
6702     const_cast<QPicture *>(&picture)->play(this);
6703     restore();
6704 }
6705
6706 /*!
6707     \fn void QPainter::drawPicture(const QPoint &point, const QPicture &picture)
6708     \overload
6709
6710     Replays the given \a picture at the given \a point.
6711 */
6712
6713 /*!
6714     \fn void QPainter::drawPicture(int x, int y, const QPicture &picture)
6715     \overload
6716
6717     Draws the given \a picture at point (\a x, \a y).
6718 */
6719
6720 #endif // QT_NO_PICTURE
6721
6722 /*!
6723     \fn void QPainter::eraseRect(const QRectF &rectangle)
6724
6725     Erases the area inside the given \a rectangle. Equivalent to
6726     calling
6727     \snippet code/src_gui_painting_qpainter.cpp 19
6728
6729     \sa fillRect()
6730 */
6731 void QPainter::eraseRect(const QRectF &r)
6732 {
6733     Q_D(QPainter);
6734
6735     fillRect(r, d->state->bgBrush);
6736 }
6737
6738 static inline bool needsResolving(const QBrush &brush)
6739 {
6740     Qt::BrushStyle s = brush.style();
6741     return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
6742              s == Qt::ConicalGradientPattern) &&
6743             brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
6744 }
6745
6746 /*!
6747     \fn void QPainter::eraseRect(const QRect &rectangle)
6748     \overload
6749
6750     Erases the area inside the given  \a rectangle.
6751 */
6752
6753 /*!
6754     \fn void QPainter::eraseRect(int x, int y, int width, int height)
6755     \overload
6756
6757     Erases the area inside the rectangle beginning at (\a x, \a y)
6758     with the given \a width and \a height.
6759 */
6760
6761
6762 /*!
6763     \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::BrushStyle style)
6764     \overload
6765
6766     Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6767     width and \a height, using the brush \a style specified.
6768
6769     \since 4.5
6770 */
6771
6772 /*!
6773     \fn void QPainter::fillRect(const QRect &rectangle, Qt::BrushStyle style)
6774     \overload
6775
6776     Fills the given \a rectangle  with the brush \a style specified.
6777
6778     \since 4.5
6779 */
6780
6781 /*!
6782     \fn void QPainter::fillRect(const QRectF &rectangle, Qt::BrushStyle style)
6783     \overload
6784
6785     Fills the given \a rectangle  with the brush \a style specified.
6786
6787     \since 4.5
6788 */
6789
6790 /*!
6791     \fn void QPainter::fillRect(const QRectF &rectangle, const QBrush &brush)
6792
6793     Fills the given \a rectangle  with the \a brush specified.
6794
6795     Alternatively, you can specify a QColor instead of a QBrush; the
6796     QBrush constructor (taking a QColor argument) will automatically
6797     create a solid pattern brush.
6798
6799     \sa drawRect()
6800 */
6801 void QPainter::fillRect(const QRectF &r, const QBrush &brush)
6802 {
6803     Q_D(QPainter);
6804
6805     if (!d->engine)
6806         return;
6807
6808     if (d->extended) {
6809         const QGradient *g = brush.gradient();
6810         if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6811             d->extended->fillRect(r, brush);
6812             return;
6813         }
6814     }
6815
6816     QPen oldPen = pen();
6817     QBrush oldBrush = this->brush();
6818     setPen(Qt::NoPen);
6819     if (brush.style() == Qt::SolidPattern) {
6820         d->colorBrush.setStyle(Qt::SolidPattern);
6821         d->colorBrush.setColor(brush.color());
6822         setBrush(d->colorBrush);
6823     } else {
6824         setBrush(brush);
6825     }
6826
6827     drawRect(r);
6828     setBrush(oldBrush);
6829     setPen(oldPen);
6830 }
6831
6832 /*!
6833     \fn void QPainter::fillRect(const QRect &rectangle, const QBrush &brush)
6834     \overload
6835
6836     Fills the given \a rectangle with the specified \a brush.
6837 */
6838
6839 void QPainter::fillRect(const QRect &r, const QBrush &brush)
6840 {
6841     Q_D(QPainter);
6842
6843     if (!d->engine)
6844         return;
6845
6846     if (d->extended) {
6847         const QGradient *g = brush.gradient();
6848         if (!g || g->coordinateMode() == QGradient::LogicalMode) {
6849             d->extended->fillRect(r, brush);
6850             return;
6851         }
6852     }
6853
6854     QPen oldPen = pen();
6855     QBrush oldBrush = this->brush();
6856     setPen(Qt::NoPen);
6857     if (brush.style() == Qt::SolidPattern) {
6858         d->colorBrush.setStyle(Qt::SolidPattern);
6859         d->colorBrush.setColor(brush.color());
6860         setBrush(d->colorBrush);
6861     } else {
6862         setBrush(brush);
6863     }
6864
6865     drawRect(r);
6866     setBrush(oldBrush);
6867     setPen(oldPen);
6868 }
6869
6870
6871
6872 /*!
6873     \fn void QPainter::fillRect(const QRect &rectangle, const QColor &color)
6874     \overload
6875
6876     Fills the given \a rectangle with the \a color specified.
6877
6878     \since 4.5
6879 */
6880 void QPainter::fillRect(const QRect &r, const QColor &color)
6881 {
6882     Q_D(QPainter);
6883
6884     if (!d->engine)
6885         return;
6886
6887     if (d->extended) {
6888         d->extended->fillRect(r, color);
6889         return;
6890     }
6891
6892     fillRect(r, QBrush(color));
6893 }
6894
6895
6896 /*!
6897     \fn void QPainter::fillRect(const QRectF &rectangle, const QColor &color)
6898     \overload
6899
6900     Fills the given \a rectangle with the \a color specified.
6901
6902     \since 4.5
6903 */
6904 void QPainter::fillRect(const QRectF &r, const QColor &color)
6905 {
6906     Q_D(QPainter);
6907
6908     if (!d->engine)
6909         return;
6910
6911     if (d->extended) {
6912         d->extended->fillRect(r, color);
6913         return;
6914     }
6915
6916     fillRect(r, QBrush(color));
6917 }
6918
6919 /*!
6920     \fn void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
6921
6922     \overload
6923
6924     Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6925     width and \a height, using the given \a brush.
6926 */
6927
6928 /*!
6929     \fn void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)
6930
6931     \overload
6932
6933     Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6934     width and \a height, using the given \a color.
6935
6936     \since 4.5
6937 */
6938
6939 /*!
6940     \fn void QPainter::fillRect(int x, int y, int width, int height, Qt::GlobalColor color)
6941
6942     \overload
6943
6944     Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
6945     width and \a height, using the given \a color.
6946
6947     \since 4.5
6948 */
6949
6950 /*!
6951     \fn void QPainter::fillRect(const QRect &rectangle, Qt::GlobalColor color);
6952
6953     \overload
6954
6955     Fills the given \a rectangle with the specified \a color.
6956
6957     \since 4.5
6958 */
6959
6960 /*!
6961     \fn void QPainter::fillRect(const QRectF &rectangle, Qt::GlobalColor color);
6962
6963     \overload
6964
6965     Fills the given \a rectangle with the specified \a color.
6966
6967     \since 4.5
6968 */
6969
6970 /*!
6971     Sets the given render \a hint on the painter if \a on is true;
6972     otherwise clears the render hint.
6973
6974     \sa setRenderHints(), renderHints(), {QPainter#Rendering
6975     Quality}{Rendering Quality}
6976 */
6977 void QPainter::setRenderHint(RenderHint hint, bool on)
6978 {
6979 #ifdef QT_DEBUG_DRAW
6980     if (qt_show_painter_debug_output)
6981         printf("QPainter::setRenderHint: hint=%x, %s\n", hint, on ? "on" : "off");
6982 #endif
6983
6984 #ifndef QT_NO_DEBUG
6985     static const bool antialiasingDisabled = qgetenv("QT_NO_ANTIALIASING").toInt();
6986     if (hint == QPainter::Antialiasing && antialiasingDisabled)
6987         return;
6988 #endif
6989
6990     setRenderHints(hint, on);
6991 }
6992
6993 /*!
6994     \since 4.2
6995
6996     Sets the given render \a hints on the painter if \a on is true;
6997     otherwise clears the render hints.
6998
6999     \sa setRenderHint(), renderHints(), {QPainter#Rendering
7000     Quality}{Rendering Quality}
7001 */
7002
7003 void QPainter::setRenderHints(RenderHints hints, bool on)
7004 {
7005     Q_D(QPainter);
7006
7007     if (!d->engine) {
7008         qWarning("QPainter::setRenderHint: Painter must be active to set rendering hints");
7009         return;
7010     }
7011
7012     if (on)
7013         d->state->renderHints |= hints;
7014     else
7015         d->state->renderHints &= ~hints;
7016
7017     if (d->extended)
7018         d->extended->renderHintsChanged();
7019     else
7020         d->state->dirtyFlags |= QPaintEngine::DirtyHints;
7021 }
7022
7023 /*!
7024     Returns a flag that specifies the rendering hints that are set for
7025     this painter.
7026
7027     \sa testRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}
7028 */
7029 QPainter::RenderHints QPainter::renderHints() const
7030 {
7031     Q_D(const QPainter);
7032
7033     if (!d->engine)
7034         return 0;
7035
7036     return d->state->renderHints;
7037 }
7038
7039 /*!
7040     \fn bool QPainter::testRenderHint(RenderHint hint) const
7041     \since 4.3
7042
7043     Returns true if \a hint is set; otherwise returns false.
7044
7045     \sa renderHints(), setRenderHint()
7046 */
7047
7048 /*!
7049     Returns true if view transformation is enabled; otherwise returns
7050     false.
7051
7052     \sa setViewTransformEnabled(), worldTransform()
7053 */
7054
7055 bool QPainter::viewTransformEnabled() const
7056 {
7057     Q_D(const QPainter);
7058     if (!d->engine) {
7059         qWarning("QPainter::viewTransformEnabled: Painter not active");
7060         return false;
7061     }
7062     return d->state->VxF;
7063 }
7064
7065 /*!
7066     \fn void QPainter::setWindow(const QRect &rectangle)
7067
7068     Sets the painter's window to the given \a rectangle, and enables
7069     view transformations.
7070
7071     The window rectangle is part of the view transformation. The
7072     window specifies the logical coordinate system. Its sister, the
7073     viewport(), specifies the device coordinate system.
7074
7075     The default window rectangle is the same as the device's
7076     rectangle.
7077
7078     \sa window(), viewTransformEnabled(), {Coordinate
7079     System#Window-Viewport Conversion}{Window-Viewport Conversion}
7080 */
7081
7082 /*!
7083     \fn void QPainter::setWindow(int x, int y, int width, int height)
7084     \overload
7085
7086     Sets the painter's window to the rectangle beginning at (\a x, \a
7087     y) and the given \a width and \a height.
7088 */
7089
7090 void QPainter::setWindow(const QRect &r)
7091 {
7092 #ifdef QT_DEBUG_DRAW
7093     if (qt_show_painter_debug_output)
7094         printf("QPainter::setWindow(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7095 #endif
7096
7097     Q_D(QPainter);
7098
7099     if (!d->engine) {
7100         qWarning("QPainter::setWindow: Painter not active");
7101         return;
7102     }
7103
7104     d->state->wx = r.x();
7105     d->state->wy = r.y();
7106     d->state->ww = r.width();
7107     d->state->wh = r.height();
7108
7109     d->state->VxF = true;
7110     d->updateMatrix();
7111 }
7112
7113 /*!
7114     Returns the window rectangle.
7115
7116     \sa setWindow(), setViewTransformEnabled()
7117 */
7118
7119 QRect QPainter::window() const
7120 {
7121     Q_D(const QPainter);
7122     if (!d->engine) {
7123         qWarning("QPainter::window: Painter not active");
7124         return QRect();
7125     }
7126     return QRect(d->state->wx, d->state->wy, d->state->ww, d->state->wh);
7127 }
7128
7129 /*!
7130     \fn void QPainter::setViewport(const QRect &rectangle)
7131
7132     Sets the painter's viewport rectangle to the given \a rectangle,
7133     and enables view transformations.
7134
7135     The viewport rectangle is part of the view transformation. The
7136     viewport specifies the device coordinate system. Its sister, the
7137     window(), specifies the logical coordinate system.
7138
7139     The default viewport rectangle is the same as the device's
7140     rectangle.
7141
7142     \sa viewport(), viewTransformEnabled(), {Coordinate
7143     System#Window-Viewport Conversion}{Window-Viewport Conversion}
7144 */
7145
7146 /*!
7147     \fn void QPainter::setViewport(int x, int y, int width, int height)
7148     \overload
7149
7150     Sets the painter's viewport rectangle to be the rectangle
7151     beginning at (\a x, \a y) with the given \a width and \a height.
7152 */
7153
7154 void QPainter::setViewport(const QRect &r)
7155 {
7156 #ifdef QT_DEBUG_DRAW
7157     if (qt_show_painter_debug_output)
7158         printf("QPainter::setViewport(), [%d,%d,%d,%d]\n", r.x(), r.y(), r.width(), r.height());
7159 #endif
7160
7161     Q_D(QPainter);
7162
7163     if (!d->engine) {
7164         qWarning("QPainter::setViewport: Painter not active");
7165         return;
7166     }
7167
7168     d->state->vx = r.x();
7169     d->state->vy = r.y();
7170     d->state->vw = r.width();
7171     d->state->vh = r.height();
7172
7173     d->state->VxF = true;
7174     d->updateMatrix();
7175 }
7176
7177 /*!
7178     Returns the viewport rectangle.
7179
7180     \sa setViewport(), setViewTransformEnabled()
7181 */
7182
7183 QRect QPainter::viewport() const
7184 {
7185     Q_D(const QPainter);
7186     if (!d->engine) {
7187         qWarning("QPainter::viewport: Painter not active");
7188         return QRect();
7189     }
7190     return QRect(d->state->vx, d->state->vy, d->state->vw, d->state->vh);
7191 }
7192
7193 /*!
7194     Enables view transformations if \a enable is true, or disables
7195     view transformations if \a enable is false.
7196
7197     \sa viewTransformEnabled(), {Coordinate System#Window-Viewport
7198     Conversion}{Window-Viewport Conversion}
7199 */
7200
7201 void QPainter::setViewTransformEnabled(bool enable)
7202 {
7203 #ifdef QT_DEBUG_DRAW
7204     if (qt_show_painter_debug_output)
7205         printf("QPainter::setViewTransformEnabled(), enable=%d\n", enable);
7206 #endif
7207
7208     Q_D(QPainter);
7209
7210     if (!d->engine) {
7211         qWarning("QPainter::setViewTransformEnabled: Painter not active");
7212         return;
7213     }
7214
7215     if (enable == d->state->VxF)
7216         return;
7217
7218     d->state->VxF = enable;
7219     d->updateMatrix();
7220 }
7221
7222 /*!
7223     \threadsafe
7224
7225     \obsolete
7226
7227     Please use QWidget::render() instead.
7228
7229     Redirects all paint commands for the given paint \a device, to the
7230     \a replacement device. The optional point \a offset defines an
7231     offset within the source device.
7232
7233     The redirection will not be effective until the begin() function
7234     has been called; make sure to call end() for the given \a
7235     device's painter (if any) before redirecting. Call
7236     restoreRedirected() to restore the previous redirection.
7237
7238     \warning Making use of redirections in the QPainter API implies
7239     that QPainter::begin() and QPaintDevice destructors need to hold
7240     a mutex for a short period. This can impact performance. Use of
7241     QWidget::render is strongly encouraged.
7242
7243     \sa redirected(), restoreRedirected()
7244 */
7245 void QPainter::setRedirected(const QPaintDevice *device,
7246                              QPaintDevice *replacement,
7247                              const QPoint &offset)
7248 {
7249     Q_ASSERT(device != 0);
7250     Q_UNUSED(device)
7251     Q_UNUSED(replacement)
7252     Q_UNUSED(offset)
7253     qWarning("QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7254 }
7255
7256 /*!
7257     \threadsafe
7258
7259     \obsolete
7260
7261     Using QWidget::render() obsoletes the use of this function.
7262
7263     Restores the previous redirection for the given \a device after a
7264     call to setRedirected().
7265
7266     \warning Making use of redirections in the QPainter API implies
7267     that QPainter::begin() and QPaintDevice destructors need to hold
7268     a mutex for a short period. This can impact performance. Use of
7269     QWidget::render is strongly encouraged.
7270
7271     \sa redirected()
7272  */
7273 void QPainter::restoreRedirected(const QPaintDevice *device)
7274 {
7275     Q_UNUSED(device)
7276     qWarning("QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead");
7277 }
7278
7279 /*!
7280     \threadsafe
7281
7282     \obsolete
7283
7284     Using QWidget::render() obsoletes the use of this function.
7285
7286     Returns the replacement for given \a device. The optional out
7287     parameter \a offset returns the offset within the replaced device.
7288
7289     \warning Making use of redirections in the QPainter API implies
7290     that QPainter::begin() and QPaintDevice destructors need to hold
7291     a mutex for a short period. This can impact performance. Use of
7292     QWidget::render is strongly encouraged.
7293
7294     \sa setRedirected(), restoreRedirected()
7295 */
7296 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
7297 {
7298     Q_UNUSED(device)
7299     Q_UNUSED(offset)
7300     return 0;
7301 }
7302
7303 void qt_format_text(const QFont &fnt, const QRectF &_r,
7304                     int tf, const QString& str, QRectF *brect,
7305                     int tabstops, int *ta, int tabarraylen,
7306                     QPainter *painter)
7307 {
7308     qt_format_text(fnt, _r,
7309                     tf, 0, str, brect,
7310                     tabstops, ta, tabarraylen,
7311                     painter);
7312 }
7313 void qt_format_text(const QFont &fnt, const QRectF &_r,
7314                     int tf, const QTextOption *option, const QString& str, QRectF *brect,
7315                     int tabstops, int *ta, int tabarraylen,
7316                     QPainter *painter)
7317 {
7318
7319     Q_ASSERT( !((tf & ~Qt::TextDontPrint)!=0 && option!=0) ); // we either have an option or flags
7320
7321     if (option) {
7322         tf |= option->alignment();
7323         if (option->wrapMode() != QTextOption::NoWrap)
7324             tf |= Qt::TextWordWrap;
7325
7326         if (option->flags() & QTextOption::IncludeTrailingSpaces)
7327             tf |= Qt::TextIncludeTrailingSpaces;
7328
7329         if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
7330             tf |= Qt::TextExpandTabs;
7331     }
7332
7333     // we need to copy r here to protect against the case (&r == brect).
7334     QRectF r(_r);
7335
7336     bool dontclip  = (tf & Qt::TextDontClip);
7337     bool wordwrap  = (tf & Qt::TextWordWrap) || (tf & Qt::TextWrapAnywhere);
7338     bool singleline = (tf & Qt::TextSingleLine);
7339     bool showmnemonic = (tf & Qt::TextShowMnemonic);
7340     bool hidemnmemonic = (tf & Qt::TextHideMnemonic);
7341
7342     Qt::LayoutDirection layout_direction;
7343     if (tf & Qt::TextForceLeftToRight)
7344         layout_direction = Qt::LeftToRight;
7345     else if (tf & Qt::TextForceRightToLeft)
7346         layout_direction = Qt::RightToLeft;
7347     else if (option)
7348         layout_direction = option->textDirection();
7349     else if (painter)
7350         layout_direction = painter->layoutDirection();
7351     else
7352         layout_direction = Qt::LeftToRight;
7353
7354     tf = QGuiApplicationPrivate::visualAlignment(layout_direction, QFlag(tf));
7355
7356     bool isRightToLeft = layout_direction == Qt::RightToLeft;
7357     bool expandtabs = ((tf & Qt::TextExpandTabs) &&
7358                         (((tf & Qt::AlignLeft) && !isRightToLeft) ||
7359                           ((tf & Qt::AlignRight) && isRightToLeft)));
7360
7361     if (!painter)
7362         tf |= Qt::TextDontPrint;
7363
7364     uint maxUnderlines = 0;
7365     int numUnderlines = 0;
7366     QVarLengthArray<int, 32> underlinePositions(1);
7367
7368     QFontMetricsF fm(fnt);
7369     QString text = str;
7370     int offset = 0;
7371 start_lengthVariant:
7372     bool hasMoreLengthVariants = false;
7373     // compatible behaviour to the old implementation. Replace
7374     // tabs by spaces
7375     int old_offset = offset;
7376     for (; offset < text.length(); offset++) {
7377         QChar chr = text.at(offset);
7378         if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
7379             text[offset] = QLatin1Char(' ');
7380         } else if (chr == QLatin1Char('\n')) {
7381             text[offset] = QChar::LineSeparator;
7382         } else if (chr == QLatin1Char('&')) {
7383             ++maxUnderlines;
7384         } else if (chr == QLatin1Char('\t')) {
7385             if (!expandtabs) {
7386                 text[offset] = QLatin1Char(' ');
7387             } else if (!tabarraylen && !tabstops) {
7388                 tabstops = qRound(fm.width(QLatin1Char('x'))*8);
7389             }
7390         } else if (chr == QChar(ushort(0x9c))) {
7391             // string with multiple length variants
7392             hasMoreLengthVariants = true;
7393             break;
7394         }
7395     }
7396
7397     int length = offset - old_offset;
7398     if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) {
7399         underlinePositions.resize(maxUnderlines + 1);
7400
7401         QChar *cout = text.data() + old_offset;
7402         QChar *cin = cout;
7403         int l = length;
7404         while (l) {
7405             if (*cin == QLatin1Char('&')) {
7406                 ++cin;
7407                 --length;
7408                 --l;
7409                 if (!l)
7410                     break;
7411                 if (*cin != QLatin1Char('&') && !hidemnmemonic)
7412                     underlinePositions[numUnderlines++] = cout - text.data() - old_offset;
7413             }
7414             *cout = *cin;
7415             ++cout;
7416             ++cin;
7417             --l;
7418         }
7419     }
7420
7421     // no need to do extra work for underlines if we don't paint
7422     if (tf & Qt::TextDontPrint)
7423         numUnderlines = 0;
7424
7425     underlinePositions[numUnderlines] = -1;
7426     qreal height = 0;
7427     qreal width = 0;
7428
7429     QString finalText = text.mid(old_offset, length);
7430     QStackTextEngine engine(finalText, fnt);
7431     if (option) {
7432         engine.option = *option;
7433     }
7434
7435     if (engine.option.tabStop() < 0 && tabstops > 0)
7436         engine.option.setTabStop(tabstops);
7437
7438     if (engine.option.tabs().isEmpty() && ta) {
7439         QList<qreal> tabs;
7440         for (int i = 0; i < tabarraylen; i++)
7441             tabs.append(qreal(ta[i]));
7442         engine.option.setTabArray(tabs);
7443     }
7444
7445     engine.option.setTextDirection(layout_direction);
7446     if (tf & Qt::AlignJustify)
7447         engine.option.setAlignment(Qt::AlignJustify);
7448     else
7449         engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
7450
7451     if (!option && (tf & Qt::TextWrapAnywhere))
7452         engine.option.setWrapMode(QTextOption::WrapAnywhere);
7453
7454     if (tf & Qt::TextJustificationForced)
7455         engine.forceJustification = true;
7456     QTextLayout textLayout(&engine);
7457     textLayout.setCacheEnabled(true);
7458     textLayout.engine()->underlinePositions = underlinePositions.data();
7459
7460     if (finalText.isEmpty()) {
7461         height = fm.height();
7462         width = 0;
7463         tf |= Qt::TextDontPrint;
7464     } else {
7465         qreal lineWidth = 0x01000000;
7466         if (wordwrap || (tf & Qt::TextJustificationForced))
7467             lineWidth = qMax<qreal>(0, r.width());
7468         if(!wordwrap)
7469             tf |= Qt::TextIncludeTrailingSpaces;
7470         textLayout.engine()->ignoreBidi = bool(tf & Qt::TextDontPrint);
7471         textLayout.beginLayout();
7472
7473         qreal leading = fm.leading();
7474         height = -leading;
7475
7476         while (1) {
7477             QTextLine l = textLayout.createLine();
7478             if (!l.isValid())
7479                 break;
7480
7481             l.setLineWidth(lineWidth);
7482             height += leading;
7483             l.setPosition(QPointF(0., height));
7484             height += l.height();
7485             width = qMax(width, l.naturalTextWidth());
7486             if (!dontclip && !brect && height >= r.height())
7487                 break;
7488         }
7489         textLayout.endLayout();
7490     }
7491
7492     qreal yoff = 0;
7493     qreal xoff = 0;
7494     if (tf & Qt::AlignBottom) {
7495         yoff = r.height() - height;
7496     } else if (tf & Qt::AlignVCenter) {
7497         yoff = (r.height() - height)/2;
7498         if (painter) {
7499             QTransform::TransformationType type = painter->transform().type();
7500             if (type <= QTransform::TxScale) {
7501                 // do the rounding manually to work around inconsistencies
7502                 // in the paint engines when drawing on floating point offsets
7503                 const qreal scale = painter->transform().m22();
7504                 if (scale != 0)
7505                     yoff = -qRound(-yoff * scale) / scale;
7506             }
7507         }
7508     }
7509     if (tf & Qt::AlignRight) {
7510         xoff = r.width() - width;
7511     } else if (tf & Qt::AlignHCenter) {
7512         xoff = (r.width() - width)/2;
7513         if (painter) {
7514             QTransform::TransformationType type = painter->transform().type();
7515             if (type <= QTransform::TxScale) {
7516                 // do the rounding manually to work around inconsistencies
7517                 // in the paint engines when drawing on floating point offsets
7518                 const qreal scale = painter->transform().m11();
7519                 if (scale != 0)
7520                     xoff = qRound(xoff * scale) / scale;
7521             }
7522         }
7523     }
7524     QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height);
7525
7526     if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) {
7527         offset++;
7528         goto start_lengthVariant;
7529     }
7530     if (brect)
7531         *brect = bounds;
7532
7533     if (!(tf & Qt::TextDontPrint)) {
7534         bool restore = false;
7535         if (!dontclip && !r.contains(bounds)) {
7536             restore = true;
7537             painter->save();
7538             painter->setClipRect(r, Qt::IntersectClip);
7539         }
7540
7541         for (int i = 0; i < textLayout.lineCount(); i++) {
7542             QTextLine line = textLayout.lineAt(i);
7543             QTextEngine *eng = textLayout.engine();
7544             eng->enableDelayDecorations();
7545
7546             qreal advance = line.horizontalAdvance();
7547             xoff = 0;
7548             if (tf & Qt::AlignRight) {
7549                 xoff = r.width() - advance -
7550                     eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal();
7551             }
7552             else if (tf & Qt::AlignHCenter)
7553                 xoff = (r.width() - advance) / 2;
7554
7555             line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff));
7556             eng->drawDecorations(painter);
7557         }
7558
7559         if (restore) {
7560             painter->restore();
7561         }
7562     }
7563 }
7564
7565 /*!
7566     Sets the layout direction used by the painter when drawing text,
7567     to the specified \a direction.
7568
7569     The default is Qt::LayoutDirectionAuto, which will implicitly determine the
7570     direction from the text drawn.
7571
7572     \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings}
7573 */
7574 void QPainter::setLayoutDirection(Qt::LayoutDirection direction)
7575 {
7576     Q_D(QPainter);
7577     if (d->state)
7578         d->state->layoutDirection = direction;
7579 }
7580
7581 /*!
7582     Returns the layout direction used by the painter when drawing text.
7583
7584     \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings}
7585 */
7586 Qt::LayoutDirection QPainter::layoutDirection() const
7587 {
7588     Q_D(const QPainter);
7589     return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto;
7590 }
7591
7592 QPainterState::QPainterState(const QPainterState *s)
7593     : brushOrigin(s->brushOrigin), font(s->font), deviceFont(s->deviceFont),
7594       pen(s->pen), brush(s->brush), bgBrush(s->bgBrush),
7595       clipRegion(s->clipRegion), clipPath(s->clipPath),
7596       clipOperation(s->clipOperation),
7597       renderHints(s->renderHints), clipInfo(s->clipInfo),
7598       worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
7599       wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
7600       vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
7601       opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
7602       clipEnabled(s->clipEnabled), bgMode(s->bgMode), painter(s->painter),
7603       layoutDirection(s->layoutDirection),
7604       composition_mode(s->composition_mode),
7605       emulationSpecifier(s->emulationSpecifier), changeFlags(0)
7606 {
7607     dirtyFlags = s->dirtyFlags;
7608 }
7609
7610 QPainterState::QPainterState()
7611     : brushOrigin(0, 0), bgBrush(Qt::white), clipOperation(Qt::NoClip),
7612       renderHints(0),
7613       wx(0), wy(0), ww(0), wh(0), vx(0), vy(0), vw(0), vh(0),
7614       opacity(1), WxF(false), VxF(false), clipEnabled(true),
7615       bgMode(Qt::TransparentMode), painter(0),
7616       layoutDirection(QGuiApplication::layoutDirection()),
7617       composition_mode(QPainter::CompositionMode_SourceOver),
7618       emulationSpecifier(0), changeFlags(0)
7619 {
7620     dirtyFlags = 0;
7621 }
7622
7623 QPainterState::~QPainterState()
7624 {
7625 }
7626
7627 void QPainterState::init(QPainter *p) {
7628     bgBrush = Qt::white;
7629     bgMode = Qt::TransparentMode;
7630     WxF = false;
7631     VxF = false;
7632     clipEnabled = true;
7633     wx = wy = ww = wh = 0;
7634     vx = vy = vw = vh = 0;
7635     painter = p;
7636     pen = QPen();
7637     brushOrigin = QPointF(0, 0);
7638     brush = QBrush();
7639     font = deviceFont = QFont();
7640     clipRegion = QRegion();
7641     clipPath = QPainterPath();
7642     clipOperation = Qt::NoClip;
7643     clipInfo.clear();
7644     worldMatrix.reset();
7645     matrix.reset();
7646     layoutDirection = QGuiApplication::layoutDirection();
7647     composition_mode = QPainter::CompositionMode_SourceOver;
7648     emulationSpecifier = 0;
7649     dirtyFlags = 0;
7650     changeFlags = 0;
7651     renderHints = 0;
7652     opacity = 1;
7653 }
7654
7655 /*!
7656     \fn void QPainter::drawImage(const QRectF &target, const QImage &image, const QRectF &source,
7657                          Qt::ImageConversionFlags flags)
7658
7659     Draws the rectangular portion \a source of the given \a image
7660     into the \a target rectangle in the paint device.
7661
7662     \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7663
7664     If the image needs to be modified to fit in a lower-resolution
7665     result (e.g. converting from 32-bit to 8-bit), use the \a flags to
7666     specify how you would prefer this to happen.
7667
7668     \table 100%
7669     \row
7670     \li
7671     \snippet code/src_gui_painting_qpainter.cpp 20
7672     \endtable
7673
7674     \sa drawPixmap()
7675 */
7676
7677 /*!
7678     \fn void QPainter::drawImage(const QRect &target, const QImage &image, const QRect &source,
7679                                  Qt::ImageConversionFlags flags)
7680     \overload
7681
7682     Draws the rectangular portion \a source of the given \a image
7683     into the \a target rectangle in the paint device.
7684
7685     \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7686 */
7687
7688 /*!
7689     \fn void QPainter::drawImage(const QPointF &point, const QImage &image)
7690
7691     \overload
7692
7693     Draws the given \a image at the given \a point.
7694 */
7695
7696 /*!
7697     \fn void QPainter::drawImage(const QPoint &point, const QImage &image)
7698
7699     \overload
7700
7701     Draws the given \a image at the given \a point.
7702 */
7703
7704 /*!
7705     \fn void QPainter::drawImage(const QPointF &point, const QImage &image, const QRectF &source,
7706                                  Qt::ImageConversionFlags flags = 0)
7707
7708     \overload
7709
7710     Draws the rectangular portion \a source of the given \a image with
7711     its origin at the given \a point.
7712 */
7713
7714 /*!
7715     \fn void QPainter::drawImage(const QPoint &point, const QImage &image, const QRect &source,
7716                                  Qt::ImageConversionFlags flags = 0)
7717     \overload
7718
7719     Draws the rectangular portion \a source of the given \a image with
7720     its origin at the given \a point.
7721 */
7722
7723 /*!
7724     \fn void QPainter::drawImage(const QRectF &rectangle, const QImage &image)
7725
7726     \overload
7727
7728     Draws the given \a image into the given \a rectangle.
7729
7730     \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7731 */
7732
7733 /*!
7734     \fn void QPainter::drawImage(const QRect &rectangle, const QImage &image)
7735
7736     \overload
7737
7738     Draws the given \a image into the given \a rectangle.
7739
7740    \note The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
7741 */
7742
7743 /*!
7744     \fn void QPainter::drawImage(int x, int y, const QImage &image,
7745                                  int sx, int sy, int sw, int sh,
7746                                  Qt::ImageConversionFlags flags)
7747     \overload
7748
7749     Draws an image at (\a{x}, \a{y}) by copying a part of \a image into
7750     the paint device.
7751
7752     (\a{x}, \a{y}) specifies the top-left point in the paint device that is
7753     to be drawn onto. (\a{sx}, \a{sy}) specifies the top-left point in \a
7754     image that is to be drawn. The default is (0, 0).
7755
7756     (\a{sw}, \a{sh}) specifies the size of the image that is to be drawn.
7757     The default, (0, 0) (and negative) means all the way to the
7758     bottom-right of the image.
7759 */
7760
7761 /*!
7762     \class QPaintEngineState
7763     \since 4.1
7764
7765     \brief The QPaintEngineState class provides information about the
7766     active paint engine's current state.
7767     \reentrant
7768
7769     QPaintEngineState records which properties that have changed since
7770     the last time the paint engine was updated, as well as their
7771     current value.
7772
7773     Which properties that have changed can at any time be retrieved
7774     using the state() function. This function returns an instance of
7775     the QPaintEngine::DirtyFlags type which stores an OR combination
7776     of QPaintEngine::DirtyFlag values. The QPaintEngine::DirtyFlag
7777     enum defines whether a property has changed since the last update
7778     or not.
7779
7780     If a property is marked with a dirty flag, its current value can
7781     be retrieved using the corresponding get function:
7782
7783     \target GetFunction
7784
7785     \table
7786     \header \li Property Flag \li Current Property Value
7787     \row \li QPaintEngine::DirtyBackground \li backgroundBrush()
7788     \row \li QPaintEngine::DirtyBackgroundMode \li backgroundMode()
7789     \row \li QPaintEngine::DirtyBrush \li brush()
7790     \row \li QPaintEngine::DirtyBrushOrigin \li brushOrigin()
7791     \row \li QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath
7792          \li clipOperation()
7793     \row \li QPaintEngine::DirtyClipPath \li clipPath()
7794     \row \li QPaintEngine::DirtyClipRegion \li clipRegion()
7795     \row \li QPaintEngine::DirtyCompositionMode \li compositionMode()
7796     \row \li QPaintEngine::DirtyFont \li font()
7797     \row \li QPaintEngine::DirtyTransform \li transform()
7798     \row \li QPaintEngine::DirtyClipEnabled \li isClipEnabled()
7799     \row \li QPaintEngine::DirtyPen \li pen()
7800     \row \li QPaintEngine::DirtyHints \li renderHints()
7801     \endtable
7802
7803     The QPaintEngineState class also provide the painter() function
7804     which returns a pointer to the painter that is currently updating
7805     the paint engine.
7806
7807     An instance of this class, representing the current state of the
7808     active paint engine, is passed as argument to the
7809     QPaintEngine::updateState() function. The only situation in which
7810     you will have to use this class directly is when implementing your
7811     own paint engine.
7812
7813     \sa QPaintEngine
7814 */
7815
7816
7817 /*!
7818     \fn QPaintEngine::DirtyFlags QPaintEngineState::state() const
7819
7820     Returns a combination of flags identifying the set of properties
7821     that need to be updated when updating the paint engine's state
7822     (i.e. during a call to the QPaintEngine::updateState() function).
7823
7824     \sa QPaintEngine::updateState()
7825 */
7826
7827
7828 /*!
7829     Returns the pen in the current paint engine state.
7830
7831     This variable should only be used when the state() returns a
7832     combination which includes the QPaintEngine::DirtyPen flag.
7833
7834     \sa state(), QPaintEngine::updateState()
7835 */
7836
7837 QPen QPaintEngineState::pen() const
7838 {
7839     return static_cast<const QPainterState *>(this)->pen;
7840 }
7841
7842 /*!
7843     Returns the brush in the current paint engine state.
7844
7845     This variable should only be used when the state() returns a
7846     combination which includes the QPaintEngine::DirtyBrush flag.
7847
7848     \sa state(), QPaintEngine::updateState()
7849 */
7850
7851 QBrush QPaintEngineState::brush() const
7852 {
7853     return static_cast<const QPainterState *>(this)->brush;
7854 }
7855
7856 /*!
7857     Returns the brush origin in the current paint engine state.
7858
7859     This variable should only be used when the state() returns a
7860     combination which includes the QPaintEngine::DirtyBrushOrigin flag.
7861
7862     \sa state(), QPaintEngine::updateState()
7863 */
7864
7865 QPointF QPaintEngineState::brushOrigin() const
7866 {
7867     return static_cast<const QPainterState *>(this)->brushOrigin;
7868 }
7869
7870 /*!
7871     Returns the background brush in the current paint engine state.
7872
7873     This variable should only be used when the state() returns a
7874     combination which includes the QPaintEngine::DirtyBackground flag.
7875
7876     \sa state(), QPaintEngine::updateState()
7877 */
7878
7879 QBrush QPaintEngineState::backgroundBrush() const
7880 {
7881     return static_cast<const QPainterState *>(this)->bgBrush;
7882 }
7883
7884 /*!
7885     Returns the background mode in the current paint engine
7886     state.
7887
7888     This variable should only be used when the state() returns a
7889     combination which includes the QPaintEngine::DirtyBackgroundMode flag.
7890
7891     \sa state(), QPaintEngine::updateState()
7892 */
7893
7894 Qt::BGMode QPaintEngineState::backgroundMode() const
7895 {
7896     return static_cast<const QPainterState *>(this)->bgMode;
7897 }
7898
7899 /*!
7900     Returns the font in the current paint engine
7901     state.
7902
7903     This variable should only be used when the state() returns a
7904     combination which includes the QPaintEngine::DirtyFont flag.
7905
7906     \sa state(), QPaintEngine::updateState()
7907 */
7908
7909 QFont QPaintEngineState::font() const
7910 {
7911     return static_cast<const QPainterState *>(this)->font;
7912 }
7913
7914 /*!
7915     \since 4.2
7916     \obsolete
7917
7918     Returns the matrix in the current paint engine
7919     state.
7920
7921     \note It is advisable to use transform() instead of this function to
7922     preserve the properties of perspective transformations.
7923
7924     This variable should only be used when the state() returns a
7925     combination which includes the QPaintEngine::DirtyTransform flag.
7926
7927     \sa state(), QPaintEngine::updateState()
7928 */
7929
7930 QMatrix QPaintEngineState::matrix() const
7931 {
7932     const QPainterState *st = static_cast<const QPainterState *>(this);
7933
7934     return st->matrix.toAffine();
7935 }
7936
7937 /*!
7938     \since 4.3
7939
7940     Returns the matrix in the current paint engine state.
7941
7942     This variable should only be used when the state() returns a
7943     combination which includes the QPaintEngine::DirtyTransform flag.
7944
7945     \sa state(), QPaintEngine::updateState()
7946 */
7947
7948
7949 QTransform QPaintEngineState::transform() const
7950 {
7951     const QPainterState *st = static_cast<const QPainterState *>(this);
7952
7953     return st->matrix;
7954 }
7955
7956
7957 /*!
7958     Returns the clip operation in the current paint engine
7959     state.
7960
7961     This variable should only be used when the state() returns a
7962     combination which includes either the QPaintEngine::DirtyClipPath
7963     or the QPaintEngine::DirtyClipRegion flag.
7964
7965     \sa state(), QPaintEngine::updateState()
7966 */
7967
7968 Qt::ClipOperation QPaintEngineState::clipOperation() const
7969 {
7970     return static_cast<const QPainterState *>(this)->clipOperation;
7971 }
7972
7973 /*!
7974     \since 4.3
7975
7976     Returns whether the coordinate of the fill have been specified
7977     as bounded by the current rendering operation and have to be
7978     resolved (about the currently rendered primitive).
7979 */
7980 bool QPaintEngineState::brushNeedsResolving() const
7981 {
7982     const QBrush &brush = static_cast<const QPainterState *>(this)->brush;
7983     return needsResolving(brush);
7984 }
7985
7986
7987 /*!
7988     \since 4.3
7989
7990     Returns whether the coordinate of the stroke have been specified
7991     as bounded by the current rendering operation and have to be
7992     resolved (about the currently rendered primitive).
7993 */
7994 bool QPaintEngineState::penNeedsResolving() const
7995 {
7996     const QPen &pen = static_cast<const QPainterState *>(this)->pen;
7997     return needsResolving(pen.brush());
7998 }
7999
8000 /*!
8001     Returns the clip region in the current paint engine state.
8002
8003     This variable should only be used when the state() returns a
8004     combination which includes the QPaintEngine::DirtyClipRegion flag.
8005
8006     \sa state(), QPaintEngine::updateState()
8007 */
8008
8009 QRegion QPaintEngineState::clipRegion() const
8010 {
8011     return static_cast<const QPainterState *>(this)->clipRegion;
8012 }
8013
8014 /*!
8015     Returns the clip path in the current paint engine state.
8016
8017     This variable should only be used when the state() returns a
8018     combination which includes the QPaintEngine::DirtyClipPath flag.
8019
8020     \sa state(), QPaintEngine::updateState()
8021 */
8022
8023 QPainterPath QPaintEngineState::clipPath() const
8024 {
8025     return static_cast<const QPainterState *>(this)->clipPath;
8026 }
8027
8028 /*!
8029     Returns whether clipping is enabled or not in the current paint
8030     engine state.
8031
8032     This variable should only be used when the state() returns a
8033     combination which includes the QPaintEngine::DirtyClipEnabled
8034     flag.
8035
8036     \sa state(), QPaintEngine::updateState()
8037 */
8038
8039 bool QPaintEngineState::isClipEnabled() const
8040 {
8041     return static_cast<const QPainterState *>(this)->clipEnabled;
8042 }
8043
8044 /*!
8045     Returns the render hints in the current paint engine state.
8046
8047     This variable should only be used when the state() returns a
8048     combination which includes the QPaintEngine::DirtyHints
8049     flag.
8050
8051     \sa state(), QPaintEngine::updateState()
8052 */
8053
8054 QPainter::RenderHints QPaintEngineState::renderHints() const
8055 {
8056     return static_cast<const QPainterState *>(this)->renderHints;
8057 }
8058
8059 /*!
8060     Returns the composition mode in the current paint engine state.
8061
8062     This variable should only be used when the state() returns a
8063     combination which includes the QPaintEngine::DirtyCompositionMode
8064     flag.
8065
8066     \sa state(), QPaintEngine::updateState()
8067 */
8068
8069 QPainter::CompositionMode QPaintEngineState::compositionMode() const
8070 {
8071     return static_cast<const QPainterState *>(this)->composition_mode;
8072 }
8073
8074
8075 /*!
8076     Returns a pointer to the painter currently updating the paint
8077     engine.
8078 */
8079
8080 QPainter *QPaintEngineState::painter() const
8081 {
8082     return static_cast<const QPainterState *>(this)->painter;
8083 }
8084
8085
8086 /*!
8087     \since 4.2
8088
8089     Returns the opacity in the current paint engine state.
8090 */
8091
8092 qreal QPaintEngineState::opacity() const
8093 {
8094     return static_cast<const QPainterState *>(this)->opacity;
8095 }
8096
8097 /*!
8098     \since 4.3
8099
8100     Sets the world transformation matrix.
8101     If \a combine is true, the specified \a transform is combined with
8102     the current matrix; otherwise it replaces the current matrix.
8103
8104     \sa transform(), setWorldTransform()
8105 */
8106
8107 void QPainter::setTransform(const QTransform &transform, bool combine )
8108 {
8109     setWorldTransform(transform, combine);
8110 }
8111
8112 /*!
8113     Returns the world transformation matrix.
8114
8115     \sa worldTransform()
8116 */
8117
8118 const QTransform & QPainter::transform() const
8119 {
8120     return worldTransform();
8121 }
8122
8123
8124 /*!
8125     Returns the matrix that transforms from logical coordinates to
8126     device coordinates of the platform dependent paint device.
8127
8128     This function is \e only needed when using platform painting
8129     commands on the platform dependent handle (Qt::HANDLE), and the
8130     platform does not do transformations nativly.
8131
8132     The QPaintEngine::PaintEngineFeature enum can be queried to
8133     determine whether the platform performs the transformations or
8134     not.
8135
8136     \sa worldTransform(), QPaintEngine::hasFeature(),
8137 */
8138
8139 const QTransform & QPainter::deviceTransform() const
8140 {
8141     Q_D(const QPainter);
8142     if (!d->engine) {
8143         qWarning("QPainter::deviceTransform: Painter not active");
8144         return d->fakeState()->transform;
8145     }
8146     return d->state->matrix;
8147 }
8148
8149
8150 /*!
8151     Resets any transformations that were made using translate(),
8152     scale(), shear(), rotate(), setWorldTransform(), setViewport()
8153     and setWindow().
8154
8155     \sa {Coordinate Transformations}
8156 */
8157
8158 void QPainter::resetTransform()
8159 {
8160      Q_D(QPainter);
8161 #ifdef QT_DEBUG_DRAW
8162     if (qt_show_painter_debug_output)
8163         printf("QPainter::resetMatrix()\n");
8164 #endif
8165     if (!d->engine) {
8166         qWarning("QPainter::resetMatrix: Painter not active");
8167         return;
8168     }
8169
8170     d->state->wx = d->state->wy = d->state->vx = d->state->vy = 0;                        // default view origins
8171     d->state->ww = d->state->vw = d->device->metric(QPaintDevice::PdmWidth);
8172     d->state->wh = d->state->vh = d->device->metric(QPaintDevice::PdmHeight);
8173     d->state->worldMatrix = QTransform();
8174     setMatrixEnabled(false);
8175     setViewTransformEnabled(false);
8176     if (d->extended)
8177         d->extended->transformChanged();
8178     else
8179         d->state->dirtyFlags |= QPaintEngine::DirtyTransform;
8180 }
8181
8182 /*!
8183     Sets the world transformation matrix.
8184     If \a combine is true, the specified \a matrix is combined with the current matrix;
8185     otherwise it replaces the current matrix.
8186
8187     \sa transform(), setTransform()
8188 */
8189
8190 void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
8191 {
8192     Q_D(QPainter);
8193
8194     if (!d->engine) {
8195         qWarning("QPainter::setWorldTransform: Painter not active");
8196         return;
8197     }
8198
8199     if (combine)
8200         d->state->worldMatrix = matrix * d->state->worldMatrix;                        // combines
8201     else
8202         d->state->worldMatrix = matrix;                                // set new matrix
8203
8204     d->state->WxF = true;
8205     d->updateMatrix();
8206 }
8207
8208 /*!
8209     Returns the world transformation matrix.
8210 */
8211
8212 const QTransform & QPainter::worldTransform() const
8213 {
8214     Q_D(const QPainter);
8215     if (!d->engine) {
8216         qWarning("QPainter::worldTransform: Painter not active");
8217         return d->fakeState()->transform;
8218     }
8219     return d->state->worldMatrix;
8220 }
8221
8222 /*!
8223     Returns the transformation matrix combining the current
8224     window/viewport and world transformation.
8225
8226     \sa setWorldTransform(), setWindow(), setViewport()
8227 */
8228
8229 QTransform QPainter::combinedTransform() const
8230 {
8231     Q_D(const QPainter);
8232     if (!d->engine) {
8233         qWarning("QPainter::combinedTransform: Painter not active");
8234         return QTransform();
8235     }
8236     return d->state->worldMatrix * d->viewTransform();
8237 }
8238
8239 /*!
8240     \since 4.7
8241
8242     This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
8243     at multiple positions with different scale, rotation and opacity. \a
8244     fragments is an array of \a fragmentCount elements specifying the
8245     parameters used to draw each pixmap fragment. The \a hints
8246     parameter can be used to pass in drawing hints.
8247
8248     This function is potentially faster than multiple calls to drawPixmap(),
8249     since the backend can optimize state changes.
8250
8251     \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
8252 */
8253
8254 void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
8255                                    const QPixmap &pixmap, PixmapFragmentHints hints)
8256 {
8257     Q_D(QPainter);
8258
8259     if (!d->engine || pixmap.isNull())
8260         return;
8261
8262 #ifndef QT_NO_DEBUG
8263     for (int i = 0; i < fragmentCount; ++i) {
8264         QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8265                           fragments[i].width, fragments[i].height);
8266         if (!(QRectF(pixmap.rect()).contains(sourceRect)))
8267             qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle");
8268     }
8269 #endif
8270
8271     if (d->engine->isExtended()) {
8272         d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
8273     } else {
8274         qreal oldOpacity = opacity();
8275         QTransform oldTransform = transform();
8276
8277         for (int i = 0; i < fragmentCount; ++i) {
8278             QTransform transform = oldTransform;
8279             qreal xOffset = 0;
8280             qreal yOffset = 0;
8281             if (fragments[i].rotation == 0) {
8282                 xOffset = fragments[i].x;
8283                 yOffset = fragments[i].y;
8284             } else {
8285                 transform.translate(fragments[i].x, fragments[i].y);
8286                 transform.rotate(fragments[i].rotation);
8287             }
8288             setOpacity(oldOpacity * fragments[i].opacity);
8289             setTransform(transform);
8290
8291             qreal w = fragments[i].scaleX * fragments[i].width;
8292             qreal h = fragments[i].scaleY * fragments[i].height;
8293             QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
8294                               fragments[i].width, fragments[i].height);
8295             drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
8296         }
8297
8298         setOpacity(oldOpacity);
8299         setTransform(oldTransform);
8300     }
8301 }
8302
8303 /*!
8304     \since 4.7
8305     \class QPainter::PixmapFragment
8306
8307     \brief This class is used in conjunction with the
8308     QPainter::drawPixmapFragments() function to specify how a pixmap, or
8309     sub-rect of a pixmap, is drawn.
8310
8311     The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
8312     as a source rectangle within the pixmap passed into the
8313     QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
8314     width and \a height are used to calculate the target rectangle that is
8315     drawn. \a x and \a y denotes the center of the target rectangle. The \a
8316     width and \a height in the target rectangle is scaled by the \a scaleX and
8317     \a scaleY values. The resulting target rectangle is then rotated \a
8318     rotation degrees around the \a x, \a y center point.
8319
8320     \sa QPainter::drawPixmapFragments()
8321 */
8322
8323 /*!
8324     \since 4.7
8325
8326     This is a convenience function that returns a QPainter::PixmapFragment that is
8327     initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
8328     rotation, \a opacity parameters.
8329 */
8330
8331 QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
8332                                               qreal scaleX, qreal scaleY, qreal rotation,
8333                                               qreal opacity)
8334 {
8335     PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
8336                                sourceRect.height(), scaleX, scaleY, rotation, opacity};
8337     return fragment;
8338 }
8339
8340 /*!
8341     \variable QPainter::PixmapFragment::x
8342     \brief the x coordinate of center point in the target rectangle.
8343 */
8344
8345 /*!
8346     \variable QPainter::PixmapFragment::y
8347     \brief the y coordinate of the center point in the target rectangle.
8348 */
8349
8350 /*!
8351     \variable QPainter::PixmapFragment::sourceLeft
8352     \brief the left coordinate of the source rectangle.
8353 */
8354
8355 /*!
8356     \variable QPainter::PixmapFragment::sourceTop
8357     \brief the top coordinate of the source rectangle.
8358 */
8359
8360 /*!
8361     \variable QPainter::PixmapFragment::width
8362
8363     \brief the width of the source rectangle and is used to calculate the width
8364     of the target rectangle.
8365 */
8366
8367 /*!
8368     \variable QPainter::PixmapFragment::height
8369
8370     \brief the height of the source rectangle and is used to calculate the
8371     height of the target rectangle.
8372 */
8373
8374 /*!
8375     \variable QPainter::PixmapFragment::scaleX
8376     \brief the horizontal scale of the target rectangle.
8377 */
8378
8379 /*!
8380     \variable QPainter::PixmapFragment::scaleY
8381     \brief the vertical scale of the target rectangle.
8382 */
8383
8384 /*!
8385     \variable QPainter::PixmapFragment::rotation
8386
8387     \brief the rotation of the target rectangle in degrees. The target
8388     rectangle is rotated after it has been scaled.
8389 */
8390
8391 /*!
8392     \variable QPainter::PixmapFragment::opacity
8393
8394     \brief the opacity of the target rectangle, where 0.0 is fully transparent
8395     and 1.0 is fully opaque.
8396 */
8397
8398 /*!
8399     \since 4.7
8400
8401     \enum QPainter::PixmapFragmentHint
8402
8403     \value OpaqueHint Indicates that the pixmap fragments to be drawn are
8404     opaque. Opaque fragments are potentially faster to draw.
8405
8406     \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
8407 */
8408
8409 void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
8410 {
8411     p->draw_helper(path, operation);
8412 }
8413
8414 QT_END_NAMESPACE