Replace 'i < len-1 && func(i+1)' by 'i+1 < len && func(i+1)'
[profile/ivi/qtbase.git] / src / gui / painting / qpainterpath.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qpainterpath.h"
43 #include "qpainterpath_p.h"
44
45 #include <qbitmap.h>
46 #include <qdebug.h>
47 #include <qiodevice.h>
48 #include <qlist.h>
49 #include <qmatrix.h>
50 #include <qpen.h>
51 #include <qpolygon.h>
52 #include <qtextlayout.h>
53 #include <qvarlengtharray.h>
54 #include <qmath.h>
55
56 #include <private/qbezier_p.h>
57 #include <private/qfontengine_p.h>
58 #include <private/qnumeric_p.h>
59 #include <private/qobject_p.h>
60 #include <private/qpathclipper_p.h>
61 #include <private/qstroker_p.h>
62 #include <private/qtextengine_p.h>
63
64 #include <limits.h>
65
66 #if 0
67 #include <performance.h>
68 #else
69 #define PM_INIT
70 #define PM_MEASURE(x)
71 #define PM_DISPLAY
72 #endif
73
74 QT_BEGIN_NAMESPACE
75
76 struct QPainterPathPrivateDeleter
77 {
78     static inline void cleanup(QPainterPathPrivate *d)
79     {
80         // note - we must up-cast to QPainterPathData since QPainterPathPrivate
81         // has a non-virtual destructor!
82         if (d && !d->ref.deref())
83             delete static_cast<QPainterPathData *>(d);
84     }
85 };
86
87 // This value is used to determine the length of control point vectors
88 // when approximating arc segments as curves. The factor is multiplied
89 // with the radius of the circle.
90
91 // #define QPP_DEBUG
92 // #define QPP_STROKE_DEBUG
93 //#define QPP_FILLPOLYGONS_DEBUG
94
95 QPainterPath qt_stroke_dash(const QPainterPath &path, qreal *dashes, int dashCount);
96
97 void qt_find_ellipse_coords(const QRectF &r, qreal angle, qreal length,
98                             QPointF* startPoint, QPointF *endPoint)
99 {
100     if (r.isNull()) {
101         if (startPoint)
102             *startPoint = QPointF();
103         if (endPoint)
104             *endPoint = QPointF();
105         return;
106     }
107
108     qreal w2 = r.width() / 2;
109     qreal h2 = r.height() / 2;
110
111     qreal angles[2] = { angle, angle + length };
112     QPointF *points[2] = { startPoint, endPoint };
113
114     for (int i = 0; i < 2; ++i) {
115         if (!points[i])
116             continue;
117
118         qreal theta = angles[i] - 360 * qFloor(angles[i] / 360);
119         qreal t = theta / 90;
120         // truncate
121         int quadrant = int(t);
122         t -= quadrant;
123
124         t = qt_t_for_arc_angle(90 * t);
125
126         // swap x and y?
127         if (quadrant & 1)
128             t = 1 - t;
129
130         qreal a, b, c, d;
131         QBezier::coefficients(t, a, b, c, d);
132         QPointF p(a + b + c*QT_PATH_KAPPA, d + c + b*QT_PATH_KAPPA);
133
134         // left quadrants
135         if (quadrant == 1 || quadrant == 2)
136             p.rx() = -p.x();
137
138         // top quadrants
139         if (quadrant == 0 || quadrant == 1)
140             p.ry() = -p.y();
141
142         *points[i] = r.center() + QPointF(w2 * p.x(), h2 * p.y());
143     }
144 }
145
146 #ifdef QPP_DEBUG
147 static void qt_debug_path(const QPainterPath &path)
148 {
149     const char *names[] = {
150         "MoveTo     ",
151         "LineTo     ",
152         "CurveTo    ",
153         "CurveToData"
154     };
155
156     printf("\nQPainterPath: elementCount=%d\n", path.elementCount());
157     for (int i=0; i<path.elementCount(); ++i) {
158         const QPainterPath::Element &e = path.elementAt(i);
159         Q_ASSERT(e.type >= 0 && e.type <= QPainterPath::CurveToDataElement);
160         printf(" - %3d:: %s, (%.2f, %.2f)\n", i, names[e.type], e.x, e.y);
161     }
162 }
163 #endif
164
165 /*!
166     \class QPainterPath
167     \ingroup painting
168     \ingroup shared
169
170     \brief The QPainterPath class provides a container for painting operations,
171     enabling graphical shapes to be constructed and reused.
172
173     A painter path is an object composed of a number of graphical
174     building blocks, such as rectangles, ellipses, lines, and curves.
175     Building blocks can be joined in closed subpaths, for example as a
176     rectangle or an ellipse. A closed path has coinciding start and
177     end points. Or they can exist independently as unclosed subpaths,
178     such as lines and curves.
179
180     A QPainterPath object can be used for filling, outlining, and
181     clipping. To generate fillable outlines for a given painter path,
182     use the QPainterPathStroker class.  The main advantage of painter
183     paths over normal drawing operations is that complex shapes only
184     need to be created once; then they can be drawn many times using
185     only calls to the QPainter::drawPath() function.
186
187     QPainterPath provides a collection of functions that can be used
188     to obtain information about the path and its elements. In addition
189     it is possible to reverse the order of the elements using the
190     toReversed() function. There are also several functions to convert
191     this painter path object into a polygon representation.
192
193     \tableofcontents
194
195     \section1 Composing a QPainterPath
196
197     A QPainterPath object can be constructed as an empty path, with a
198     given start point, or as a copy of another QPainterPath object.
199     Once created, lines and curves can be added to the path using the
200     lineTo(), arcTo(), cubicTo() and quadTo() functions. The lines and
201     curves stretch from the currentPosition() to the position passed
202     as argument.
203
204     The currentPosition() of the QPainterPath object is always the end
205     position of the last subpath that was added (or the initial start
206     point). Use the moveTo() function to move the currentPosition()
207     without adding a component. The moveTo() function implicitly
208     starts a new subpath, and closes the previous one.  Another way of
209     starting a new subpath is to call the closeSubpath() function
210     which closes the current path by adding a line from the
211     currentPosition() back to the path's start position. Note that the
212     new path will have (0, 0) as its initial currentPosition().
213
214     QPainterPath class also provides several convenience functions to
215     add closed subpaths to a painter path: addEllipse(), addPath(),
216     addRect(), addRegion() and addText(). The addPolygon() function
217     adds an \e unclosed subpath. In fact, these functions are all
218     collections of moveTo(), lineTo() and cubicTo() operations.
219
220     In addition, a path can be added to the current path using the
221     connectPath() function. But note that this function will connect
222     the last element of the current path to the first element of given
223     one by adding a line.
224
225     Below is a code snippet that shows how a QPainterPath object can
226     be used:
227
228     \table 100%
229     \row
230     \o \inlineimage qpainterpath-construction.png
231     \o
232     \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 0
233     \endtable
234
235     The painter path is initially empty when constructed. We first add
236     a rectangle, which is a closed subpath. Then we add two bezier
237     curves which together form a closed subpath even though they are
238     not closed individually. Finally we draw the entire path. The path
239     is filled using the default fill rule, Qt::OddEvenFill. Qt
240     provides two methods for filling paths:
241
242     \table
243     \header
244     \o Qt::OddEvenFill
245     \o Qt::WindingFill
246     \row
247     \o \inlineimage qt-fillrule-oddeven.png
248     \o \inlineimage qt-fillrule-winding.png
249     \endtable
250
251     See the Qt::FillRule documentation for the definition of the
252     rules. A painter path's currently set fill rule can be retrieved
253     using the fillRule() function, and altered using the setFillRule()
254     function.
255
256     \section1 QPainterPath Information
257
258     The QPainterPath class provides a collection of functions that
259     returns information about the path and its elements.
260
261     The currentPosition() function returns the end point of the last
262     subpath that was added (or the initial start point). The
263     elementAt() function can be used to retrieve the various subpath
264     elements, the \e number of elements can be retrieved using the
265     elementCount() function, and the isEmpty() function tells whether
266     this QPainterPath object contains any elements at all.
267
268     The controlPointRect() function returns the rectangle containing
269     all the points and control points in this path. This function is
270     significantly faster to compute than the exact boundingRect()
271     which returns the bounding rectangle of this painter path with
272     floating point precision.
273
274     Finally, QPainterPath provides the contains() function which can
275     be used to determine whether a given point or rectangle is inside
276     the path, and the intersects() function which determines if any of
277     the points inside a given rectangle also are inside this path.
278
279     \section1 QPainterPath Conversion
280
281     For compatibility reasons, it might be required to simplify the
282     representation of a painter path: QPainterPath provides the
283     toFillPolygon(), toFillPolygons() and toSubpathPolygons()
284     functions which convert the painter path into a polygon. The
285     toFillPolygon() returns the painter path as one single polygon,
286     while the two latter functions return a list of polygons.
287
288     The toFillPolygons() and toSubpathPolygons() functions are
289     provided because it is usually faster to draw several small
290     polygons than to draw one large polygon, even though the total
291     number of points drawn is the same. The difference between the two
292     is the \e number of polygons they return: The toSubpathPolygons()
293     creates one polygon for each subpath regardless of intersecting
294     subpaths (i.e. overlapping bounding rectangles), while the
295     toFillPolygons() functions creates only one polygon for
296     overlapping subpaths.
297
298     The toFillPolygon() and toFillPolygons() functions first convert
299     all the subpaths to polygons, then uses a rewinding technique to
300     make sure that overlapping subpaths can be filled using the
301     correct fill rule. Note that rewinding inserts additional lines in
302     the polygon so the outline of the fill polygon does not match the
303     outline of the path.
304
305     \section1 Examples
306
307     Qt provides the \l {painting/painterpaths}{Painter Paths Example}
308     and the \l {painting/deform}{Vector Deformation example} which are
309     located in Qt's example directory.
310
311     The \l {painting/painterpaths}{Painter Paths Example} shows how
312     painter paths can be used to build complex shapes for rendering
313     and lets the user experiment with the filling and stroking.  The
314     \l {painting/deform}{Vector Deformation Example} shows how to use
315     QPainterPath to draw text.
316
317     \table
318     \header
319     \o \l {painting/painterpaths}{Painter Paths Example}
320     \o \l {painting/deform}{Vector Deformation Example}
321     \row
322     \o \inlineimage qpainterpath-example.png
323     \o \inlineimage qpainterpath-demo.png
324     \endtable
325
326     \sa QPainterPathStroker, QPainter, QRegion, {Painter Paths Example}
327 */
328
329 /*!
330     \enum QPainterPath::ElementType
331
332     This enum describes the types of elements used to connect vertices
333     in subpaths.
334
335     Note that elements added as closed subpaths using the
336     addEllipse(), addPath(), addPolygon(), addRect(), addRegion() and
337     addText() convenience functions, is actually added to the path as
338     a collection of separate elements using the moveTo(), lineTo() and
339     cubicTo() functions.
340
341     \value MoveToElement          A new subpath. See also moveTo().
342     \value LineToElement            A line. See also lineTo().
343     \value CurveToElement         A curve. See also cubicTo() and quadTo().
344     \value CurveToDataElement  The extra data required to describe a curve in
345                                                a CurveToElement element.
346
347     \sa elementAt(),  elementCount()
348 */
349
350 /*!
351     \class QPainterPath::Element
352
353     \brief The QPainterPath::Element class specifies the position and
354     type of a subpath.
355
356     Once a QPainterPath object is constructed, subpaths like lines and
357     curves can be added to the path (creating
358     QPainterPath::LineToElement and QPainterPath::CurveToElement
359     components).
360
361     The lines and curves stretch from the currentPosition() to the
362     position passed as argument. The currentPosition() of the
363     QPainterPath object is always the end position of the last subpath
364     that was added (or the initial start point). The moveTo() function
365     can be used to move the currentPosition() without adding a line or
366     curve, creating a QPainterPath::MoveToElement component.
367
368     \sa QPainterPath
369 */
370
371 /*!
372     \variable QPainterPath::Element::x
373     \brief the x coordinate of the element's position.
374
375     \sa {operator QPointF()}
376 */
377
378 /*!
379     \variable QPainterPath::Element::y
380     \brief the y coordinate of the element's position.
381
382     \sa {operator QPointF()}
383 */
384
385 /*!
386     \variable QPainterPath::Element::type
387     \brief the type of element
388
389     \sa isCurveTo(), isLineTo(), isMoveTo()
390 */
391
392 /*!
393     \fn bool QPainterPath::Element::operator==(const Element &other) const
394     \since 4.2
395
396     Returns true if this element is equal to \a other;
397     otherwise returns false.
398
399     \sa operator!=()
400 */
401
402 /*!
403     \fn bool QPainterPath::Element::operator!=(const Element &other) const
404     \since 4.2
405
406     Returns true if this element is not equal to \a other;
407     otherwise returns false.
408
409     \sa operator==()
410 */
411
412 /*!
413     \fn bool QPainterPath::Element::isCurveTo () const
414
415     Returns true if the element is a curve, otherwise returns false.
416
417     \sa type, QPainterPath::CurveToElement
418 */
419
420 /*!
421     \fn bool QPainterPath::Element::isLineTo () const
422
423     Returns true if the element is a line, otherwise returns false.
424
425     \sa type, QPainterPath::LineToElement
426 */
427
428 /*!
429     \fn bool QPainterPath::Element::isMoveTo () const
430
431     Returns true if the element is moving the current position,
432     otherwise returns false.
433
434     \sa type, QPainterPath::MoveToElement
435 */
436
437 /*!
438     \fn QPainterPath::Element::operator QPointF () const
439
440     Returns the element's position.
441
442     \sa x, y
443 */
444
445 /*!
446     \fn void QPainterPath::addEllipse(qreal x, qreal y, qreal width, qreal height)
447     \overload
448
449     Creates an ellipse within the bounding rectangle defined by its top-left
450     corner at (\a x, \a y), \a width and \a height, and adds it to the
451     painter path as a closed subpath.
452 */
453
454 /*!
455     \since 4.4
456
457     \fn void QPainterPath::addEllipse(const QPointF &center, qreal rx, qreal ry)
458     \overload
459
460     Creates an ellipse positioned at \a{center} with radii \a{rx} and \a{ry},
461     and adds it to the painter path as a closed subpath.
462 */
463
464 /*!
465     \fn void QPainterPath::addText(qreal x, qreal y, const QFont &font, const QString &text)
466     \overload
467
468     Adds the given \a text to this path as a set of closed subpaths created
469     from the \a font supplied. The subpaths are positioned so that the left
470     end of the text's baseline lies at the point specified by (\a x, \a y).
471 */
472
473 /*!
474     \fn int QPainterPath::elementCount() const
475
476     Returns the number of path elements in the painter path.
477
478     \sa ElementType, elementAt(), isEmpty()
479 */
480
481 /*!
482     \fn const QPainterPath::Element &QPainterPath::elementAt(int index) const
483
484     Returns the element at the given \a index in the painter path.
485
486     \sa ElementType, elementCount(), isEmpty()
487 */
488
489 /*!
490     \fn void QPainterPath::setElementPositionAt(int index, qreal x, qreal y)
491     \since 4.2
492
493     Sets the x and y coordinate of the element at index \a index to \a
494     x and \a y.
495 */
496
497 /*###
498     \fn QPainterPath &QPainterPath::operator +=(const QPainterPath &other)
499
500     Appends the \a other painter path to this painter path and returns a
501     reference to the result.
502 */
503
504 /*!
505     Constructs an empty QPainterPath object.
506 */
507 QPainterPath::QPainterPath()
508     : d_ptr(0)
509 {
510 }
511
512 /*!
513     \fn QPainterPath::QPainterPath(const QPainterPath &path)
514
515     Creates a QPainterPath object that is a copy of the given \a path.
516
517     \sa operator=()
518 */
519 QPainterPath::QPainterPath(const QPainterPath &other)
520     : d_ptr(other.d_ptr.data())
521 {
522     if (d_ptr)
523         d_ptr->ref.ref();
524 }
525
526 /*!
527     Creates a QPainterPath object with the given \a startPoint as its
528     current position.
529 */
530
531 QPainterPath::QPainterPath(const QPointF &startPoint)
532     : d_ptr(new QPainterPathData)
533 {
534     Element e = { startPoint.x(), startPoint.y(), MoveToElement };
535     d_func()->elements << e;
536 }
537
538 /*!
539     \internal
540 */
541 void QPainterPath::detach_helper()
542 {
543     QPainterPathPrivate *data = new QPainterPathData(*d_func());
544     d_ptr.reset(data);
545 }
546
547 /*!
548     \internal
549 */
550 void QPainterPath::ensureData_helper()
551 {
552     QPainterPathPrivate *data = new QPainterPathData;
553     data->elements.reserve(16);
554     QPainterPath::Element e = { 0, 0, QPainterPath::MoveToElement };
555     data->elements << e;
556     d_ptr.reset(data);
557     Q_ASSERT(d_ptr != 0);
558 }
559
560 /*!
561     \fn QPainterPath &QPainterPath::operator=(const QPainterPath &path)
562
563     Assigns the given \a path to this painter path.
564
565     \sa QPainterPath()
566 */
567 QPainterPath &QPainterPath::operator=(const QPainterPath &other)
568 {
569     if (other.d_func() != d_func()) {
570         QPainterPathPrivate *data = other.d_func();
571         if (data)
572             data->ref.ref();
573         d_ptr.reset(data);
574     }
575     return *this;
576 }
577
578 /*!
579     \fn void QPainterPath::swap(QPainterPath &other)
580     \since 4.8
581
582     Swaps painter path \a other with this painter path. This operation is very
583     fast and never fails.
584 */
585
586 /*!
587     Destroys this QPainterPath object.
588 */
589 QPainterPath::~QPainterPath()
590 {
591 }
592
593 /*!
594     Closes the current subpath by drawing a line to the beginning of
595     the subpath, automatically starting a new path. The current point
596     of the new path is (0, 0).
597
598     If the subpath does not contain any elements, this function does
599     nothing.
600
601     \sa moveTo(), {QPainterPath#Composing a QPainterPath}{Composing
602     a QPainterPath}
603  */
604 void QPainterPath::closeSubpath()
605 {
606 #ifdef QPP_DEBUG
607     printf("QPainterPath::closeSubpath()\n");
608 #endif
609     if (isEmpty())
610         return;
611     detach();
612
613     d_func()->close();
614 }
615
616 /*!
617     \fn void QPainterPath::moveTo(qreal x, qreal y)
618
619     \overload
620
621     Moves the current position to (\a{x}, \a{y}) and starts a new
622     subpath, implicitly closing the previous path.
623 */
624
625 /*!
626     \fn void QPainterPath::moveTo(const QPointF &point)
627
628     Moves the current point to the given \a point, implicitly starting
629     a new subpath and closing the previous one.
630
631     \sa closeSubpath(), {QPainterPath#Composing a
632     QPainterPath}{Composing a QPainterPath}
633 */
634 void QPainterPath::moveTo(const QPointF &p)
635 {
636 #ifdef QPP_DEBUG
637     printf("QPainterPath::moveTo() (%.2f,%.2f)\n", p.x(), p.y());
638 #endif
639
640     if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) {
641 #ifndef QT_NO_DEBUG
642         qWarning("QPainterPath::moveTo: Adding point where x or y is NaN or Inf, ignoring call");
643 #endif
644         return;
645     }
646
647     ensureData();
648     detach();
649
650     QPainterPathData *d = d_func();
651     Q_ASSERT(!d->elements.isEmpty());
652
653     d->require_moveTo = false;
654
655     if (d->elements.last().type == MoveToElement) {
656         d->elements.last().x = p.x();
657         d->elements.last().y = p.y();
658     } else {
659         Element elm = { p.x(), p.y(), MoveToElement };
660         d->elements.append(elm);
661     }
662     d->cStart = d->elements.size() - 1;
663 }
664
665 /*!
666     \fn void QPainterPath::lineTo(qreal x, qreal y)
667
668     \overload
669
670     Draws a line from the current position to the point (\a{x},
671     \a{y}).
672 */
673
674 /*!
675     \fn void QPainterPath::lineTo(const QPointF &endPoint)
676
677     Adds a straight line from the current position to the given \a
678     endPoint.  After the line is drawn, the current position is updated
679     to be at the end point of the line.
680
681     \sa addPolygon(), addRect(), {QPainterPath#Composing a
682     QPainterPath}{Composing a QPainterPath}
683  */
684 void QPainterPath::lineTo(const QPointF &p)
685 {
686 #ifdef QPP_DEBUG
687     printf("QPainterPath::lineTo() (%.2f,%.2f)\n", p.x(), p.y());
688 #endif
689
690     if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) {
691 #ifndef QT_NO_DEBUG
692         qWarning("QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call");
693 #endif
694         return;
695     }
696
697     ensureData();
698     detach();
699
700     QPainterPathData *d = d_func();
701     Q_ASSERT(!d->elements.isEmpty());
702     d->maybeMoveTo();
703     if (p == QPointF(d->elements.last()))
704         return;
705     Element elm = { p.x(), p.y(), LineToElement };
706     d->elements.append(elm);
707
708     d->convex = d->elements.size() == 3 || (d->elements.size() == 4 && d->isClosed());
709 }
710
711 /*!
712     \fn void QPainterPath::cubicTo(qreal c1X, qreal c1Y, qreal c2X,
713     qreal c2Y, qreal endPointX, qreal endPointY);
714
715     \overload
716
717     Adds a cubic Bezier curve between the current position and the end
718     point (\a{endPointX}, \a{endPointY}) with control points specified
719     by (\a{c1X}, \a{c1Y}) and (\a{c2X}, \a{c2Y}).
720 */
721
722 /*!
723     \fn void QPainterPath::cubicTo(const QPointF &c1, const QPointF &c2, const QPointF &endPoint)
724
725     Adds a cubic Bezier curve between the current position and the
726     given \a endPoint using the control points specified by \a c1, and
727     \a c2.
728
729     After the curve is added, the current position is updated to be at
730     the end point of the curve.
731
732     \table 100%
733     \row
734     \o \inlineimage qpainterpath-cubicto.png
735     \o
736     \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 1
737     \endtable
738
739     \sa quadTo(), {QPainterPath#Composing a QPainterPath}{Composing
740     a QPainterPath}
741 */
742 void QPainterPath::cubicTo(const QPointF &c1, const QPointF &c2, const QPointF &e)
743 {
744 #ifdef QPP_DEBUG
745     printf("QPainterPath::cubicTo() (%.2f,%.2f), (%.2f,%.2f), (%.2f,%.2f)\n",
746            c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y());
747 #endif
748
749     if (!qt_is_finite(c1.x()) || !qt_is_finite(c1.y()) || !qt_is_finite(c2.x()) || !qt_is_finite(c2.y())
750         || !qt_is_finite(e.x()) || !qt_is_finite(e.y())) {
751 #ifndef QT_NO_DEBUG
752         qWarning("QPainterPath::cubicTo: Adding point where x or y is NaN or Inf, ignoring call");
753 #endif
754         return;
755     }
756
757     ensureData();
758     detach();
759
760     QPainterPathData *d = d_func();
761     Q_ASSERT(!d->elements.isEmpty());
762
763
764     // Abort on empty curve as a stroker cannot handle this and the
765     // curve is irrelevant anyway.
766     if (d->elements.last() == c1 && c1 == c2 && c2 == e)
767         return;
768
769     d->maybeMoveTo();
770
771     Element ce1 = { c1.x(), c1.y(), CurveToElement };
772     Element ce2 = { c2.x(), c2.y(), CurveToDataElement };
773     Element ee = { e.x(), e.y(), CurveToDataElement };
774     d->elements << ce1 << ce2 << ee;
775 }
776
777 /*!
778     \fn void QPainterPath::quadTo(qreal cx, qreal cy, qreal endPointX, qreal endPointY);
779
780     \overload
781
782     Adds a quadratic Bezier curve between the current point and the endpoint
783     (\a{endPointX}, \a{endPointY}) with the control point specified by
784     (\a{cx}, \a{cy}).
785 */
786
787 /*!
788     \fn void QPainterPath::quadTo(const QPointF &c, const QPointF &endPoint)
789
790     Adds a quadratic Bezier curve between the current position and the
791     given \a endPoint with the control point specified by \a c.
792
793     After the curve is added, the current point is updated to be at
794     the end point of the curve.
795
796     \sa cubicTo(), {QPainterPath#Composing a QPainterPath}{Composing a
797     QPainterPath}
798 */
799 void QPainterPath::quadTo(const QPointF &c, const QPointF &e)
800 {
801 #ifdef QPP_DEBUG
802     printf("QPainterPath::quadTo() (%.2f,%.2f), (%.2f,%.2f)\n",
803            c.x(), c.y(), e.x(), e.y());
804 #endif
805
806     if (!qt_is_finite(c.x()) || !qt_is_finite(c.y()) || !qt_is_finite(e.x()) || !qt_is_finite(e.y())) {
807 #ifndef QT_NO_DEBUG
808         qWarning("QPainterPath::quadTo: Adding point where x or y is NaN or Inf, ignoring call");
809 #endif
810         return;
811     }
812
813     ensureData();
814     detach();
815
816     Q_D(QPainterPath);
817     Q_ASSERT(!d->elements.isEmpty());
818     const QPainterPath::Element &elm = d->elements.at(elementCount()-1);
819     QPointF prev(elm.x, elm.y);
820
821     // Abort on empty curve as a stroker cannot handle this and the
822     // curve is irrelevant anyway.
823     if (prev == c && c == e)
824         return;
825
826     QPointF c1((prev.x() + 2*c.x()) / 3, (prev.y() + 2*c.y()) / 3);
827     QPointF c2((e.x() + 2*c.x()) / 3, (e.y() + 2*c.y()) / 3);
828     cubicTo(c1, c2, e);
829 }
830
831 /*!
832     \fn void QPainterPath::arcTo(qreal x, qreal y, qreal width, qreal
833     height, qreal startAngle, qreal sweepLength)
834
835     \overload
836
837     Creates an arc that occupies the rectangle QRectF(\a x, \a y, \a
838     width, \a height), beginning at the specified \a startAngle and
839     extending \a sweepLength degrees counter-clockwise.
840
841 */
842
843 /*!
844     \fn void QPainterPath::arcTo(const QRectF &rectangle, qreal startAngle, qreal sweepLength)
845
846     Creates an arc that occupies the given \a rectangle, beginning at
847     the specified \a startAngle and extending \a sweepLength degrees
848     counter-clockwise.
849
850     Angles are specified in degrees. Clockwise arcs can be specified
851     using negative angles.
852
853     Note that this function connects the starting point of the arc to
854     the current position if they are not already connected. After the
855     arc has been added, the current position is the last point in
856     arc. To draw a line back to the first point, use the
857     closeSubpath() function.
858
859     \table 100%
860     \row
861     \o \inlineimage qpainterpath-arcto.png
862     \o
863     \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 2
864     \endtable
865
866     \sa arcMoveTo(), addEllipse(), QPainter::drawArc(), QPainter::drawPie(),
867     {QPainterPath#Composing a QPainterPath}{Composing a
868     QPainterPath}
869 */
870 void QPainterPath::arcTo(const QRectF &rect, qreal startAngle, qreal sweepLength)
871 {
872 #ifdef QPP_DEBUG
873     printf("QPainterPath::arcTo() (%.2f, %.2f, %.2f, %.2f, angle=%.2f, sweep=%.2f\n",
874            rect.x(), rect.y(), rect.width(), rect.height(), startAngle, sweepLength);
875 #endif
876
877     if ((!qt_is_finite(rect.x()) && !qt_is_finite(rect.y())) || !qt_is_finite(rect.width()) || !qt_is_finite(rect.height())
878         || !qt_is_finite(startAngle) || !qt_is_finite(sweepLength)) {
879 #ifndef QT_NO_DEBUG
880         qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN or Inf, ignoring call");
881 #endif
882         return;
883     }
884
885     if (rect.isNull())
886         return;
887
888     ensureData();
889     detach();
890
891     int point_count;
892     QPointF pts[15];
893     QPointF curve_start = qt_curves_for_arc(rect, startAngle, sweepLength, pts, &point_count);
894
895     lineTo(curve_start);
896     for (int i=0; i<point_count; i+=3) {
897         cubicTo(pts[i].x(), pts[i].y(),
898                 pts[i+1].x(), pts[i+1].y(),
899                 pts[i+2].x(), pts[i+2].y());
900     }
901
902 }
903
904
905 /*!
906     \fn void QPainterPath::arcMoveTo(qreal x, qreal y, qreal width, qreal height, qreal angle)
907     \overload
908     \since 4.2
909
910     Creates a move to that lies on the arc that occupies the
911     QRectF(\a x, \a y, \a width, \a height) at \a angle.
912 */
913
914
915 /*!
916     \fn void QPainterPath::arcMoveTo(const QRectF &rectangle, qreal angle)
917     \since 4.2
918
919     Creates a move to that lies on the arc that occupies the given \a
920     rectangle at \a angle.
921
922     Angles are specified in degrees. Clockwise arcs can be specified
923     using negative angles.
924
925     \sa moveTo(), arcTo()
926 */
927
928 void QPainterPath::arcMoveTo(const QRectF &rect, qreal angle)
929 {
930     if (rect.isNull())
931         return;
932
933     QPointF pt;
934     qt_find_ellipse_coords(rect, angle, 0, &pt, 0);
935     moveTo(pt);
936 }
937
938
939
940 /*!
941     \fn QPointF QPainterPath::currentPosition() const
942
943     Returns the current position of the path.
944 */
945 QPointF QPainterPath::currentPosition() const
946 {
947     return !d_ptr || d_func()->elements.isEmpty()
948         ? QPointF()
949         : QPointF(d_func()->elements.last().x, d_func()->elements.last().y);
950 }
951
952
953 /*!
954     \fn void QPainterPath::addRect(qreal x, qreal y, qreal width, qreal height)
955
956     \overload
957
958     Adds a rectangle at position (\a{x}, \a{y}), with the given \a
959     width and \a height, as a closed subpath.
960 */
961
962 /*!
963     \fn void QPainterPath::addRect(const QRectF &rectangle)
964
965     Adds the given \a rectangle to this path as a closed subpath.
966
967     The \a rectangle is added as a clockwise set of lines. The painter
968     path's current position after the \a rectangle has been added is
969     at the top-left corner of the rectangle.
970
971     \table 100%
972     \row
973     \o \inlineimage qpainterpath-addrectangle.png
974     \o
975     \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 3
976     \endtable
977
978     \sa addRegion(), lineTo(), {QPainterPath#Composing a
979     QPainterPath}{Composing a QPainterPath}
980 */
981 void QPainterPath::addRect(const QRectF &r)
982 {
983     if (!qt_is_finite(r.x()) || !qt_is_finite(r.y()) || !qt_is_finite(r.width()) || !qt_is_finite(r.height())) {
984 #ifndef QT_NO_DEBUG
985         qWarning("QPainterPath::addRect: Adding rect where a parameter is NaN or Inf, ignoring call");
986 #endif
987         return;
988     }
989
990     if (r.isNull())
991         return;
992
993     ensureData();
994     detach();
995
996     bool first = d_func()->elements.size() < 2;
997
998     d_func()->elements.reserve(d_func()->elements.size() + 5);
999     moveTo(r.x(), r.y());
1000
1001     Element l1 = { r.x() + r.width(), r.y(), LineToElement };
1002     Element l2 = { r.x() + r.width(), r.y() + r.height(), LineToElement };
1003     Element l3 = { r.x(), r.y() + r.height(), LineToElement };
1004     Element l4 = { r.x(), r.y(), LineToElement };
1005
1006     d_func()->elements << l1 << l2 << l3 << l4;
1007     d_func()->require_moveTo = true;
1008     d_func()->convex = first;
1009 }
1010
1011 /*!
1012     Adds the given \a polygon to the path as an (unclosed) subpath.
1013
1014     Note that the current position after the polygon has been added,
1015     is the last point in \a polygon. To draw a line back to the first
1016     point, use the closeSubpath() function.
1017
1018     \table 100%
1019     \row
1020     \o \inlineimage qpainterpath-addpolygon.png
1021     \o
1022     \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 4
1023     \endtable
1024
1025     \sa lineTo(), {QPainterPath#Composing a QPainterPath}{Composing
1026     a QPainterPath}
1027 */
1028 void QPainterPath::addPolygon(const QPolygonF &polygon)
1029 {
1030     if (polygon.isEmpty())
1031         return;
1032
1033     ensureData();
1034     detach();
1035
1036     d_func()->elements.reserve(d_func()->elements.size() + polygon.size());
1037
1038     moveTo(polygon.first());
1039     for (int i=1; i<polygon.size(); ++i) {
1040         Element elm = { polygon.at(i).x(), polygon.at(i).y(), LineToElement };
1041         d_func()->elements << elm;
1042     }
1043 }
1044
1045 /*!
1046     \fn void QPainterPath::addEllipse(const QRectF &boundingRectangle)
1047
1048     Creates an ellipse within the specified \a boundingRectangle
1049     and adds it to the painter path as a closed subpath.
1050
1051     The ellipse is composed of a clockwise curve, starting and
1052     finishing at zero degrees (the 3 o'clock position).
1053
1054     \table 100%
1055     \row
1056     \o \inlineimage qpainterpath-addellipse.png
1057     \o
1058     \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 5
1059     \endtable
1060
1061     \sa arcTo(), QPainter::drawEllipse(), {QPainterPath#Composing a
1062     QPainterPath}{Composing a QPainterPath}
1063 */
1064 void QPainterPath::addEllipse(const QRectF &boundingRect)
1065 {
1066     if (!qt_is_finite(boundingRect.x()) || !qt_is_finite(boundingRect.y())
1067         || !qt_is_finite(boundingRect.width()) || !qt_is_finite(boundingRect.height())) {
1068 #ifndef QT_NO_DEBUG
1069         qWarning("QPainterPath::addEllipse: Adding ellipse where a parameter is NaN or Inf, ignoring call");
1070 #endif
1071         return;
1072     }
1073
1074     if (boundingRect.isNull())
1075         return;
1076
1077     ensureData();
1078     detach();
1079
1080     Q_D(QPainterPath);
1081     bool first = d_func()->elements.size() < 2;
1082     d->elements.reserve(d->elements.size() + 13);
1083
1084     QPointF pts[12];
1085     int point_count;
1086     QPointF start = qt_curves_for_arc(boundingRect, 0, -360, pts, &point_count);
1087
1088     moveTo(start);
1089     cubicTo(pts[0], pts[1], pts[2]);           // 0 -> 270
1090     cubicTo(pts[3], pts[4], pts[5]);           // 270 -> 180
1091     cubicTo(pts[6], pts[7], pts[8]);           // 180 -> 90
1092     cubicTo(pts[9], pts[10], pts[11]);         // 90 - >0
1093     d_func()->require_moveTo = true;
1094
1095     d_func()->convex = first;
1096 }
1097
1098 /*!
1099     \fn void QPainterPath::addText(const QPointF &point, const QFont &font, const QString &text)
1100
1101     Adds the given \a text to this path as a set of closed subpaths
1102     created from the \a font supplied. The subpaths are positioned so
1103     that the left end of the text's baseline lies at the specified \a
1104     point.
1105
1106     \table 100%
1107     \row
1108     \o \inlineimage qpainterpath-addtext.png
1109     \o
1110     \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 6
1111     \endtable
1112
1113     \sa QPainter::drawText(), {QPainterPath#Composing a
1114     QPainterPath}{Composing a QPainterPath}
1115 */
1116 void QPainterPath::addText(const QPointF &point, const QFont &f, const QString &text)
1117 {
1118     if (text.isEmpty())
1119         return;
1120
1121     ensureData();
1122     detach();
1123
1124     QTextLayout layout(text, f);
1125     layout.setCacheEnabled(true);
1126     QTextEngine *eng = layout.engine();
1127     layout.beginLayout();
1128     QTextLine line = layout.createLine();
1129     Q_UNUSED(line);
1130     layout.endLayout();
1131     const QScriptLine &sl = eng->lines[0];
1132     if (!sl.length || !eng->layoutData)
1133         return;
1134
1135     int nItems = eng->layoutData->items.size();
1136
1137     qreal x(point.x());
1138     qreal y(point.y());
1139
1140     QVarLengthArray<int> visualOrder(nItems);
1141     QVarLengthArray<uchar> levels(nItems);
1142     for (int i = 0; i < nItems; ++i)
1143         levels[i] = eng->layoutData->items[i].analysis.bidiLevel;
1144     QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
1145
1146     for (int i = 0; i < nItems; ++i) {
1147         int item = visualOrder[i];
1148         QScriptItem &si = eng->layoutData->items[item];
1149
1150         if (si.analysis.flags < QScriptAnalysis::TabOrObject) {
1151             QGlyphLayout glyphs = eng->shapedGlyphs(&si);
1152             QFontEngine *fe = f.d->engineForScript(si.analysis.script);
1153             Q_ASSERT(fe);
1154             fe->addOutlineToPath(x, y, glyphs, this,
1155                                  si.analysis.bidiLevel % 2
1156                                  ? QTextItem::RenderFlags(QTextItem::RightToLeft)
1157                                  : QTextItem::RenderFlags(0));
1158
1159             const qreal lw = fe->lineThickness().toReal();
1160             if (f.d->underline) {
1161                 qreal pos = fe->underlinePosition().toReal();
1162                 addRect(x, y + pos, si.width.toReal(), lw);
1163             }
1164             if (f.d->overline) {
1165                 qreal pos = fe->ascent().toReal() + 1;
1166                 addRect(x, y - pos, si.width.toReal(), lw);
1167             }
1168             if (f.d->strikeOut) {
1169                 qreal pos = fe->ascent().toReal() / 3;
1170                 addRect(x, y - pos, si.width.toReal(), lw);
1171             }
1172         }
1173         x += si.width.toReal();
1174     }
1175 }
1176
1177 /*!
1178     \fn void QPainterPath::addPath(const QPainterPath &path)
1179
1180     Adds the given \a path to \e this path as a closed subpath.
1181
1182     \sa connectPath(), {QPainterPath#Composing a
1183     QPainterPath}{Composing a QPainterPath}
1184 */
1185 void QPainterPath::addPath(const QPainterPath &other)
1186 {
1187     if (other.isEmpty())
1188         return;
1189
1190     ensureData();
1191     detach();
1192
1193     QPainterPathData *d = reinterpret_cast<QPainterPathData *>(d_func());
1194     // Remove last moveto so we don't get multiple moveto's
1195     if (d->elements.last().type == MoveToElement)
1196         d->elements.remove(d->elements.size()-1);
1197
1198     // Locate where our own current subpath will start after the other path is added.
1199     int cStart = d->elements.size() + other.d_func()->cStart;
1200     d->elements += other.d_func()->elements;
1201     d->cStart = cStart;
1202
1203     d->require_moveTo = other.d_func()->isClosed();
1204 }
1205
1206
1207 /*!
1208     \fn void QPainterPath::connectPath(const QPainterPath &path)
1209
1210     Connects the given \a path to \e this path by adding a line from the
1211     last element of this path to the first element of the given path.
1212
1213     \sa addPath(), {QPainterPath#Composing a QPainterPath}{Composing
1214     a QPainterPath}
1215 */
1216 void QPainterPath::connectPath(const QPainterPath &other)
1217 {
1218     if (other.isEmpty())
1219         return;
1220
1221     ensureData();
1222     detach();
1223
1224     QPainterPathData *d = reinterpret_cast<QPainterPathData *>(d_func());
1225     // Remove last moveto so we don't get multiple moveto's
1226     if (d->elements.last().type == MoveToElement)
1227         d->elements.remove(d->elements.size()-1);
1228
1229     // Locate where our own current subpath will start after the other path is added.
1230     int cStart = d->elements.size() + other.d_func()->cStart;
1231     int first = d->elements.size();
1232     d->elements += other.d_func()->elements;
1233
1234     if (first != 0)
1235         d->elements[first].type = LineToElement;
1236
1237     // avoid duplicate points
1238     if (first > 0 && QPointF(d->elements[first]) == QPointF(d->elements[first - 1])) {
1239         d->elements.remove(first--);
1240         --cStart;
1241     }
1242
1243     if (cStart != first)
1244         d->cStart = cStart;
1245 }
1246
1247 /*!
1248     Adds the given \a region to the path by adding each rectangle in
1249     the region as a separate closed subpath.
1250
1251     \sa addRect(), {QPainterPath#Composing a QPainterPath}{Composing
1252     a QPainterPath}
1253 */
1254 void QPainterPath::addRegion(const QRegion &region)
1255 {
1256     ensureData();
1257     detach();
1258
1259     QVector<QRect> rects = region.rects();
1260     d_func()->elements.reserve(rects.size() * 5);
1261     for (int i=0; i<rects.size(); ++i)
1262         addRect(rects.at(i));
1263 }
1264
1265
1266 /*!
1267     Returns the painter path's currently set fill rule.
1268
1269     \sa setFillRule()
1270 */
1271 Qt::FillRule QPainterPath::fillRule() const
1272 {
1273     return isEmpty() ? Qt::OddEvenFill : d_func()->fillRule;
1274 }
1275
1276 /*!
1277     \fn void QPainterPath::setFillRule(Qt::FillRule fillRule)
1278
1279     Sets the fill rule of the painter path to the given \a
1280     fillRule. Qt provides two methods for filling paths:
1281
1282     \table
1283     \header
1284     \o Qt::OddEvenFill (default)
1285     \o Qt::WindingFill
1286     \row
1287     \o \inlineimage qt-fillrule-oddeven.png
1288     \o \inlineimage qt-fillrule-winding.png
1289     \endtable
1290
1291     \sa fillRule()
1292 */
1293 void QPainterPath::setFillRule(Qt::FillRule fillRule)
1294 {
1295     ensureData();
1296     if (d_func()->fillRule == fillRule)
1297         return;
1298     detach();
1299
1300     d_func()->fillRule = fillRule;
1301 }
1302
1303 #define QT_BEZIER_A(bezier, coord) 3 * (-bezier.coord##1 \
1304                                         + 3*bezier.coord##2 \
1305                                         - 3*bezier.coord##3 \
1306                                         +bezier.coord##4)
1307
1308 #define QT_BEZIER_B(bezier, coord) 6 * (bezier.coord##1 \
1309                                         - 2*bezier.coord##2 \
1310                                         + bezier.coord##3)
1311
1312 #define QT_BEZIER_C(bezier, coord) 3 * (- bezier.coord##1 \
1313                                         + bezier.coord##2)
1314
1315 #define QT_BEZIER_CHECK_T(bezier, t) \
1316     if (t >= 0 && t <= 1) { \
1317         QPointF p(b.pointAt(t)); \
1318         if (p.x() < minx) minx = p.x(); \
1319         else if (p.x() > maxx) maxx = p.x(); \
1320         if (p.y() < miny) miny = p.y(); \
1321         else if (p.y() > maxy) maxy = p.y(); \
1322     }
1323
1324
1325 static QRectF qt_painterpath_bezier_extrema(const QBezier &b)
1326 {
1327     qreal minx, miny, maxx, maxy;
1328
1329     // initialize with end points
1330     if (b.x1 < b.x4) {
1331         minx = b.x1;
1332         maxx = b.x4;
1333     } else {
1334         minx = b.x4;
1335         maxx = b.x1;
1336     }
1337     if (b.y1 < b.y4) {
1338         miny = b.y1;
1339         maxy = b.y4;
1340     } else {
1341         miny = b.y4;
1342         maxy = b.y1;
1343     }
1344
1345     // Update for the X extrema
1346     {
1347         qreal ax = QT_BEZIER_A(b, x);
1348         qreal bx = QT_BEZIER_B(b, x);
1349         qreal cx = QT_BEZIER_C(b, x);
1350         // specialcase quadratic curves to avoid div by zero
1351         if (qFuzzyIsNull(ax)) {
1352
1353             // linear curves are covered by initialization.
1354             if (!qFuzzyIsNull(bx)) {
1355                 qreal t = -cx / bx;
1356                 QT_BEZIER_CHECK_T(b, t);
1357             }
1358
1359         } else {
1360             const qreal tx = bx * bx - 4 * ax * cx;
1361
1362             if (tx >= 0) {
1363                 qreal temp = qSqrt(tx);
1364                 qreal rcp = 1 / (2 * ax);
1365                 qreal t1 = (-bx + temp) * rcp;
1366                 QT_BEZIER_CHECK_T(b, t1);
1367
1368                 qreal t2 = (-bx - temp) * rcp;
1369                 QT_BEZIER_CHECK_T(b, t2);
1370             }
1371         }
1372     }
1373
1374     // Update for the Y extrema
1375     {
1376         qreal ay = QT_BEZIER_A(b, y);
1377         qreal by = QT_BEZIER_B(b, y);
1378         qreal cy = QT_BEZIER_C(b, y);
1379
1380         // specialcase quadratic curves to avoid div by zero
1381         if (qFuzzyIsNull(ay)) {
1382
1383             // linear curves are covered by initialization.
1384             if (!qFuzzyIsNull(by)) {
1385                 qreal t = -cy / by;
1386                 QT_BEZIER_CHECK_T(b, t);
1387             }
1388
1389         } else {
1390             const qreal ty = by * by - 4 * ay * cy;
1391
1392             if (ty > 0) {
1393                 qreal temp = qSqrt(ty);
1394                 qreal rcp = 1 / (2 * ay);
1395                 qreal t1 = (-by + temp) * rcp;
1396                 QT_BEZIER_CHECK_T(b, t1);
1397
1398                 qreal t2 = (-by - temp) * rcp;
1399                 QT_BEZIER_CHECK_T(b, t2);
1400             }
1401         }
1402     }
1403     return QRectF(minx, miny, maxx - minx, maxy - miny);
1404 }
1405
1406 /*!
1407     Returns the bounding rectangle of this painter path as a rectangle with
1408     floating point precision.
1409
1410     \sa controlPointRect()
1411 */
1412 QRectF QPainterPath::boundingRect() const
1413 {
1414     if (!d_ptr)
1415         return QRectF();
1416     QPainterPathData *d = d_func();
1417
1418     if (d->dirtyBounds)
1419         computeBoundingRect();
1420     return d->bounds;
1421 }
1422
1423 /*!
1424     Returns the rectangle containing all the points and control points
1425     in this path.
1426
1427     This function is significantly faster to compute than the exact
1428     boundingRect(), and the returned rectangle is always a superset of
1429     the rectangle returned by boundingRect().
1430
1431     \sa boundingRect()
1432 */
1433 QRectF QPainterPath::controlPointRect() const
1434 {
1435     if (!d_ptr)
1436         return QRectF();
1437     QPainterPathData *d = d_func();
1438
1439     if (d->dirtyControlBounds)
1440         computeControlPointRect();
1441     return d->controlBounds;
1442 }
1443
1444
1445 /*!
1446     \fn bool QPainterPath::isEmpty() const
1447
1448     Returns true if either there are no elements in this path, or if the only
1449     element is a MoveToElement; otherwise returns false.
1450
1451     \sa elementCount()
1452 */
1453
1454 /*!
1455     Creates and returns a reversed copy of the path.
1456
1457     It is the order of the elements that is reversed: If a
1458     QPainterPath is composed by calling the moveTo(), lineTo() and
1459     cubicTo() functions in the specified order, the reversed copy is
1460     composed by calling cubicTo(), lineTo() and moveTo().
1461 */
1462 QPainterPath QPainterPath::toReversed() const
1463 {
1464     Q_D(const QPainterPath);
1465     QPainterPath rev;
1466
1467     if (isEmpty()) {
1468         rev = *this;
1469         return rev;
1470     }
1471
1472     rev.moveTo(d->elements.at(d->elements.size()-1).x, d->elements.at(d->elements.size()-1).y);
1473
1474     for (int i=d->elements.size()-1; i>=1; --i) {
1475         const QPainterPath::Element &elm = d->elements.at(i);
1476         const QPainterPath::Element &prev = d->elements.at(i-1);
1477         switch (elm.type) {
1478         case LineToElement:
1479             rev.lineTo(prev.x, prev.y);
1480             break;
1481         case MoveToElement:
1482             rev.moveTo(prev.x, prev.y);
1483             break;
1484         case CurveToDataElement:
1485             {
1486                 Q_ASSERT(i>=3);
1487                 const QPainterPath::Element &cp1 = d->elements.at(i-2);
1488                 const QPainterPath::Element &sp = d->elements.at(i-3);
1489                 Q_ASSERT(prev.type == CurveToDataElement);
1490                 Q_ASSERT(cp1.type == CurveToElement);
1491                 rev.cubicTo(prev.x, prev.y, cp1.x, cp1.y, sp.x, sp.y);
1492                 i -= 2;
1493                 break;
1494             }
1495         default:
1496             Q_ASSERT(!"qt_reversed_path");
1497             break;
1498         }
1499     }
1500     //qt_debug_path(rev);
1501     return rev;
1502 }
1503
1504 /*!
1505     Converts the path into a list of polygons using the QTransform
1506     \a matrix, and returns the list.
1507
1508     This function creates one polygon for each subpath regardless of
1509     intersecting subpaths (i.e. overlapping bounding rectangles). To
1510     make sure that such overlapping subpaths are filled correctly, use
1511     the toFillPolygons() function instead.
1512
1513     \sa toFillPolygons(), toFillPolygon(), {QPainterPath#QPainterPath
1514     Conversion}{QPainterPath Conversion}
1515 */
1516 QList<QPolygonF> QPainterPath::toSubpathPolygons(const QTransform &matrix) const
1517 {
1518
1519     Q_D(const QPainterPath);
1520     QList<QPolygonF> flatCurves;
1521     if (isEmpty())
1522         return flatCurves;
1523
1524     QPolygonF current;
1525     for (int i=0; i<elementCount(); ++i) {
1526         const QPainterPath::Element &e = d->elements.at(i);
1527         switch (e.type) {
1528         case QPainterPath::MoveToElement:
1529             if (current.size() > 1)
1530                 flatCurves += current;
1531             current.clear();
1532             current.reserve(16);
1533             current += QPointF(e.x, e.y) * matrix;
1534             break;
1535         case QPainterPath::LineToElement:
1536             current += QPointF(e.x, e.y) * matrix;
1537             break;
1538         case QPainterPath::CurveToElement: {
1539             Q_ASSERT(d->elements.at(i+1).type == QPainterPath::CurveToDataElement);
1540             Q_ASSERT(d->elements.at(i+2).type == QPainterPath::CurveToDataElement);
1541             QBezier bezier = QBezier::fromPoints(QPointF(d->elements.at(i-1).x, d->elements.at(i-1).y) * matrix,
1542                                        QPointF(e.x, e.y) * matrix,
1543                                        QPointF(d->elements.at(i+1).x, d->elements.at(i+1).y) * matrix,
1544                                                  QPointF(d->elements.at(i+2).x, d->elements.at(i+2).y) * matrix);
1545             bezier.addToPolygon(&current);
1546             i+=2;
1547             break;
1548         }
1549         case QPainterPath::CurveToDataElement:
1550             Q_ASSERT(!"QPainterPath::toSubpathPolygons(), bad element type");
1551             break;
1552         }
1553     }
1554
1555     if (current.size()>1)
1556         flatCurves += current;
1557
1558     return flatCurves;
1559 }
1560
1561 /*!
1562   \overload
1563  */
1564 QList<QPolygonF> QPainterPath::toSubpathPolygons(const QMatrix &matrix) const
1565 {
1566     return toSubpathPolygons(QTransform(matrix));
1567 }
1568
1569 /*!
1570     Converts the path into a list of polygons using the
1571     QTransform \a matrix, and returns the list.
1572
1573     The function differs from the toFillPolygon() function in that it
1574     creates several polygons. It is provided because it is usually
1575     faster to draw several small polygons than to draw one large
1576     polygon, even though the total number of points drawn is the same.
1577
1578     The toFillPolygons() function differs from the toSubpathPolygons()
1579     function in that it create only polygon for subpaths that have
1580     overlapping bounding rectangles.
1581
1582     Like the toFillPolygon() function, this function uses a rewinding
1583     technique to make sure that overlapping subpaths can be filled
1584     using the correct fill rule. Note that rewinding inserts addition
1585     lines in the polygons so the outline of the fill polygon does not
1586     match the outline of the path.
1587
1588     \sa toSubpathPolygons(), toFillPolygon(),
1589     {QPainterPath#QPainterPath Conversion}{QPainterPath Conversion}
1590 */
1591 QList<QPolygonF> QPainterPath::toFillPolygons(const QTransform &matrix) const
1592 {
1593
1594     QList<QPolygonF> polys;
1595
1596     QList<QPolygonF> subpaths = toSubpathPolygons(matrix);
1597     int count = subpaths.size();
1598
1599     if (count == 0)
1600         return polys;
1601
1602     QList<QRectF> bounds;
1603     for (int i=0; i<count; ++i)
1604         bounds += subpaths.at(i).boundingRect();
1605
1606 #ifdef QPP_FILLPOLYGONS_DEBUG
1607     printf("QPainterPath::toFillPolygons, subpathCount=%d\n", count);
1608     for (int i=0; i<bounds.size(); ++i)
1609         qDebug() << " bounds" << i << bounds.at(i);
1610 #endif
1611
1612     QVector< QList<int> > isects;
1613     isects.resize(count);
1614
1615     // find all intersections
1616     for (int j=0; j<count; ++j) {
1617         if (subpaths.at(j).size() <= 2)
1618             continue;
1619         QRectF cbounds = bounds.at(j);
1620         for (int i=0; i<count; ++i) {
1621             if (cbounds.intersects(bounds.at(i))) {
1622                 isects[j] << i;
1623             }
1624         }
1625     }
1626
1627 #ifdef QPP_FILLPOLYGONS_DEBUG
1628     printf("Intersections before flattening:\n");
1629     for (int i = 0; i < count; ++i) {
1630         printf("%d: ", i);
1631         for (int j = 0; j < isects[i].size(); ++j) {
1632             printf("%d ", isects[i][j]);
1633         }
1634         printf("\n");
1635     }
1636 #endif
1637
1638     // flatten the sets of intersections
1639     for (int i=0; i<count; ++i) {
1640         const QList<int> &current_isects = isects.at(i);
1641         for (int j=0; j<current_isects.size(); ++j) {
1642             int isect_j = current_isects.at(j);
1643             if (isect_j == i)
1644                 continue;
1645             for (int k=0; k<isects[isect_j].size(); ++k) {
1646                 int isect_k = isects[isect_j][k];
1647                 if (isect_k != i && !isects.at(i).contains(isect_k)) {
1648                     isects[i] += isect_k;
1649                 }
1650             }
1651             isects[isect_j].clear();
1652         }
1653     }
1654
1655 #ifdef QPP_FILLPOLYGONS_DEBUG
1656     printf("Intersections after flattening:\n");
1657     for (int i = 0; i < count; ++i) {
1658         printf("%d: ", i);
1659         for (int j = 0; j < isects[i].size(); ++j) {
1660             printf("%d ", isects[i][j]);
1661         }
1662         printf("\n");
1663     }
1664 #endif
1665
1666     // Join the intersected subpaths as rewinded polygons
1667     for (int i=0; i<count; ++i) {
1668         const QList<int> &subpath_list = isects[i];
1669         if (!subpath_list.isEmpty()) {
1670             QPolygonF buildUp;
1671             for (int j=0; j<subpath_list.size(); ++j) {
1672                 const QPolygonF &subpath = subpaths.at(subpath_list.at(j));
1673                 buildUp += subpath;
1674                 if (!subpath.isClosed())
1675                     buildUp += subpath.first();
1676                 if (!buildUp.isClosed())
1677                     buildUp += buildUp.first();
1678             }
1679             polys += buildUp;
1680         }
1681     }
1682
1683     return polys;
1684 }
1685
1686 /*!
1687   \overload
1688  */
1689 QList<QPolygonF> QPainterPath::toFillPolygons(const QMatrix &matrix) const
1690 {
1691     return toFillPolygons(QTransform(matrix));
1692 }
1693
1694 //same as qt_polygon_isect_line in qpolygon.cpp
1695 static void qt_painterpath_isect_line(const QPointF &p1,
1696                                       const QPointF &p2,
1697                                       const QPointF &pos,
1698                                       int *winding)
1699 {
1700     qreal x1 = p1.x();
1701     qreal y1 = p1.y();
1702     qreal x2 = p2.x();
1703     qreal y2 = p2.y();
1704     qreal y = pos.y();
1705
1706     int dir = 1;
1707
1708     if (qFuzzyCompare(y1, y2)) {
1709         // ignore horizontal lines according to scan conversion rule
1710         return;
1711     } else if (y2 < y1) {
1712         qreal x_tmp = x2; x2 = x1; x1 = x_tmp;
1713         qreal y_tmp = y2; y2 = y1; y1 = y_tmp;
1714         dir = -1;
1715     }
1716
1717     if (y >= y1 && y < y2) {
1718         qreal x = x1 + ((x2 - x1) / (y2 - y1)) * (y - y1);
1719
1720         // count up the winding number if we're
1721         if (x<=pos.x()) {
1722             (*winding) += dir;
1723         }
1724     }
1725 }
1726
1727 static void qt_painterpath_isect_curve(const QBezier &bezier, const QPointF &pt,
1728                                        int *winding, int depth = 0)
1729 {
1730     qreal y = pt.y();
1731     qreal x = pt.x();
1732     QRectF bounds = bezier.bounds();
1733
1734     // potential intersection, divide and try again...
1735     // Please note that a sideeffect of the bottom exclusion is that
1736     // horizontal lines are dropped, but this is correct according to
1737     // scan conversion rules.
1738     if (y >= bounds.y() && y < bounds.y() + bounds.height()) {
1739
1740         // hit lower limit... This is a rough threshold, but its a
1741         // tradeoff between speed and precision.
1742         const qreal lower_bound = qreal(.001);
1743         if (depth == 32 || (bounds.width() < lower_bound && bounds.height() < lower_bound)) {
1744             // We make the assumption here that the curve starts to
1745             // approximate a line after while (i.e. that it doesn't
1746             // change direction drastically during its slope)
1747             if (bezier.pt1().x() <= x) {
1748                 (*winding) += (bezier.pt4().y() > bezier.pt1().y() ? 1 : -1);
1749             }
1750             return;
1751         }
1752
1753         // split curve and try again...
1754         QBezier first_half, second_half;
1755         bezier.split(&first_half, &second_half);
1756         qt_painterpath_isect_curve(first_half, pt, winding, depth + 1);
1757         qt_painterpath_isect_curve(second_half, pt, winding, depth + 1);
1758     }
1759 }
1760
1761 /*!
1762     \fn bool QPainterPath::contains(const QPointF &point) const
1763
1764     Returns true if the given \a point is inside the path, otherwise
1765     returns false.
1766
1767     \sa intersects()
1768 */
1769 bool QPainterPath::contains(const QPointF &pt) const
1770 {
1771     if (isEmpty() || !controlPointRect().contains(pt))
1772         return false;
1773
1774     QPainterPathData *d = d_func();
1775
1776     int winding_number = 0;
1777
1778     QPointF last_pt;
1779     QPointF last_start;
1780     for (int i=0; i<d->elements.size(); ++i) {
1781         const Element &e = d->elements.at(i);
1782
1783         switch (e.type) {
1784
1785         case MoveToElement:
1786             if (i > 0) // implicitly close all paths.
1787                 qt_painterpath_isect_line(last_pt, last_start, pt, &winding_number);
1788             last_start = last_pt = e;
1789             break;
1790
1791         case LineToElement:
1792             qt_painterpath_isect_line(last_pt, e, pt, &winding_number);
1793             last_pt = e;
1794             break;
1795
1796         case CurveToElement:
1797             {
1798                 const QPainterPath::Element &cp2 = d->elements.at(++i);
1799                 const QPainterPath::Element &ep = d->elements.at(++i);
1800                 qt_painterpath_isect_curve(QBezier::fromPoints(last_pt, e, cp2, ep),
1801                                            pt, &winding_number);
1802                 last_pt = ep;
1803
1804             }
1805             break;
1806
1807         default:
1808             break;
1809         }
1810     }
1811
1812     // implicitly close last subpath
1813     if (last_pt != last_start)
1814         qt_painterpath_isect_line(last_pt, last_start, pt, &winding_number);
1815
1816     return (d->fillRule == Qt::WindingFill
1817             ? (winding_number != 0)
1818             : ((winding_number % 2) != 0));
1819 }
1820
1821 static bool qt_painterpath_isect_line_rect(qreal x1, qreal y1, qreal x2, qreal y2,
1822                                            const QRectF &rect)
1823 {
1824     qreal left = rect.left();
1825     qreal right = rect.right();
1826     qreal top = rect.top();
1827     qreal bottom = rect.bottom();
1828
1829     enum { Left, Right, Top, Bottom };
1830     // clip the lines, after cohen-sutherland, see e.g. http://www.nondot.org/~sabre/graphpro/line6.html
1831     int p1 = ((x1 < left) << Left)
1832              | ((x1 > right) << Right)
1833              | ((y1 < top) << Top)
1834              | ((y1 > bottom) << Bottom);
1835     int p2 = ((x2 < left) << Left)
1836              | ((x2 > right) << Right)
1837              | ((y2 < top) << Top)
1838              | ((y2 > bottom) << Bottom);
1839
1840     if (p1 & p2)
1841         // completely inside
1842         return false;
1843
1844     if (p1 | p2) {
1845         qreal dx = x2 - x1;
1846         qreal dy = y2 - y1;
1847
1848         // clip x coordinates
1849         if (x1 < left) {
1850             y1 += dy/dx * (left - x1);
1851             x1 = left;
1852         } else if (x1 > right) {
1853             y1 -= dy/dx * (x1 - right);
1854             x1 = right;
1855         }
1856         if (x2 < left) {
1857             y2 += dy/dx * (left - x2);
1858             x2 = left;
1859         } else if (x2 > right) {
1860             y2 -= dy/dx * (x2 - right);
1861             x2 = right;
1862         }
1863
1864         p1 = ((y1 < top) << Top)
1865              | ((y1 > bottom) << Bottom);
1866         p2 = ((y2 < top) << Top)
1867              | ((y2 > bottom) << Bottom);
1868
1869         if (p1 & p2)
1870             return false;
1871
1872         // clip y coordinates
1873         if (y1 < top) {
1874             x1 += dx/dy * (top - y1);
1875             y1 = top;
1876         } else if (y1 > bottom) {
1877             x1 -= dx/dy * (y1 - bottom);
1878             y1 = bottom;
1879         }
1880         if (y2 < top) {
1881             x2 += dx/dy * (top - y2);
1882             y2 = top;
1883         } else if (y2 > bottom) {
1884             x2 -= dx/dy * (y2 - bottom);
1885             y2 = bottom;
1886         }
1887
1888         p1 = ((x1 < left) << Left)
1889              | ((x1 > right) << Right);
1890         p2 = ((x2 < left) << Left)
1891              | ((x2 > right) << Right);
1892
1893         if (p1 & p2)
1894             return false;
1895
1896         return true;
1897     }
1898     return false;
1899 }
1900
1901 static bool qt_isect_curve_horizontal(const QBezier &bezier, qreal y, qreal x1, qreal x2, int depth = 0)
1902 {
1903     QRectF bounds = bezier.bounds();
1904
1905     if (y >= bounds.top() && y < bounds.bottom()
1906         && bounds.right() >= x1 && bounds.left() < x2) {
1907         const qreal lower_bound = qreal(.01);
1908         if (depth == 32 || (bounds.width() < lower_bound && bounds.height() < lower_bound))
1909             return true;
1910
1911         QBezier first_half, second_half;
1912         bezier.split(&first_half, &second_half);
1913         if (qt_isect_curve_horizontal(first_half, y, x1, x2, depth + 1)
1914             || qt_isect_curve_horizontal(second_half, y, x1, x2, depth + 1))
1915             return true;
1916     }
1917     return false;
1918 }
1919
1920 static bool qt_isect_curve_vertical(const QBezier &bezier, qreal x, qreal y1, qreal y2, int depth = 0)
1921 {
1922     QRectF bounds = bezier.bounds();
1923
1924     if (x >= bounds.left() && x < bounds.right()
1925         && bounds.bottom() >= y1 && bounds.top() < y2) {
1926         const qreal lower_bound = qreal(.01);
1927         if (depth == 32 || (bounds.width() < lower_bound && bounds.height() < lower_bound))
1928             return true;
1929
1930         QBezier first_half, second_half;
1931         bezier.split(&first_half, &second_half);
1932         if (qt_isect_curve_vertical(first_half, x, y1, y2, depth + 1)
1933             || qt_isect_curve_vertical(second_half, x, y1, y2, depth + 1))
1934             return true;
1935     }
1936      return false;
1937 }
1938
1939 /*
1940     Returns true if any lines or curves cross the four edges in of rect
1941 */
1942 static bool qt_painterpath_check_crossing(const QPainterPath *path, const QRectF &rect)
1943 {
1944     QPointF last_pt;
1945     QPointF last_start;
1946     for (int i=0; i<path->elementCount(); ++i) {
1947         const QPainterPath::Element &e = path->elementAt(i);
1948
1949         switch (e.type) {
1950
1951         case QPainterPath::MoveToElement:
1952             if (i > 0
1953                 && qFuzzyCompare(last_pt.x(), last_start.x())
1954                 && qFuzzyCompare(last_pt.y(), last_start.y())
1955                 && qt_painterpath_isect_line_rect(last_pt.x(), last_pt.y(),
1956                                                   last_start.x(), last_start.y(), rect))
1957                 return true;
1958             last_start = last_pt = e;
1959             break;
1960
1961         case QPainterPath::LineToElement:
1962             if (qt_painterpath_isect_line_rect(last_pt.x(), last_pt.y(), e.x, e.y, rect))
1963                 return true;
1964             last_pt = e;
1965             break;
1966
1967         case QPainterPath::CurveToElement:
1968             {
1969                 QPointF cp2 = path->elementAt(++i);
1970                 QPointF ep = path->elementAt(++i);
1971                 QBezier bezier = QBezier::fromPoints(last_pt, e, cp2, ep);
1972                 if (qt_isect_curve_horizontal(bezier, rect.top(), rect.left(), rect.right())
1973                     || qt_isect_curve_horizontal(bezier, rect.bottom(), rect.left(), rect.right())
1974                     || qt_isect_curve_vertical(bezier, rect.left(), rect.top(), rect.bottom())
1975                     || qt_isect_curve_vertical(bezier, rect.right(), rect.top(), rect.bottom()))
1976                     return true;
1977                 last_pt = ep;
1978             }
1979             break;
1980
1981         default:
1982             break;
1983         }
1984     }
1985
1986     // implicitly close last subpath
1987     if (last_pt != last_start
1988         && qt_painterpath_isect_line_rect(last_pt.x(), last_pt.y(),
1989                                           last_start.x(), last_start.y(), rect))
1990         return true;
1991
1992     return false;
1993 }
1994
1995 /*!
1996     \fn bool QPainterPath::intersects(const QRectF &rectangle) const
1997
1998     Returns true if any point in the given \a rectangle intersects the
1999     path; otherwise returns false.
2000
2001     There is an intersection if any of the lines making up the
2002     rectangle crosses a part of the path or if any part of the
2003     rectangle overlaps with any area enclosed by the path. This
2004     function respects the current fillRule to determine what is
2005     considered inside the path.
2006
2007     \sa contains()
2008 */
2009 bool QPainterPath::intersects(const QRectF &rect) const
2010 {
2011     if (elementCount() == 1 && rect.contains(elementAt(0)))
2012         return true;
2013
2014     if (isEmpty())
2015         return false;
2016
2017     QRectF cp = controlPointRect();
2018     QRectF rn = rect.normalized();
2019
2020     // QRectF::intersects returns false if one of the rects is a null rect
2021     // which would happen for a painter path consisting of a vertical or
2022     // horizontal line
2023     if (qMax(rn.left(), cp.left()) > qMin(rn.right(), cp.right())
2024         || qMax(rn.top(), cp.top()) > qMin(rn.bottom(), cp.bottom()))
2025         return false;
2026
2027     // If any path element cross the rect its bound to be an intersection
2028     if (qt_painterpath_check_crossing(this, rect))
2029         return true;
2030
2031     if (contains(rect.center()))
2032         return true;
2033
2034     Q_D(QPainterPath);
2035
2036     // Check if the rectangle surounds any subpath...
2037     for (int i=0; i<d->elements.size(); ++i) {
2038         const Element &e = d->elements.at(i);
2039         if (e.type == QPainterPath::MoveToElement && rect.contains(e))
2040             return true;
2041     }
2042
2043     return false;
2044 }
2045
2046 /*!
2047     Translates all elements in the path by (\a{dx}, \a{dy}).
2048
2049     \since 4.6
2050     \sa translated()
2051 */
2052 void QPainterPath::translate(qreal dx, qreal dy)
2053 {
2054     if (!d_ptr || (dx == 0 && dy == 0))
2055         return;
2056
2057     int elementsLeft = d_ptr->elements.size();
2058     if (elementsLeft <= 0)
2059         return;
2060
2061     detach();
2062     QPainterPath::Element *element = d_func()->elements.data();
2063     Q_ASSERT(element);
2064     while (elementsLeft--) {
2065         element->x += dx;
2066         element->y += dy;
2067         ++element;
2068     }
2069 }
2070
2071 /*!
2072     \fn void QPainterPath::translate(const QPointF &offset)
2073     \overload
2074     \since 4.6
2075
2076     Translates all elements in the path by the given \a offset.
2077
2078     \sa translated()
2079 */
2080
2081 /*!
2082     Returns a copy of the path that is translated by (\a{dx}, \a{dy}).
2083
2084     \since 4.6
2085     \sa translate()
2086 */
2087 QPainterPath QPainterPath::translated(qreal dx, qreal dy) const
2088 {
2089     QPainterPath copy(*this);
2090     copy.translate(dx, dy);
2091     return copy;
2092 }
2093
2094 /*!
2095     \fn QPainterPath QPainterPath::translated(const QPointF &offset) const;
2096     \overload
2097     \since 4.6
2098
2099     Returns a copy of the path that is translated by the given \a offset.
2100
2101     \sa translate()
2102 */
2103
2104 /*!
2105     \fn bool QPainterPath::contains(const QRectF &rectangle) const
2106
2107     Returns true if the given \a rectangle is inside the path,
2108     otherwise returns false.
2109 */
2110 bool QPainterPath::contains(const QRectF &rect) const
2111 {
2112     Q_D(QPainterPath);
2113
2114     // the path is empty or the control point rect doesn't completely
2115     // cover the rectangle we abort stratight away.
2116     if (isEmpty() || !controlPointRect().contains(rect))
2117         return false;
2118
2119     // if there are intersections, chances are that the rect is not
2120     // contained, except if we have winding rule, in which case it
2121     // still might.
2122     if (qt_painterpath_check_crossing(this, rect)) {
2123         if (fillRule() == Qt::OddEvenFill) {
2124             return false;
2125         } else {
2126             // Do some wague sampling in the winding case. This is not
2127             // precise but it should mostly be good enough.
2128             if (!contains(rect.topLeft()) ||
2129                 !contains(rect.topRight()) ||
2130                 !contains(rect.bottomRight()) ||
2131                 !contains(rect.bottomLeft()))
2132                 return false;
2133         }
2134     }
2135
2136     // If there exists a point inside that is not part of the path its
2137     // because: rectangle lies completely outside path or a subpath
2138     // excludes parts of the rectangle. Both cases mean that the rect
2139     // is not contained
2140     if (!contains(rect.center()))
2141         return false;
2142
2143     // If there are any subpaths inside this rectangle we need to
2144     // check if they are still contained as a result of the fill
2145     // rule. This can only be the case for WindingFill though. For
2146     // OddEvenFill the rect will never be contained if it surrounds a
2147     // subpath. (the case where two subpaths are completely identical
2148     // can be argued but we choose to neglect it).
2149     for (int i=0; i<d->elements.size(); ++i) {
2150         const Element &e = d->elements.at(i);
2151         if (e.type == QPainterPath::MoveToElement && rect.contains(e)) {
2152             if (fillRule() == Qt::OddEvenFill)
2153                 return false;
2154
2155             bool stop = false;
2156             for (; !stop && i<d->elements.size(); ++i) {
2157                 const Element &el = d->elements.at(i);
2158                 switch (el.type) {
2159                 case MoveToElement:
2160                     stop = true;
2161                     break;
2162                 case LineToElement:
2163                     if (!contains(el))
2164                         return false;
2165                     break;
2166                 case CurveToElement:
2167                     if (!contains(d->elements.at(i+2)))
2168                         return false;
2169                     i += 2;
2170                     break;
2171                 default:
2172                     break;
2173                 }
2174             }
2175
2176             // compensate for the last ++i in the inner for
2177             --i;
2178         }
2179     }
2180
2181     return true;
2182 }
2183
2184 static inline bool epsilonCompare(const QPointF &a, const QPointF &b, const QSizeF &epsilon)
2185 {
2186     return qAbs(a.x() - b.x()) <= epsilon.width()
2187         && qAbs(a.y() - b.y()) <= epsilon.height();
2188 }
2189
2190 /*!
2191     Returns true if this painterpath is equal to the given \a path.
2192
2193     Note that comparing paths may involve a per element comparison
2194     which can be slow for complex paths.
2195
2196     \sa operator!=()
2197 */
2198
2199 bool QPainterPath::operator==(const QPainterPath &path) const
2200 {
2201     QPainterPathData *d = reinterpret_cast<QPainterPathData *>(d_func());
2202     if (path.d_func() == d)
2203         return true;
2204     else if (!d || !path.d_func())
2205         return false;
2206     else if (d->fillRule != path.d_func()->fillRule)
2207         return false;
2208     else if (d->elements.size() != path.d_func()->elements.size())
2209         return false;
2210
2211     const qreal qt_epsilon = sizeof(qreal) == sizeof(double) ? 1e-12 : qreal(1e-5);
2212
2213     QSizeF epsilon = boundingRect().size();
2214     epsilon.rwidth() *= qt_epsilon;
2215     epsilon.rheight() *= qt_epsilon;
2216
2217     for (int i = 0; i < d->elements.size(); ++i)
2218         if (d->elements.at(i).type != path.d_func()->elements.at(i).type
2219             || !epsilonCompare(d->elements.at(i), path.d_func()->elements.at(i), epsilon))
2220             return false;
2221
2222     return true;
2223 }
2224
2225 /*!
2226     Returns true if this painter path differs from the given \a path.
2227
2228     Note that comparing paths may involve a per element comparison
2229     which can be slow for complex paths.
2230
2231     \sa operator==()
2232 */
2233
2234 bool QPainterPath::operator!=(const QPainterPath &path) const
2235 {
2236     return !(*this==path);
2237 }
2238
2239 /*!
2240     \since 4.5
2241
2242     Returns the intersection of this path and the \a other path.
2243
2244     \sa intersected(), operator&=(), united(), operator|()
2245 */
2246 QPainterPath QPainterPath::operator&(const QPainterPath &other) const
2247 {
2248     return intersected(other);
2249 }
2250
2251 /*!
2252     \since 4.5
2253
2254     Returns the union of this path and the \a other path.
2255
2256     \sa united(), operator|=(), intersected(), operator&()
2257 */
2258 QPainterPath QPainterPath::operator|(const QPainterPath &other) const
2259 {
2260     return united(other);
2261 }
2262
2263 /*!
2264     \since 4.5
2265
2266     Returns the union of this path and the \a other path. This function is equivalent
2267     to operator|().
2268
2269     \sa united(), operator+=(), operator-()
2270 */
2271 QPainterPath QPainterPath::operator+(const QPainterPath &other) const
2272 {
2273     return united(other);
2274 }
2275
2276 /*!
2277     \since 4.5
2278
2279     Subtracts the \a other path from a copy of this path, and returns the copy.
2280
2281     \sa subtracted(), operator-=(), operator+()
2282 */
2283 QPainterPath QPainterPath::operator-(const QPainterPath &other) const
2284 {
2285     return subtracted(other);
2286 }
2287
2288 /*!
2289     \since 4.5
2290
2291     Intersects this path with \a other and returns a reference to this path.
2292
2293     \sa intersected(), operator&(), operator|=()
2294 */
2295 QPainterPath &QPainterPath::operator&=(const QPainterPath &other)
2296 {
2297     return *this = (*this & other);
2298 }
2299
2300 /*!
2301     \since 4.5
2302
2303     Unites this path with \a other and returns a reference to this path.
2304
2305     \sa united(), operator|(), operator&=()
2306 */
2307 QPainterPath &QPainterPath::operator|=(const QPainterPath &other)
2308 {
2309     return *this = (*this | other);
2310 }
2311
2312 /*!
2313     \since 4.5
2314
2315     Unites this path with \a other, and returns a reference to this path. This
2316     is equivalent to operator|=().
2317
2318     \sa united(), operator+(), operator-=()
2319 */
2320 QPainterPath &QPainterPath::operator+=(const QPainterPath &other)
2321 {
2322     return *this = (*this + other);
2323 }
2324
2325 /*!
2326     \since 4.5
2327
2328     Subtracts \a other from this path, and returns a reference to this
2329     path.
2330
2331     \sa subtracted(), operator-(), operator+=()
2332 */
2333 QPainterPath &QPainterPath::operator-=(const QPainterPath &other)
2334 {
2335     return *this = (*this - other);
2336 }
2337
2338 #ifndef QT_NO_DATASTREAM
2339 /*!
2340     \fn QDataStream &operator<<(QDataStream &stream, const QPainterPath &path)
2341     \relates QPainterPath
2342
2343     Writes the given painter \a path to the given \a stream, and
2344     returns a reference to the \a stream.
2345
2346     \sa {Serializing Qt Data Types}
2347 */
2348 QDataStream &operator<<(QDataStream &s, const QPainterPath &p)
2349 {
2350     if (p.isEmpty()) {
2351         s << 0;
2352         return s;
2353     }
2354
2355     s << p.elementCount();
2356     for (int i=0; i < p.d_func()->elements.size(); ++i) {
2357         const QPainterPath::Element &e = p.d_func()->elements.at(i);
2358         s << int(e.type);
2359         s << double(e.x) << double(e.y);
2360     }
2361     s << p.d_func()->cStart;
2362     s << int(p.d_func()->fillRule);
2363     return s;
2364 }
2365
2366 /*!
2367     \fn QDataStream &operator>>(QDataStream &stream, QPainterPath &path)
2368     \relates QPainterPath
2369
2370     Reads a painter path from the given \a stream into the specified \a path,
2371     and returns a reference to the \a stream.
2372
2373     \sa {Serializing Qt Data Types}
2374 */
2375 QDataStream &operator>>(QDataStream &s, QPainterPath &p)
2376 {
2377     int size;
2378     s >> size;
2379
2380     if (size == 0)
2381         return s;
2382
2383     p.ensureData(); // in case if p.d_func() == 0
2384     if (p.d_func()->elements.size() == 1) {
2385         Q_ASSERT(p.d_func()->elements.at(0).type == QPainterPath::MoveToElement);
2386         p.d_func()->elements.clear();
2387     }
2388     p.d_func()->elements.reserve(p.d_func()->elements.size() + size);
2389     for (int i=0; i<size; ++i) {
2390         int type;
2391         double x, y;
2392         s >> type;
2393         s >> x;
2394         s >> y;
2395         Q_ASSERT(type >= 0 && type <= 3);
2396         if (!qt_is_finite(x) || !qt_is_finite(y)) {
2397 #ifndef QT_NO_DEBUG
2398             qWarning("QDataStream::operator>>: NaN or Inf element found in path, skipping it");
2399 #endif
2400             continue;
2401         }
2402         QPainterPath::Element elm = { x, y, QPainterPath::ElementType(type) };
2403         p.d_func()->elements.append(elm);
2404     }
2405     s >> p.d_func()->cStart;
2406     int fillRule;
2407     s >> fillRule;
2408     Q_ASSERT(fillRule == Qt::OddEvenFill || Qt::WindingFill);
2409     p.d_func()->fillRule = Qt::FillRule(fillRule);
2410     p.d_func()->dirtyBounds = true;
2411     p.d_func()->dirtyControlBounds = true;
2412     return s;
2413 }
2414 #endif // QT_NO_DATASTREAM
2415
2416
2417 /*******************************************************************************
2418  * class QPainterPathStroker
2419  */
2420
2421 void qt_path_stroke_move_to(qfixed x, qfixed y, void *data)
2422 {
2423     ((QPainterPath *) data)->moveTo(qt_fixed_to_real(x), qt_fixed_to_real(y));
2424 }
2425
2426 void qt_path_stroke_line_to(qfixed x, qfixed y, void *data)
2427 {
2428     ((QPainterPath *) data)->lineTo(qt_fixed_to_real(x), qt_fixed_to_real(y));
2429 }
2430
2431 void qt_path_stroke_cubic_to(qfixed c1x, qfixed c1y,
2432                              qfixed c2x, qfixed c2y,
2433                              qfixed ex, qfixed ey,
2434                              void *data)
2435 {
2436     ((QPainterPath *) data)->cubicTo(qt_fixed_to_real(c1x), qt_fixed_to_real(c1y),
2437                                      qt_fixed_to_real(c2x), qt_fixed_to_real(c2y),
2438                                      qt_fixed_to_real(ex), qt_fixed_to_real(ey));
2439 }
2440
2441 /*!
2442     \since 4.1
2443     \class QPainterPathStroker
2444     \ingroup painting
2445
2446     \brief The QPainterPathStroker class is used to generate fillable
2447     outlines for a given painter path.
2448
2449     By calling the createStroke() function, passing a given
2450     QPainterPath as argument, a new painter path representing the
2451     outline of the given path is created. The newly created painter
2452     path can then be filled to draw the original painter path's
2453     outline.
2454
2455     You can control the various design aspects (width, cap styles,
2456     join styles and dash pattern) of the outlining using the following
2457     functions:
2458
2459     \list
2460     \o setWidth()
2461     \o setCapStyle()
2462     \o setJoinStyle()
2463     \o setDashPattern()
2464     \endlist
2465
2466     The setDashPattern() function accepts both a Qt::PenStyle object
2467     and a vector representation of the pattern as argument.
2468
2469     In addition you can specify a curve's threshold, controlling the
2470     granularity with which a curve is drawn, using the
2471     setCurveThreshold() function. The default threshold is a well
2472     adjusted value (0.25), and normally you should not need to modify
2473     it. However, you can make the curve's appearance smoother by
2474     decreasing its value.
2475
2476     You can also control the miter limit for the generated outline
2477     using the setMiterLimit() function. The miter limit describes how
2478     far from each join the miter join can extend. The limit is
2479     specified in the units of width so the pixelwise miter limit will
2480     be \c {miterlimit * width}. This value is only used if the join
2481     style is Qt::MiterJoin.
2482
2483     The painter path generated by the createStroke() function should
2484     only be used for outlining the given painter path. Otherwise it
2485     may cause unexpected behavior. Generated outlines also require the
2486     Qt::WindingFill rule which is set by default.
2487
2488     \sa QPen, QBrush
2489 */
2490
2491 QPainterPathStrokerPrivate::QPainterPathStrokerPrivate()
2492     : dashOffset(0)
2493 {
2494     stroker.setMoveToHook(qt_path_stroke_move_to);
2495     stroker.setLineToHook(qt_path_stroke_line_to);
2496     stroker.setCubicToHook(qt_path_stroke_cubic_to);
2497 }
2498
2499 /*!
2500    Creates a new stroker.
2501  */
2502 QPainterPathStroker::QPainterPathStroker()
2503     : d_ptr(new QPainterPathStrokerPrivate)
2504 {
2505 }
2506
2507 /*!
2508     Destroys the stroker.
2509 */
2510 QPainterPathStroker::~QPainterPathStroker()
2511 {
2512 }
2513
2514
2515 /*!
2516     Generates a new path that is a fillable area representing the
2517     outline of the given \a path.
2518
2519     The various design aspects of the outline are based on the
2520     stroker's properties: width(), capStyle(), joinStyle(),
2521     dashPattern(), curveThreshold() and miterLimit().
2522
2523     The generated path should only be used for outlining the given
2524     painter path. Otherwise it may cause unexpected
2525     behavior. Generated outlines also require the Qt::WindingFill rule
2526     which is set by default.
2527 */
2528 QPainterPath QPainterPathStroker::createStroke(const QPainterPath &path) const
2529 {
2530     QPainterPathStrokerPrivate *d = const_cast<QPainterPathStrokerPrivate *>(d_func());
2531     QPainterPath stroke;
2532     if (path.isEmpty())
2533         return path;
2534     if (d->dashPattern.isEmpty()) {
2535         d->stroker.strokePath(path, &stroke, QTransform());
2536     } else {
2537         QDashStroker dashStroker(&d->stroker);
2538         dashStroker.setDashPattern(d->dashPattern);
2539         dashStroker.setDashOffset(d->dashOffset);
2540         dashStroker.setClipRect(d->stroker.clipRect());
2541         dashStroker.strokePath(path, &stroke, QTransform());
2542     }
2543     stroke.setFillRule(Qt::WindingFill);
2544     return stroke;
2545 }
2546
2547 /*!
2548     Sets the width of the generated outline painter path to \a width.
2549
2550     The generated outlines will extend approximately 50% of \a width
2551     to each side of the given input path's original outline.
2552 */
2553 void QPainterPathStroker::setWidth(qreal width)
2554 {
2555     Q_D(QPainterPathStroker);
2556     if (width <= 0)
2557         width = 1;
2558     d->stroker.setStrokeWidth(qt_real_to_fixed(width));
2559 }
2560
2561 /*!
2562     Returns the width of the generated outlines.
2563 */
2564 qreal QPainterPathStroker::width() const
2565 {
2566     return qt_fixed_to_real(d_func()->stroker.strokeWidth());
2567 }
2568
2569
2570 /*!
2571     Sets the cap style of the generated outlines to \a style.  If a
2572     dash pattern is set, each segment of the pattern is subject to the
2573     cap \a style.
2574 */
2575 void QPainterPathStroker::setCapStyle(Qt::PenCapStyle style)
2576 {
2577     d_func()->stroker.setCapStyle(style);
2578 }
2579
2580
2581 /*!
2582     Returns the cap style of the generated outlines.
2583 */
2584 Qt::PenCapStyle QPainterPathStroker::capStyle() const
2585 {
2586     return d_func()->stroker.capStyle();
2587 }
2588
2589 /*!
2590     Sets the join style of the generated outlines to \a style.
2591 */
2592 void QPainterPathStroker::setJoinStyle(Qt::PenJoinStyle style)
2593 {
2594     d_func()->stroker.setJoinStyle(style);
2595 }
2596
2597 /*!
2598     Returns the join style of the generated outlines.
2599 */
2600 Qt::PenJoinStyle QPainterPathStroker::joinStyle() const
2601 {
2602     return d_func()->stroker.joinStyle();
2603 }
2604
2605 /*!
2606     Sets the miter limit of the generated outlines to \a limit.
2607
2608     The miter limit describes how far from each join the miter join
2609     can extend. The limit is specified in units of the currently set
2610     width. So the pixelwise miter limit will be \c { miterlimit *
2611     width}.
2612
2613     This value is only used if the join style is Qt::MiterJoin.
2614 */
2615 void QPainterPathStroker::setMiterLimit(qreal limit)
2616 {
2617     d_func()->stroker.setMiterLimit(qt_real_to_fixed(limit));
2618 }
2619
2620 /*!
2621     Returns the miter limit for the generated outlines.
2622 */
2623 qreal QPainterPathStroker::miterLimit() const
2624 {
2625     return qt_fixed_to_real(d_func()->stroker.miterLimit());
2626 }
2627
2628
2629 /*!
2630     Specifies the curve flattening \a threshold, controlling the
2631     granularity with which the generated outlines' curve is drawn.
2632
2633     The default threshold is a well adjusted value (0.25), and
2634     normally you should not need to modify it. However, you can make
2635     the curve's appearance smoother by decreasing its value.
2636 */
2637 void QPainterPathStroker::setCurveThreshold(qreal threshold)
2638 {
2639     d_func()->stroker.setCurveThreshold(qt_real_to_fixed(threshold));
2640 }
2641
2642 /*!
2643     Returns the curve flattening threshold for the generated
2644     outlines.
2645 */
2646 qreal QPainterPathStroker::curveThreshold() const
2647 {
2648     return qt_fixed_to_real(d_func()->stroker.curveThreshold());
2649 }
2650
2651 /*!
2652     Sets the dash pattern for the generated outlines to \a style.
2653 */
2654 void QPainterPathStroker::setDashPattern(Qt::PenStyle style)
2655 {
2656     d_func()->dashPattern = QDashStroker::patternForStyle(style);
2657 }
2658
2659 /*!
2660     \overload
2661
2662     Sets the dash pattern for the generated outlines to \a
2663     dashPattern.  This function makes it possible to specify custom
2664     dash patterns.
2665
2666     Each element in the vector contains the lengths of the dashes and spaces
2667     in the stroke, beginning with the first dash in the first element, the
2668     first space in the second element, and alternating between dashes and
2669     spaces for each following pair of elements.
2670
2671     The vector can contain an odd number of elements, in which case the last
2672     element will be extended by the length of the first element when the
2673     pattern repeats.
2674 */
2675 void QPainterPathStroker::setDashPattern(const QVector<qreal> &dashPattern)
2676 {
2677     d_func()->dashPattern.clear();
2678     for (int i=0; i<dashPattern.size(); ++i)
2679         d_func()->dashPattern << qt_real_to_fixed(dashPattern.at(i));
2680 }
2681
2682 /*!
2683     Returns the dash pattern for the generated outlines.
2684 */
2685 QVector<qreal> QPainterPathStroker::dashPattern() const
2686 {
2687     return d_func()->dashPattern;
2688 }
2689
2690 /*!
2691     Returns the dash offset for the generated outlines.
2692  */
2693 qreal QPainterPathStroker::dashOffset() const
2694 {
2695     return d_func()->dashOffset;
2696 }
2697
2698 /*!
2699   Sets the dash offset for the generated outlines to \a offset.
2700
2701   See the documentation for QPen::setDashOffset() for a description of the
2702   dash offset.
2703  */
2704 void QPainterPathStroker::setDashOffset(qreal offset)
2705 {
2706     d_func()->dashOffset = offset;
2707 }
2708
2709 /*!
2710   Converts the path into a polygon using the QTransform
2711   \a matrix, and returns the polygon.
2712
2713   The polygon is created by first converting all subpaths to
2714   polygons, then using a rewinding technique to make sure that
2715   overlapping subpaths can be filled using the correct fill rule.
2716
2717   Note that rewinding inserts addition lines in the polygon so
2718   the outline of the fill polygon does not match the outline of
2719   the path.
2720
2721   \sa toSubpathPolygons(), toFillPolygons(),
2722   {QPainterPath#QPainterPath Conversion}{QPainterPath Conversion}
2723 */
2724 QPolygonF QPainterPath::toFillPolygon(const QTransform &matrix) const
2725 {
2726
2727     QList<QPolygonF> flats = toSubpathPolygons(matrix);
2728     QPolygonF polygon;
2729     if (flats.isEmpty())
2730         return polygon;
2731     QPointF first = flats.first().first();
2732     for (int i=0; i<flats.size(); ++i) {
2733         polygon += flats.at(i);
2734         if (!flats.at(i).isClosed())
2735             polygon += flats.at(i).first();
2736         if (i > 0)
2737             polygon += first;
2738     }
2739     return polygon;
2740 }
2741
2742 /*!
2743   \overload
2744 */
2745 QPolygonF QPainterPath::toFillPolygon(const QMatrix &matrix) const
2746 {
2747     return toFillPolygon(QTransform(matrix));
2748 }
2749
2750
2751 //derivative of the equation
2752 static inline qreal slopeAt(qreal t, qreal a, qreal b, qreal c, qreal d)
2753 {
2754     return 3*t*t*(d - 3*c + 3*b - a) + 6*t*(c - 2*b + a) + 3*(b - a);
2755 }
2756
2757 /*!
2758     Returns the length of the current path.
2759 */
2760 qreal QPainterPath::length() const
2761 {
2762     Q_D(QPainterPath);
2763     if (isEmpty())
2764         return 0;
2765
2766     qreal len = 0;
2767     for (int i=1; i<d->elements.size(); ++i) {
2768         const Element &e = d->elements.at(i);
2769
2770         switch (e.type) {
2771         case MoveToElement:
2772             break;
2773         case LineToElement:
2774         {
2775             len += QLineF(d->elements.at(i-1), e).length();
2776             break;
2777         }
2778         case CurveToElement:
2779         {
2780             QBezier b = QBezier::fromPoints(d->elements.at(i-1),
2781                                             e,
2782                                             d->elements.at(i+1),
2783                                             d->elements.at(i+2));
2784             len += b.length();
2785             i += 2;
2786             break;
2787         }
2788         default:
2789             break;
2790         }
2791     }
2792     return len;
2793 }
2794
2795 /*!
2796     Returns percentage of the whole path at the specified length \a len.
2797
2798     Note that similarly to other percent methods, the percentage measurement
2799     is not linear with regards to the length, if curves are present
2800     in the path. When curves are present the percentage argument is mapped
2801     to the t parameter of the Bezier equations.
2802 */
2803 qreal QPainterPath::percentAtLength(qreal len) const
2804 {
2805     Q_D(QPainterPath);
2806     if (isEmpty() || len <= 0)
2807         return 0;
2808
2809     qreal totalLength = length();
2810     if (len > totalLength)
2811         return 1;
2812
2813     qreal curLen = 0;
2814     for (int i=1; i<d->elements.size(); ++i) {
2815         const Element &e = d->elements.at(i);
2816
2817         switch (e.type) {
2818         case MoveToElement:
2819             break;
2820         case LineToElement:
2821         {
2822             QLineF line(d->elements.at(i-1), e);
2823             qreal llen = line.length();
2824             curLen += llen;
2825             if (curLen >= len) {
2826                 return len/totalLength ;
2827             }
2828
2829             break;
2830         }
2831         case CurveToElement:
2832         {
2833             QBezier b = QBezier::fromPoints(d->elements.at(i-1),
2834                                             e,
2835                                             d->elements.at(i+1),
2836                                             d->elements.at(i+2));
2837             qreal blen = b.length();
2838             qreal prevLen = curLen;
2839             curLen += blen;
2840
2841             if (curLen >= len) {
2842                 qreal res = b.tAtLength(len - prevLen);
2843                 return (res * blen + prevLen)/totalLength;
2844             }
2845
2846             i += 2;
2847             break;
2848         }
2849         default:
2850             break;
2851         }
2852     }
2853
2854     return 0;
2855 }
2856
2857 static inline QBezier bezierAtT(const QPainterPath &path, qreal t, qreal *startingLength, qreal *bezierLength)
2858 {
2859     *startingLength = 0;
2860     if (t > 1)
2861         return QBezier();
2862
2863     qreal curLen = 0;
2864     qreal totalLength = path.length();
2865
2866     const int lastElement = path.elementCount() - 1;
2867     for (int i=0; i <= lastElement; ++i) {
2868         const QPainterPath::Element &e = path.elementAt(i);
2869
2870         switch (e.type) {
2871         case QPainterPath::MoveToElement:
2872             break;
2873         case QPainterPath::LineToElement:
2874         {
2875             QLineF line(path.elementAt(i-1), e);
2876             qreal llen = line.length();
2877             curLen += llen;
2878             if (i == lastElement || curLen/totalLength >= t) {
2879                 *bezierLength = llen;
2880                 QPointF a = path.elementAt(i-1);
2881                 QPointF delta = e - a;
2882                 return QBezier::fromPoints(a, a + delta / 3, a + 2 * delta / 3, e);
2883             }
2884             break;
2885         }
2886         case QPainterPath::CurveToElement:
2887         {
2888             QBezier b = QBezier::fromPoints(path.elementAt(i-1),
2889                                             e,
2890                                             path.elementAt(i+1),
2891                                             path.elementAt(i+2));
2892             qreal blen = b.length();
2893             curLen += blen;
2894
2895             if (i + 2 == lastElement || curLen/totalLength >= t) {
2896                 *bezierLength = blen;
2897                 return b;
2898             }
2899
2900             i += 2;
2901             break;
2902         }
2903         default:
2904             break;
2905         }
2906         *startingLength = curLen;
2907     }
2908     return QBezier();
2909 }
2910
2911 /*!
2912     Returns the point at at the percentage \a t of the current path.
2913     The argument \a t has to be between 0 and 1.
2914
2915     Note that similarly to other percent methods, the percentage measurement
2916     is not linear with regards to the length, if curves are present
2917     in the path. When curves are present the percentage argument is mapped
2918     to the t parameter of the Bezier equations.
2919 */
2920 QPointF QPainterPath::pointAtPercent(qreal t) const
2921 {
2922     if (t < 0 || t > 1) {
2923         qWarning("QPainterPath::pointAtPercent accepts only values between 0 and 1");
2924         return QPointF();
2925     }
2926
2927     if (!d_ptr || d_ptr->elements.size() == 0)
2928         return QPointF();
2929
2930     if (d_ptr->elements.size() == 1)
2931         return d_ptr->elements.at(0);
2932
2933     qreal totalLength = length();
2934     qreal curLen = 0;
2935     qreal bezierLen = 0;
2936     QBezier b = bezierAtT(*this, t, &curLen, &bezierLen);
2937     qreal realT = (totalLength * t - curLen) / bezierLen;
2938
2939     return b.pointAt(qBound(qreal(0), realT, qreal(1)));
2940 }
2941
2942 /*!
2943     Returns the angle of the path tangent at the percentage \a t.
2944     The argument \a t has to be between 0 and 1.
2945
2946     Positive values for the angles mean counter-clockwise while negative values
2947     mean the clockwise direction. Zero degrees is at the 3 o'clock position.
2948
2949     Note that similarly to the other percent methods, the percentage measurement
2950     is not linear with regards to the length if curves are present
2951     in the path. When curves are present the percentage argument is mapped
2952     to the t parameter of the Bezier equations.
2953 */
2954 qreal QPainterPath::angleAtPercent(qreal t) const
2955 {
2956     if (t < 0 || t > 1) {
2957         qWarning("QPainterPath::angleAtPercent accepts only values between 0 and 1");
2958         return 0;
2959     }
2960
2961     qreal totalLength = length();
2962     qreal curLen = 0;
2963     qreal bezierLen = 0;
2964     QBezier bez = bezierAtT(*this, t, &curLen, &bezierLen);
2965     qreal realT = (totalLength * t - curLen) / bezierLen;
2966
2967     qreal m1 = slopeAt(realT, bez.x1, bez.x2, bez.x3, bez.x4);
2968     qreal m2 = slopeAt(realT, bez.y1, bez.y2, bez.y3, bez.y4);
2969
2970     return QLineF(0, 0, m1, m2).angle();
2971 }
2972
2973 #if defined(Q_WS_WINCE)
2974 #pragma warning( disable : 4056 4756 )
2975 #endif
2976
2977 /*!
2978     Returns the slope of the path at the percentage \a t. The
2979     argument \a t has to be between 0 and 1.
2980
2981     Note that similarly to other percent methods, the percentage measurement
2982     is not linear with regards to the length, if curves are present
2983     in the path. When curves are present the percentage argument is mapped
2984     to the t parameter of the Bezier equations.
2985 */
2986 qreal QPainterPath::slopeAtPercent(qreal t) const
2987 {
2988     if (t < 0 || t > 1) {
2989         qWarning("QPainterPath::slopeAtPercent accepts only values between 0 and 1");
2990         return 0;
2991     }
2992
2993     qreal totalLength = length();
2994     qreal curLen = 0;
2995     qreal bezierLen = 0;
2996     QBezier bez = bezierAtT(*this, t, &curLen, &bezierLen);
2997     qreal realT = (totalLength * t - curLen) / bezierLen;
2998
2999     qreal m1 = slopeAt(realT, bez.x1, bez.x2, bez.x3, bez.x4);
3000     qreal m2 = slopeAt(realT, bez.y1, bez.y2, bez.y3, bez.y4);
3001     //tangent line
3002     qreal slope = 0;
3003
3004 #define SIGN(x) ((x < 0)?-1:1)
3005     if (m1)
3006         slope = m2/m1;
3007     else {
3008         //windows doesn't define INFINITY :(
3009 #ifdef INFINITY
3010         slope = INFINITY*SIGN(m2);
3011 #else
3012         if (sizeof(qreal) == sizeof(double)) {
3013             return 1.79769313486231570e+308;
3014         } else {
3015             return ((qreal)3.40282346638528860e+38);
3016         }
3017 #endif
3018     }
3019
3020     return slope;
3021 }
3022
3023 /*!
3024   \since 4.4
3025
3026   Adds the given rectangle \a rect with rounded corners to the path.
3027
3028   The \a xRadius and \a yRadius arguments specify the radii of
3029   the ellipses defining the corners of the rounded rectangle.
3030   When \a mode is Qt::RelativeSize, \a xRadius and
3031   \a yRadius are specified in percentage of half the rectangle's
3032   width and height respectively, and should be in the range 0.0 to 100.0.
3033
3034   \sa addRect()
3035 */
3036 void QPainterPath::addRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius,
3037                                   Qt::SizeMode mode)
3038 {
3039     QRectF r = rect.normalized();
3040
3041     if (r.isNull())
3042         return;
3043
3044     if (mode == Qt::AbsoluteSize) {
3045         qreal w = r.width() / 2;
3046         qreal h = r.height() / 2;
3047
3048         if (w == 0) {
3049             xRadius = 0;
3050         } else {
3051             xRadius = 100 * qMin(xRadius, w) / w;
3052         }
3053         if (h == 0) {
3054             yRadius = 0;
3055         } else {
3056             yRadius = 100 * qMin(yRadius, h) / h;
3057         }
3058     } else {
3059         if (xRadius > 100)                          // fix ranges
3060             xRadius = 100;
3061
3062         if (yRadius > 100)
3063             yRadius = 100;
3064     }
3065
3066     if (xRadius <= 0 || yRadius <= 0) {             // add normal rectangle
3067         addRect(r);
3068         return;
3069     }
3070
3071     qreal x = r.x();
3072     qreal y = r.y();
3073     qreal w = r.width();
3074     qreal h = r.height();
3075     qreal rxx2 = w*xRadius/100;
3076     qreal ryy2 = h*yRadius/100;
3077
3078     ensureData();
3079     detach();
3080
3081     bool first = d_func()->elements.size() < 2;
3082
3083     arcMoveTo(x, y, rxx2, ryy2, 180);
3084     arcTo(x, y, rxx2, ryy2, 180, -90);
3085     arcTo(x+w-rxx2, y, rxx2, ryy2, 90, -90);
3086     arcTo(x+w-rxx2, y+h-ryy2, rxx2, ryy2, 0, -90);
3087     arcTo(x, y+h-ryy2, rxx2, ryy2, 270, -90);
3088     closeSubpath();
3089
3090     d_func()->require_moveTo = true;
3091     d_func()->convex = first;
3092 }
3093
3094 /*!
3095   \fn void QPainterPath::addRoundedRect(qreal x, qreal y, qreal w, qreal h, qreal xRadius, qreal yRadius, Qt::SizeMode mode = Qt::AbsoluteSize);
3096   \since 4.4
3097   \overload
3098
3099   Adds the given rectangle \a x, \a y, \a w, \a h  with rounded corners to the path.
3100  */
3101
3102 /*!
3103   \obsolete
3104
3105   Adds a rectangle \a r with rounded corners to the path.
3106
3107   The \a xRnd and \a yRnd arguments specify how rounded the corners
3108   should be. 0 is angled corners, 99 is maximum roundedness.
3109
3110   \sa addRoundedRect()
3111 */
3112 void QPainterPath::addRoundRect(const QRectF &r, int xRnd, int yRnd)
3113 {
3114     if(xRnd >= 100)                          // fix ranges
3115         xRnd = 99;
3116     if(yRnd >= 100)
3117         yRnd = 99;
3118     if(xRnd <= 0 || yRnd <= 0) {             // add normal rectangle
3119         addRect(r);
3120         return;
3121     }
3122
3123     QRectF rect = r.normalized();
3124
3125     if (rect.isNull())
3126         return;
3127
3128     qreal x = rect.x();
3129     qreal y = rect.y();
3130     qreal w = rect.width();
3131     qreal h = rect.height();
3132     qreal rxx2 = w*xRnd/100;
3133     qreal ryy2 = h*yRnd/100;
3134
3135     ensureData();
3136     detach();
3137
3138     bool first = d_func()->elements.size() < 2;
3139
3140     arcMoveTo(x, y, rxx2, ryy2, 180);
3141     arcTo(x, y, rxx2, ryy2, 180, -90);
3142     arcTo(x+w-rxx2, y, rxx2, ryy2, 90, -90);
3143     arcTo(x+w-rxx2, y+h-ryy2, rxx2, ryy2, 0, -90);
3144     arcTo(x, y+h-ryy2, rxx2, ryy2, 270, -90);
3145     closeSubpath();
3146
3147     d_func()->require_moveTo = true;
3148     d_func()->convex = first;
3149 }
3150
3151 /*!
3152   \obsolete
3153
3154   \fn bool QPainterPath::addRoundRect(const QRectF &rect, int roundness);
3155   \since 4.3
3156   \overload
3157
3158   Adds a rounded rectangle, \a rect, to the path.
3159
3160   The \a roundness argument specifies uniform roundness for the
3161   rectangle.  Vertical and horizontal roundness factors will be
3162   adjusted accordingly to act uniformly around both axes. Use this
3163   method if you want a rectangle equally rounded across both the X and
3164   Y axis.
3165
3166   \sa addRoundedRect()
3167 */
3168
3169 /*!
3170   \obsolete
3171
3172   \fn void QPainterPath::addRoundRect(qreal x, qreal y, qreal w, qreal h, int xRnd, int yRnd);
3173   \overload
3174
3175   Adds a rectangle with rounded corners to the path. The rectangle
3176   is constructed from \a x, \a y, and the width and height \a w
3177   and \a h.
3178
3179   The \a xRnd and \a yRnd arguments specify how rounded the corners
3180   should be. 0 is angled corners, 99 is maximum roundedness.
3181
3182   \sa addRoundedRect()
3183  */
3184
3185 /*!
3186   \obsolete
3187
3188   \fn bool QPainterPath::addRoundRect(qreal x, qreal y, qreal width, qreal height, int roundness);
3189   \since 4.3
3190   \overload
3191
3192   Adds a rounded rectangle to the path, defined by the coordinates \a
3193   x and \a y with the specified \a width and \a height.
3194
3195   The \a roundness argument specifies uniform roundness for the
3196   rectangle. Vertical and horizontal roundness factors will be
3197   adjusted accordingly to act uniformly around both axes. Use this
3198   method if you want a rectangle equally rounded across both the X and
3199   Y axis.
3200
3201   \sa addRoundedRect()
3202 */
3203
3204 /*!
3205     \since 4.3
3206
3207     Returns a path which is the union of this path's fill area and \a p's fill area.
3208
3209     Set operations on paths will treat the paths as areas. Non-closed
3210     paths will be treated as implicitly closed.
3211     Bezier curves may be flattened to line segments due to numerical instability of
3212     doing bezier curve intersections.
3213
3214     \sa intersected(), subtracted()
3215 */
3216 QPainterPath QPainterPath::united(const QPainterPath &p) const
3217 {
3218     if (isEmpty() || p.isEmpty())
3219         return isEmpty() ? p : *this;
3220     QPathClipper clipper(*this, p);
3221     return clipper.clip(QPathClipper::BoolOr);
3222 }
3223
3224 /*!
3225     \since 4.3
3226
3227     Returns a path which is the intersection of this path's fill area and \a p's fill area.
3228     Bezier curves may be flattened to line segments due to numerical instability of
3229     doing bezier curve intersections.
3230 */
3231 QPainterPath QPainterPath::intersected(const QPainterPath &p) const
3232 {
3233     if (isEmpty() || p.isEmpty())
3234         return QPainterPath();
3235     QPathClipper clipper(*this, p);
3236     return clipper.clip(QPathClipper::BoolAnd);
3237 }
3238
3239 /*!
3240     \since 4.3
3241
3242     Returns a path which is \a p's fill area subtracted from this path's fill area.
3243
3244     Set operations on paths will treat the paths as areas. Non-closed
3245     paths will be treated as implicitly closed.
3246     Bezier curves may be flattened to line segments due to numerical instability of
3247     doing bezier curve intersections.
3248 */
3249 QPainterPath QPainterPath::subtracted(const QPainterPath &p) const
3250 {
3251     if (isEmpty() || p.isEmpty())
3252         return *this;
3253     QPathClipper clipper(*this, p);
3254     return clipper.clip(QPathClipper::BoolSub);
3255 }
3256
3257 /*!
3258     \since 4.3
3259     \obsolete
3260
3261     Use subtracted() instead.
3262
3263     \sa subtracted()
3264 */
3265 QPainterPath QPainterPath::subtractedInverted(const QPainterPath &p) const
3266 {
3267     return p.subtracted(*this);
3268 }
3269
3270 /*!
3271     \since 4.4
3272
3273     Returns a simplified version of this path. This implies merging all subpaths that intersect,
3274     and returning a path containing no intersecting edges. Consecutive parallel lines will also
3275     be merged. The simplified path will always use the default fill rule, Qt::OddEvenFill.
3276     Bezier curves may be flattened to line segments due to numerical instability of
3277     doing bezier curve intersections.
3278 */
3279 QPainterPath QPainterPath::simplified() const
3280 {
3281     if(isEmpty())
3282         return *this;
3283     QPathClipper clipper(*this, QPainterPath());
3284     return clipper.clip(QPathClipper::Simplify);
3285 }
3286
3287 /*!
3288   \since 4.3
3289
3290   Returns true if the current path intersects at any point the given path \a p.
3291   Also returns true if the current path contains or is contained by any part of \a p.
3292
3293   Set operations on paths will treat the paths as areas. Non-closed
3294   paths will be treated as implicitly closed.
3295
3296   \sa contains()
3297  */
3298 bool QPainterPath::intersects(const QPainterPath &p) const
3299 {
3300     if (p.elementCount() == 1)
3301         return contains(p.elementAt(0));
3302     if (isEmpty() || p.isEmpty())
3303         return false;
3304     QPathClipper clipper(*this, p);
3305     return clipper.intersect();
3306 }
3307
3308 /*!
3309   \since 4.3
3310
3311   Returns true if the given path \a p is contained within
3312   the current path. Returns false if any edges of the current path and
3313   \a p intersect.
3314
3315   Set operations on paths will treat the paths as areas. Non-closed
3316   paths will be treated as implicitly closed.
3317
3318   \sa intersects()
3319  */
3320 bool QPainterPath::contains(const QPainterPath &p) const
3321 {
3322     if (p.elementCount() == 1)
3323         return contains(p.elementAt(0));
3324     if (isEmpty() || p.isEmpty())
3325         return false;
3326     QPathClipper clipper(*this, p);
3327     return clipper.contains();
3328 }
3329
3330 void QPainterPath::setDirty(bool dirty)
3331 {
3332     d_func()->dirtyBounds        = dirty;
3333     d_func()->dirtyControlBounds = dirty;
3334     delete d_func()->pathConverter;
3335     d_func()->pathConverter = 0;
3336     d_func()->convex = false;
3337 }
3338
3339 void QPainterPath::computeBoundingRect() const
3340 {
3341     QPainterPathData *d = d_func();
3342     d->dirtyBounds = false;
3343     if (!d_ptr) {
3344         d->bounds = QRect();
3345         return;
3346     }
3347
3348     qreal minx, maxx, miny, maxy;
3349     minx = maxx = d->elements.at(0).x;
3350     miny = maxy = d->elements.at(0).y;
3351     for (int i=1; i<d->elements.size(); ++i) {
3352         const Element &e = d->elements.at(i);
3353
3354         switch (e.type) {
3355         case MoveToElement:
3356         case LineToElement:
3357             if (e.x > maxx) maxx = e.x;
3358             else if (e.x < minx) minx = e.x;
3359             if (e.y > maxy) maxy = e.y;
3360             else if (e.y < miny) miny = e.y;
3361             break;
3362         case CurveToElement:
3363             {
3364                 QBezier b = QBezier::fromPoints(d->elements.at(i-1),
3365                                                 e,
3366                                                 d->elements.at(i+1),
3367                                                 d->elements.at(i+2));
3368                 QRectF r = qt_painterpath_bezier_extrema(b);
3369                 qreal right = r.right();
3370                 qreal bottom = r.bottom();
3371                 if (r.x() < minx) minx = r.x();
3372                 if (right > maxx) maxx = right;
3373                 if (r.y() < miny) miny = r.y();
3374                 if (bottom > maxy) maxy = bottom;
3375                 i += 2;
3376             }
3377             break;
3378         default:
3379             break;
3380         }
3381     }
3382     d->bounds = QRectF(minx, miny, maxx - minx, maxy - miny);
3383 }
3384
3385
3386 void QPainterPath::computeControlPointRect() const
3387 {
3388     QPainterPathData *d = d_func();
3389     d->dirtyControlBounds = false;
3390     if (!d_ptr) {
3391         d->controlBounds = QRect();
3392         return;
3393     }
3394
3395     qreal minx, maxx, miny, maxy;
3396     minx = maxx = d->elements.at(0).x;
3397     miny = maxy = d->elements.at(0).y;
3398     for (int i=1; i<d->elements.size(); ++i) {
3399         const Element &e = d->elements.at(i);
3400         if (e.x > maxx) maxx = e.x;
3401         else if (e.x < minx) minx = e.x;
3402         if (e.y > maxy) maxy = e.y;
3403         else if (e.y < miny) miny = e.y;
3404     }
3405     d->controlBounds = QRectF(minx, miny, maxx - minx, maxy - miny);
3406 }
3407
3408 #ifndef QT_NO_DEBUG_STREAM
3409 QDebug operator<<(QDebug s, const QPainterPath &p)
3410 {
3411     s.nospace() << "QPainterPath: Element count=" << p.elementCount() << endl;
3412     const char *types[] = {"MoveTo", "LineTo", "CurveTo", "CurveToData"};
3413     for (int i=0; i<p.elementCount(); ++i) {
3414         s.nospace() << " -> " << types[p.elementAt(i).type] << "(x=" << p.elementAt(i).x << ", y=" << p.elementAt(i).y << ')' << endl;
3415
3416     }
3417     return s;
3418 }
3419 #endif
3420
3421 QT_END_NAMESPACE