File indexing completed on 2024-05-12 15:56:43

0001 /* This file is part of the KDE project
0002    SPDX-FileCopyrightText: 2006 Thorsten Zachmann <zachmann@kde.org>
0003    SPDX-FileCopyrightText: 2007 Thomas Zander <zander@kde.org>
0004    SPDX-FileCopyrightText: 2006-2008 Jan Hambrecht <jaham@gmx.net>
0005 
0006    SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #ifndef KOPATHPOINT_H
0010 #define KOPATHPOINT_H
0011 
0012 #include "kritaflake_export.h"
0013 
0014 #include <QFlags>
0015 
0016 class KoPathShape;
0017 class QPointF;
0018 class QTransform;
0019 class QRectF;
0020 class QPainter;
0021 class KisHandlePainterHelper;
0022 
0023 /**
0024  * @brief A KoPathPoint represents a point in a path.
0025  *
0026  * A KoPathPoint stores a point in a path. Additional to this point
0027  * 2 control points are stored.
0028  * controlPoint1 is used to describe the second point of a cubic
0029  * bezier ending at the point. controlPoint2 is used to describe the
0030  * first point of a cubic bezier curve starting at the point.
0031  */
0032 class KRITAFLAKE_EXPORT KoPathPoint
0033 {
0034 public:
0035     /// property enum
0036     enum PointProperty {
0037         Normal = 0, ///< it has no control points
0038         StartSubpath = 1, ///< it starts a new subpath by a moveTo command
0039         StopSubpath = 2, ///< it stops a subpath (last point of subpath)
0040         CloseSubpath = 8, ///< it closes a subpath (only applicable on StartSubpath and StopSubpath)
0041         IsSmooth = 16, ///< it is smooth, both control points on a line through the point
0042         IsSymmetric = 32 ///< it is symmetric, like smooth but control points have same distance to point
0043     };
0044     Q_DECLARE_FLAGS(PointProperties, PointProperty)
0045 
0046     /// the type for identifying part of a KoPathPoint
0047     enum PointType {
0048         None = 0,
0049         Node = 1,          ///< the node point
0050         ControlPoint1 = 2, ///< the first control point
0051         ControlPoint2 = 4,  ///< the second control point
0052         All = 7
0053     };
0054     Q_DECLARE_FLAGS(PointTypes, PointType)
0055 
0056     /// Default constructor
0057     KoPathPoint();
0058 
0059     /**
0060      * @brief Constructor
0061      *
0062      * @param path is a pointer to the path shape this point is used in
0063      * @param point the position relative to the shape origin
0064      * @param properties describing the point
0065      */
0066     KoPathPoint(KoPathShape *path, const QPointF &point, PointProperties properties = Normal);
0067 
0068     /**
0069      * @brief Copy Constructor
0070      */
0071     KoPathPoint(const KoPathPoint &pathPoint);
0072     KoPathPoint(const KoPathPoint &pathPoint, KoPathShape *newParent);
0073 
0074     /**
0075      * @brief Assignment operator.
0076      */
0077     KoPathPoint& operator=(const KoPathPoint &other);
0078 
0079     /// Compare operator
0080     bool operator == (const KoPathPoint &other) const;
0081 
0082     /**
0083      * @brief Destructor
0084      */
0085     ~KoPathPoint();
0086 
0087     /**
0088      * @brief return the position relative to the shape origin
0089      *
0090      * @return point
0091      */
0092     QPointF point() const;
0093 
0094     /**
0095      * @brief get the control point 1
0096      *
0097      * This points is used for controlling a curve ending at this point
0098      *
0099      * @return control point 1 of this point
0100      */
0101     QPointF controlPoint1() const;
0102 
0103     /**
0104      * @brief get the second control point
0105      *
0106      * This points is used for controlling a curve starting at this point
0107      *
0108      * @return control point 2 of this point
0109      */
0110     QPointF controlPoint2() const;
0111 
0112     /**
0113      * @brief alter the point
0114      *
0115      * @param point to set
0116      */
0117     void setPoint(const QPointF &point);
0118 
0119     /**
0120      * @brief Set the control point 1
0121      *
0122      * @param point to set
0123      */
0124     void setControlPoint1(const QPointF &point);
0125 
0126     /**
0127      * @brief Set the control point 2
0128      *
0129      * @param point to set
0130      */
0131     void setControlPoint2(const QPointF &point);
0132 
0133     /// Removes the first control point
0134     void removeControlPoint1();
0135 
0136     /// Removes the second control point
0137     void removeControlPoint2();
0138 
0139     /**
0140      * @brief Get the properties of a point
0141      *
0142      * @return properties of the point
0143      */
0144     PointProperties properties() const;
0145 
0146     /**
0147      * @brief Set the properties of a point
0148      * @param properties the new properties
0149      */
0150     void setProperties(PointProperties properties);
0151 
0152     /**
0153      * @brief Sets a single property of a point.
0154      * @param property the property to set
0155      */
0156     void setProperty(PointProperty property);
0157 
0158     /**
0159      * @brief Removes a property from the point.
0160      * @param property the property to remove
0161      */
0162     void unsetProperty(PointProperty property);
0163 
0164     /**
0165      * @brief Checks if there is a controlPoint1
0166      *
0167      * The control point is active if a control point was set by
0168      * calling setControlPoint1. However a start point of a subpath
0169      * (StartSubpath) can only have an active control 1 if the
0170      * subpath is closed (CloseSubpath on first and last point).
0171      *
0172      * @return true if control point is active, false otherwise
0173      */
0174     bool activeControlPoint1() const;
0175 
0176     /**
0177      * @brief Checks if there is a controlPoint2
0178      *
0179      * The control point is active if a control point was set by
0180      * calling setControlPoint2. However a end point of a subpath
0181      * (StopSubpath) can only have an active control point 2 if there
0182      * subpath is closed (CloseSubpath on first and last point).
0183      *
0184      * @return true if control point is active, false otherwise
0185      */
0186     bool activeControlPoint2() const;
0187 
0188     /**
0189      * @brief apply matrix on the point
0190      *
0191      * This does a matrix multiplication on all points of the point
0192      *
0193      * @param matrix which will be applied to all points
0194      */
0195     void map(const QTransform &matrix);
0196 
0197     /**
0198      * Paints the path point with the actual brush and pen
0199      * @param painter used for painting the shape point
0200      * @param handleRadius size of point handles in pixel
0201      * @param types the points which should be painted
0202      * @param active If true only the given active points are painted
0203      *               If false all given points are used.
0204      */
0205     void paint(KisHandlePainterHelper &handlesHelper, PointTypes types, bool active = true);
0206 
0207     /**
0208      * @brief Sets the parent path shape.
0209      * @param parent the new parent path shape
0210      */
0211     void setParent(KoPathShape* parent);
0212 
0213     /**
0214      * @brief Get the path shape the point belongs to
0215      * @return the path shape the point belongs to
0216      */
0217     KoPathShape *parent() const;
0218 
0219     /**
0220      * @brief Get the bounding rect of the point.
0221      *
0222      * This takes into account if there are controlpoints
0223      *
0224      * @param active If true only the active points are used in calculation
0225      *               of the bounding rectangle. If false all points are used.
0226      *
0227      * @return bounding rect in document coordinates
0228      */
0229     QRectF boundingRect(bool active = true) const;
0230 
0231     /**
0232      * @brief Reverses the path point.
0233      *
0234      * The control points are swapped and the point properties are adjusted.
0235      * The position dependent properties like StartSubpath and CloseSubpath
0236      * are not changed.
0237      */
0238     void reverse();
0239 
0240     /**
0241      * Returns if this point is a smooth join of adjacent path segments.
0242      *
0243      * The smoothness is defined by the parallelness of the tangents emanating
0244      * from the knot point, i.e. the normalized vectors from the knot to the
0245      * first and second control point.
0246      * The previous and next path points are used to determine the smoothness
0247      * in case this path point has not two control points.
0248      *
0249      * @param previous the previous path point
0250      * @param next the next path point
0251      */
0252     bool isSmooth(KoPathPoint *previous, KoPathPoint *next) const;
0253 
0254 protected:
0255     friend class KoPathShapePrivate;
0256 private:
0257     class Private;
0258     Private * const d;
0259 };
0260 
0261 //   /// a KoSubpath contains a path from a moveTo until a close or a new moveTo
0262 //   typedef QList<KoPathPoint *> KoSubpath;
0263 //   typedef QList<KoSubpath *> KoSubpathList;
0264 //   /// A KoPathSegment is a pair two neighboring KoPathPoints
0265 //   typedef QPair<KoPathPoint*,KoPathPoint*> KoPathSegment;
0266 //   /// The position of a path point within a path shape
0267 //   typedef QPair<KoSubpath*, int> KoPointPosition;
0268 
0269 Q_DECLARE_OPERATORS_FOR_FLAGS(KoPathPoint::PointProperties)
0270 Q_DECLARE_OPERATORS_FOR_FLAGS(KoPathPoint::PointTypes)
0271 
0272 #endif