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