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