/*!
    \example painting/painterpaths
    \title Painter Paths Example

    The Painter Paths example shows how painter paths can be used to
    build complex shapes for rendering.

    \image painterpaths-example.png

    The QPainterPath class provides a container for painting
    operations, enabling graphical shapes to be constructed and
    reused.

    A painter path is an object composed of a number of graphical
    building blocks (such as rectangles, ellipses, lines, and curves),
    and can be used for filling, outlining, and clipping. The main
    advantage of painter paths over normal drawing operations is that
    complex shapes only need to be created once, but they can be drawn
    many times using only calls to QPainter::drawPath().

    The example consists of two classes:

    \list
        \o The \c RenderArea class which is a custom widget displaying
           a single painter path.
        \o The \c Window class which is the applications main window
           displaying several \c RenderArea widgets, and allowing the user
           to manipulate the painter paths' filling, pen, color
           and rotation angle.
    \endlist

    First we will review the \c Window class, then we will take a look
    at the \c RenderArea class.

    \section1 Window Class Definition

    The \c Window class inherits QWidget, and is the applications main
    window displaying several \c RenderArea widgets, and allowing the
    user to manipulate the painter paths' filling, pen, color and
    rotation angle.

    \quotefromfile painting/painterpaths/window.h
    \skipto class Window
    \printuntil penColorChanged()

    We declare three private slots to respond to user input regarding
    filling and color: \c fillRuleChanged(), \c fillGradientChanged()
    and \c penColorChanged().

    When the user changes the pen width and the rotation angle, the
    new value is passed directly on to the \c RenderArea widgets using
    the QSpinBox::valueChanged() signal. The reason why we must
    implement slots to update the filling and color, is that QComboBox
    doesn't provide a similar signal passing the new value as
    argument; so we need to retrieve the new value, or values, before
    we can update the \c RenderArea widgets.

    \skipto private
    \printuntil currentItemData

    We also declare a couple of private convenience functions: \c
    populateWithColors() populates a given QComboBox with items
    corresponding to the color names Qt knows about, and \c
    currentItemData() returns the current item for a given QComboBox.

    \skipto enum
    \printuntil /^\};/

    Then we declare the various components of the main window
    widget. We also declare a convenience constant specifying the
    number of \c RenderArea widgets.

    \section1 Window Class Implementation

    In the implementation of the \c Window class we first declare the
    constant \c Pi with six significant figures:

    \quotefromfile painting/painterpaths/window.cpp
    \skipto Pi
    \printuntil Pi

    In the constructor, we then define the various painter paths and
    create corresponding \c RenderArea widgets which will render the
    graphical shapes:

    \skipto Window
    \printuntil rectPath.close

    We construct a rectangle with sharp corners using the
    QPainterPath::moveTo() and QPainterPath::lineTo()
    functions.

    QPainterPath::moveTo() moves the current point to the point passed
    as argument. A painter path is an object composed of a number of
    graphical building blocks, i.e. subpaths. Moving the current point
    will also start a new subpath (implicitly closing the previously
    current path when the new one is started). The
    QPainterPath::lineTo() function adds a straight line from the
    current point to the given end point. After the line is drawn, the
    current point is updated to be at the end point of the line.

    We first move the current point starting a new subpath, and we
    draw three of the rectangle's sides. Then we call the
    QPainterPath::closeSubpath() function which draws a line to the
    beginning of the current subpath. A new subpath is automatically
    begun when the current subpath is closed. The current point of the
    new path is (0, 0). We could also have called
    QPainterPath::lineTo() to draw the last line as well, and then
    explicitly start a new subpath using the QPainterPath::moveTo()
    function.

    QPainterPath also provide the QPainterPath::addRect() convenience
    function, which adds a given rectangle to the path as a closed
    subpath. The rectangle is added as a clockwise set of lines. The
    painter path's current position after the rect has been added is
    at the top-left corner of the rectangle.

    \skipto roundRectPath
    \printuntil roundRectPath.close

    Then we construct a rectangle with rounded corners. As before, we
    use the QPainterPath::moveTo() and QPainterPath::lineTo()
    functions to draw the rectangle's sides. To create the rounded
    corners we use the QPainterPath::arcTo() function.

    QPainterPath::arcTo() creates an arc that occupies the given
    rectangle (specified by a QRect or the rectangle's coordinates),
    beginning at the given start angle and extending the given degrees
    counter-clockwise. Angles are specified in degrees. Clockwise arcs
    can be specified using negative angles.  The function connects the
    current point to the starting point of the arc if they are not
    already connected.

    \skipto ellipsePath
    \printuntil ellipsePath.arcTo

    We also use the QPainterPath::arcTo() function to construct the
    ellipse path. First we move the current point starting a new
    path. Then we call QPainterPath::arcTo() with starting angle 0.0
    and 360.0 degrees as the last argument, creating an ellipse.

    Again, QPainterPath provides a convenience function (
    QPainterPath::addEllipse()) which creates an ellipse within a
    given bounding rectangle and adds it to the painter path. If the
    current subpath is closed, a new subpath is started. The ellipse
    is composed of a clockwise curve, starting and finishing at zero
    degrees (the 3 o'clock position).

    \skipto piePath
    \printuntil piePath.close

    When constructing the pie chart path we continue to use a
    combination of the mentioned functions: First we move the current
    point, starting a new subpath. Then we create a line from the
    center of the chart to the arc, and the arc itself. When we close
    the subpath, we implicitly construct the last line back to the
    center of the chart.

    \skipto polygonPath
    \printuntil polygonPath.close

    Constructing a polygon is equivalent to constructing a rectangle.

    QPainterPath also provide the QPainterPath::addPolygon()
    convenience function which adds the given polygon to the path as a
    new subpath. Current position after the polygon has been added is
    the last point in polygon.

    \skipto groupPath
    \printuntil groupPath.close

    Then we create a path consisting of a group of subpaths: First we
    move the current point, and create a circle using the
    QPainterPath::arcTo() function with starting angle 0.0, and 360
    degrees as the last argument, as we did when we created the
    ellipse path. Then we move the current point again, starting a
    new subpath, and construct three sides of a square using the
    QPainterPath::lineTo() function.

    Now, when we call the QPainterPath::closeSubpath() fucntion the
    last side is created. Remember that the
    QPainterPath::closeSubpath() function draws a line to the
    beginning of the \e current subpath, i.e the square.

    QPainterPath provide a convenience function,
    QPainterPath::addPath() which adds a given path to the path that
    calls the function.

    \skipto textPath
    \printuntil textPath.addText

    When creating the text path, we first create the font. Then we set
    the font's style strategy which tells the font matching algorithm
    what type of fonts should be used to find an appropriate default
    family. QFont::ForceOutline forces the use of outline fonts.

    To construct the text, we use the QPainterPath::addText() function
    which adds the given text to the path as a set of closed subpaths
    created from the supplied font. The subpaths are positioned so
    that the left end of the text's baseline lies at the specified
    point.

    \skipto bezierPath
    \printuntil bezierPath.cubicTo

    To create the Bezier path, we use the QPainterPath::cubicTo()
    function which adds a Bezier curve between the current point and
    the given end point with the given control point.  After the curve
    is added, the current point is updated to be at the end point of
    the curve.

    In this case we omit to close the subpath so that we only have a
    simple curve. But there is still a logical line from the curve's
    endpoint back to the beginning of the subpath; it becomes visible
    when filling the path as can be seen in the applications main
    window.

    \skipto starPath
    \printuntil starPath.close

    The final path that we construct shows that you can use
    QPainterPath to construct rather complex shapes using only the
    previous mentioned QPainterPath::moveTo(), QPainterPath::lineTo()
    and QPainterPath::closeSubpath() functions.

    \skipto renderAreas
    \printuntil Q_ASSERT

    Now that we have created all the painter paths that we need, we
    create a corresponding \c RenderArea widget for each. In the end,
    we make sure that the number of render areas is correct using the
    Q_ASSERT() macro.

    \skipto fillRuleComboBox
    \printuntil fillRuleLabel->setBuddy

    Then we create the widgets associated with the painter paths' fill
    rule.

    There are two available fill rules in Qt: The Qt::OddEvenFill rule
    determine whether a point is inside the shape by drawing a
    horizontal line from the point to a location outside the shape,
    and count the number of intersections. If the number of
    intersections is an odd number, the point is inside the
    shape. This rule is the default.

    The Qt::WindingFill rule determine whether a point is inside the
    shape by drawing a horizontal line from the point to a location
    outside the shape. Then it determines whether the direction of the
    line at each intersection point is up or down. The winding number
    is determined by summing the direction of each intersection. If
    the number is non zero, the point is inside the shape.

    The Qt::WindingFill rule can in most cases be considered as the
    intersection of closed shapes.

    \skipto fillColor1ComboBox
    \printuntil fillToLabel->setSizePolicy
    \skipto penWidthSpinBox
    \printuntil penWidthLabel->setBuddy
    \skipto penColorComboBox
    \printuntil penColorLabel->setBuddy
    \skipto rotationAngleSpinBox
    \printuntil rotationAngleLabel->setBuddy

    We also create the other widgets associated with the filling, the
    pen and the rotation angle.

    \skipto connect
    \printto QGridLayout

    We connect the comboboxes \l {QComboBox::activated()}{activated()}
    signals to the associated slots in the \c Window class, while we
    connect the spin boxes \l
    {QSpinBox::valueChanged()}{valueChanged()} signal directly to the
    \c RenderArea widget's respective slots.

    \skipto topLayout
    \printuntil setLayout

    We add the \c RenderArea widgets to a separate layout which we
    then add to the main layout along with the rest of the widgets.

    \skipto fillRuleChanged
    \printuntil /^\}/

    Finally, we initialize the \c RenderArea widgets by calling the \c
    fillRuleChanged(), \c fillGradientChanged() and \c
    penColorChanged() slots, and we set the inital pen width and
    window title.

    \skipto fillRuleChanged()
    \printuntil /^\}/
    \skipto fillGradientChanged()
    \printuntil /^\}/
    \skipto penColorChanged()
    \printuntil /^\}/

    The private slots are implemented to retrieve the new value, or
    values, from the associated comboboxes and update the RenderArea
    widgets.

    First we determine the new value, or values, using the private \c
    currentItemData() function and the qvariant_cast() template
    function. Then we call the associated slot for each of the \c
    RenderArea widgets to update the painter paths.

    \skipto populateWithColors
    \printuntil /^\}/

    The \c populateWithColors() function populates the given combobox
    with items corresponding to the color names Qt knows about
    provided by the static QColor::colorNames() function.

    \skipto currentItemData
    \printuntil /^\}/

    The \c currentItemData() function simply return the current item
    of the given combobox.

    \section1 RenderArea Class Definition

    The \c RenderArea class inherits QWidget, and is a custom widget
    displaying a single painter path.

    \quotefromfile painting/painterpaths/renderarea.h
    \skipto class RenderArea
    \printuntil paintEvent

    We declare several public slots updating the \c RenderArea
    widget's associated painter path. In addition we reimplement the
    QWidget::minimumSizeHint() and QWidget::sizeHint() functions to
    give the \c RenderArea widget a reasonable size within our
    application, and we reimplement the QWidget::paintEvent() event
    handler to draw its painter path.

    \skipto private
    \printuntil /^\};/

    Each instance of the \c RenderArea class has a QPainterPath, a
    couple of fill colors, a pen width, a pen color and a rotation
    angle.

    \section1 RenderArea Class Implementation

    The constructor takes a QPainterPath as argument (in addition to
    the optional QWidget parent):

    \quotefromfile painting/painterpaths/renderarea.cpp
    \skipto RenderArea
    \printuntil /^\}/

    In the constructor we initialize the \c RenderArea widget with the
    QPainterPath parameter as well as initializing the pen width and
    rotation angle. We also set the widgets \l
    {QWidget::backgroundRole()}{background role}; QPalette::Base is
    typically white.

    \skipto minimumSizeHint
    \printuntil /^\}/

    \skipto sizeHint
    \printuntil /^\}/

    Then we reimplement the QWidget::minimumSizeHint() and
    QWidget::sizeHint() functions to give the \c RenderArea widget a
    reasonable size within our application.

    \skipto setFillRule
    \printuntil /^\}/

    \skipto setFillGradient
    \printuntil /^\}/

    \skipto setPenWidth
    \printuntil /^\}/

    \skipto setPenColor
    \printuntil /^\}/

    \skipto setRotationAngle
    \printuntil /^\}/

    The various public slots updates the \c RenderArea widget's
    painter path by setting the associated property and make a call to
    the QWidget::update() function, forcing a repaint of the widget
    with the new rendering preferences.

    The QWidget::update() slot does not cause an immediate repaint;
    instead it schedules a paint event for processing when Qt returns
    to the main event loop.

    \skipto paintEvent
    \printuntil setRenderHint

    A paint event is a request to repaint all or parts of the
    widget. The paintEvent() function is an event handler that can be
    reimplemented to receive the widget's paint events. We reimplement
    the event handler to render the \c RenderArea widget's painter
    path.

    First, we create a QPainter for the \c RenderArea instance, and
    set the painter's render hints. The QPainter::RenderHints are used
    to specify flags to QPainter that may, or may not, be respected by
    any given engine. QPainter::Antialiasing indicates that the engine
    should anti-alias the edges of primitives if possible, i.e. put
    additional pixels around the original ones to smooth the edges.

    \skipto scale
    \printto setPen

    Then we scale the QPainter's coordinate system to ensure that the
    painter path is rendered in the right size, i.e that it grows with
    the \c RenderArea widget when the application is resized. When we
    constructed the various painter paths, they were all rnedered
    within a square with a 100 pixel width wich is equivalent to \c
    RenderArea::sizeHint(). The QPainter::scale() function scales the
    coordinate system by the \c RenderArea widget's \e current width
    and height divided by 100.

    Now, when we are sure that the painter path has the right size, we
    can translate the coordinate system to make the painter path
    rotate around the \c RenderArea widget's center. After we have
    performed the rotation, we must remember to translate the
    coordinate system back again.

    \skipto setPen
    \printuntil /^\}/

    Then we set the QPainter's pen with the instance's rendering
    preferences. We create a QLinearGradient and set its colors
    corresponding to the \c RenderArea widget's fill colors. Finally,
    we set the QPainter's brush (the gradient is automatically
    converted into a QBrush), and draw the \c RenderArea widget's
    painter path using the QPainter::drawPath() function.
*/
