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