📄 qpainterpath.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qpainterpath.h"#include "qpainterpath_p.h"#include <qbitmap.h>#include <qdebug.h>#include <qiodevice.h>#include <qlist.h>#include <qmatrix.h>#include <qpen.h>#include <qpolygon.h>#include <qtextlayout.h>#include <qvarlengtharray.h>#include <private/qbezier_p.h>#include <private/qfontengine_p.h>#include <private/qmath_p.h>#include <private/qnumeric_p.h>#include <private/qobject_p.h>#include <private/qpathclipper_p.h>#include <private/qstroker_p.h>#include <private/qtextengine_p.h>#include <limits.h>#include <math.h>#if 0#include <performance.h>#else#define PM_INIT#define PM_MEASURE(x)#define PM_DISPLAY#endif// This value is used to determine the length of control point vectors// when approximating arc segments as curves. The factor is multiplied// with the radius of the circle.#define KAPPA 0.5522847498// #define QPP_DEBUG// #define QPP_STROKE_DEBUG//#define QPP_FILLPOLYGONS_DEBUGQPainterPath qt_stroke_dash(const QPainterPath &path, qreal *dashes, int dashCount);void qt_find_ellipse_coords(const QRectF &r, qreal angle, qreal length, QPointF* startPoint, QPointF *endPoint){#define ANGLE(t) ((t) * 2 * Q_PI / qreal(360.0)) qreal a = r.width() / qreal(2.0); qreal b = r.height() / qreal(2.0); if (startPoint) { *startPoint = r.center() + QPointF(a * qCos(ANGLE(angle)), -b * qSin(ANGLE(angle))); } if (endPoint) { *endPoint = r.center() + QPointF(a * qCos(ANGLE(angle + length)), -b * qSin(ANGLE(angle + length))); }}#ifdef QPP_DEBUGstatic void qt_debug_path(const QPainterPath &path){ const char *names[] = { "MoveTo ", "LineTo ", "CurveTo ", "CurveToData" }; printf("\nQPainterPath: elementCount=%d\n", path.elementCount()); for (int i=0; i<path.elementCount(); ++i) { const QPainterPath::Element &e = path.elementAt(i); Q_ASSERT(e.type >= 0 && e.type <= QPainterPath::CurveToDataElement); printf(" - %3d:: %s, (%.2f, %.2f)\n", i, names[e.type], e.x, e.y); }}#endif/*! \class QPainterPath \ingroup multimedia \brief 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. Building blocks can be joined in closed subpaths, for example as a rectangle or an ellipse. A closed path has coinciding start and end points. Or they can exist independently as unclosed subpaths, such as lines and curves. A QPainterPath object can be used for filling, outlining, and clipping. To generate fillable outlines for a given painter path, use the QPainterPathStroker class. The main advantage of painter paths over normal drawing operations is that complex shapes only need to be created once; then they can be drawn many times using only calls to the QPainter::drawPath() function. QPainterPath provides a collection of functions that can be used to obtain information about the path and its elements. In addition it is possible to reverse the order of the elements using the toReversed() function. There are also several functions to convert this painter path object into a polygon representation. \tableofcontents \section1 Composing a QPainterPath A QPainterPath object can be constructed as an empty path, with a given start point, or as a copy of another QPainterPath object. Once created, lines and curves can be added to the path using the lineTo(), arcTo(), cubicTo() and quadTo() functions. The lines and curves stretch from the currentPosition() to the position passed as argument. The currentPosition() of the QPainterPath object is always the end position of the last subpath that was added (or the initial start point). Use the moveTo() function to move the currentPosition() without adding a component. The moveTo() function implicitly starts a new subpath, and closes the previous one. Another way of starting a new subpath is to call the closeSubpath() function which closes the current path by adding a line from the currentPosition() back to the path's start position. Note that the new path will have (0, 0) as its initial currentPosition(). QPainterPath class also provides several convenience functions to add closed subpaths to a painter path: addEllipse(), addPath(), addRect(), addRegion() and addText(). The addPolygon() function adds an \e unclosed subpath. In fact, these functions are all collections of moveTo(), lineTo() and cubicTo() operations. In addition, a path can be added to the current path using the connectPath() function. But note that this function will connect the last element of the current path to the first element of given one by adding a line. Below is a code snippet that shows how a QPainterPath object can be used: \table 100% \row \o \inlineimage qpainterpath-construction.png \o \code QPainterPath path; path.addRect(20, 20, 60, 60); path.moveTo(0, 0); path.cubicTo(99, 0, 50, 50, 99, 99); path.cubicTo(0, 99, 50, 50, 0, 0); QPainter painter(this); painter.fillRect(0, 0, 100, 100, Qt::white); painter.setPen(QPen(QColor(79, 106, 25), 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); painter.setBrush(QColor(122, 163, 39)); painter.drawPath(path); \endcode \endtable The painter path is initially empty when constructed. We first add a rectangle, which is a closed subpath. Then we add two bezier curves which together form a closed subpath even though they are not closed individually. Finally we draw the entire path. The path is filled using the default fill rule, Qt::OddEvenFill. Qt provides two methods for filling paths: \table \row \o \inlineimage qt-fillrule-oddeven.png \o \inlineimage qt-fillrule-winding.png \header \o Qt::OddEvenFill \o Qt::WindingFill \endtable See the Qt::FillRule documentation for the definition of the rules. A painter path's currently set fill rule can be retrieved using the fillRule() function, and altered using the setFillRule() function. \section1 QPainterPath Information The QPainterPath class provides a collection of functions that returns information about the path and its elements. The currentPosition() function returns the end point of the last subpath that was added (or the initial start point). The elementAt() function can be used to retrieve the various subpath elements, the \e number of elements can be retrieved using the elementCount() function, and the isEmpty() function tells whether this QPainterPath object contains any elements at all. The controlPointRect() function returns the rectangle containing all the points and control points in this path. This function is significantly faster to compute than the exact boundingRect() which returns the bounding rectangle of this painter path with floating point precision. Finally, QPainterPath provides the contains() function which can be used to determine whether a given point or rectangle is inside the path, and the intersects() function which determines if any of the points inside a given rectangle also are inside this path. \section1 QPainterPath Conversion For compatibility reasons, it might be required to simplify the representation of a painter path: QPainterPath provides the toFillPolygon(), toFillPolygons() and toSubpathPolygons() functions which convert the painter path into a polygon. The toFillPolygon() returns the painter path as one single polygon, while the two latter functions return a list of polygons. The toFillPolygons() and toSubpathPolygons() functions are provided because it is usually faster to draw several small polygons than to draw one large polygon, even though the total number of points drawn is the same. The difference between the two is the \e number of polygons they return: The toSubpathPolygons() creates one polygon for each subpath regardless of intersecting subpaths (i.e. overlapping bounding rectangles), while the toFillPolygons() functions creates only one polygon for overlapping subpaths. The toFillPolygon() and toFillPolygons() functions first convert all the subpaths to polygons, then uses a rewinding technique to make sure that overlapping subpaths can be filled using the correct fill rule. Note that rewinding inserts additional lines in the polygon so the outline of the fill polygon does not match the outline of the path. \section1 Examples Qt provides the \l {painting/painterpaths}{Painter Paths Example} and the \l {demos/deform}{Vector Deformation Demo} which are located in Qt's example and demo directories respectively. The \l {painting/painterpaths}{Painter Paths Example} shows how painter paths can be used to build complex shapes for rendering and lets the user experiment with the filling and stroking. The \l {demos/deform}{Vector Deformation Demo} shows how to use QPainterPath to draw text. \table \row \o \inlineimage qpainterpath-example.png \o \inlineimage qpainterpath-demo.png \header \o \l {painting/painterpaths}{Painter Paths Example} \o \l {demos/deform}{Vector Deformation Demo} \endtable \sa QPainterPathStroker, QPainter, QRegion, {Painter Paths Example}*//*! \enum QPainterPath::ElementType This enum describes the types of elements used to connect vertices in subpaths. Note that elements added as closed subpaths using the addEllipse(), addPath(), addPolygon(), addRect(), addRegion() and addText() convenience functions, is actually added to the path as a collection of separate elements using the moveTo(), lineTo() and cubicTo() functions. \value MoveToElement A new subpath. See also moveTo(). \value LineToElement A line. See also lineTo(). \value CurveToElement A curve. See also cubicTo() and quadTo(). \value CurveToDataElement The extra data required to describe a curve in a CurveToElement element. \sa elementAt(), elementCount()*//*! \class QPainterPath::Element \brief The QPainterPath::Element class specifies the position and type of a subpath. Once a QPainterPath object is constructed, subpaths like lines and curves can be added to the path (creating QPainterPath::LineToElement and QPainterPath::CurveToElement components). The lines and curves stretch from the currentPosition() to the position passed as argument. The currentPosition() of the QPainterPath object is always the end position of the last subpath that was added (or the initial start point). The moveTo() function can be used to move the currentPosition() without adding a line or curve, creating a QPainterPath::MoveToElement component. \sa QPainterPath*//*! \variable QPainterPath::Element::x \brief the x coordinate of the element's position. \sa {operator QPointF()}*//*! \variable QPainterPath::Element::y \brief the y coordinate of the element's position. \sa {operator QPointF()}*//*! \variable QPainterPath::Element::type \brief the type of element \sa isCurveTo(), isLineTo(), isMoveTo()*//*! \fn bool QPainterPath::Element::operator==(const Element &other) const \since 4.2 Returns true if this element is equal to \a other; otherwise returns false. \sa operator!=()*//*! \fn bool QPainterPath::Element::operator!=(const Element &other) const \since 4.2 Returns true if this element is not equal to \a other; otherwise returns false. \sa operator==()*//*! \fn bool QPainterPath::Element::isCurveTo () const Returns true if the element is a curve, otherwise returns false. \sa type, QPainterPath::CurveToElement*//*! \fn bool QPainterPath::Element::isLineTo () const Returns true if the element is a line, otherwise returns false. \sa type, QPainterPath::LineToElement*//*! \fn bool QPainterPath::Element::isMoveTo () const Returns true if the element is moving the current position, otherwise returns false. \sa type, QPainterPath::MoveToElement*//*! \fn QPainterPath::Element::operator QPointF () const Returns the element's position. \sa x, y*//*! \fn void QPainterPath::addEllipse(qreal x, qreal y, qreal width, qreal height) \overload Creates an ellipse within the bounding rectangle defined by its top-left corner at (\a x, \a y), \a width and \a height, and adds it to the painter path as a closed subpath.*//*! \fn void QPainterPath::addText(qreal x, qreal y, const QFont &font, const QString &text) \overload Adds the given \a text to this path as a set of closed subpaths created from the \a font supplied. The subpaths are positioned so that the left end of the text's baseline lies at the point specified by (\a x, \a y).*//*! \fn int QPainterPath::elementCount() const Returns the number of path elements in the painter path.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -