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