File indexing completed on 2024-06-09 04:20:49
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Sharaf Zaman <sharafzaz121@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #ifndef SVGMESHPATCH_H 0007 #define SVGMESHPATCH_H 0008 0009 #include <array> 0010 0011 #include <QColor> 0012 #include <QPointF> 0013 #include <QVector> 0014 #include <QMap> 0015 #include <QScopedPointer> 0016 #include <QPainterPath> 0017 0018 #include <KoPathShape.h> 0019 0020 struct SvgMeshStop { 0021 QColor color; 0022 QPointF point; 0023 0024 SvgMeshStop() 0025 {} 0026 0027 SvgMeshStop(QColor color, QPointF point) 0028 : color(color), point(point) 0029 {} 0030 0031 bool isValid() const { return color.isValid(); } 0032 }; 0033 0034 using SvgMeshPath = std::array<QPointF, 4>; 0035 0036 class KRITAFLAKE_EXPORT SvgMeshPatch 0037 { 0038 public: 0039 /// Position of stop in the patch 0040 enum Type { 0041 Top = 0, 0042 Right, 0043 Bottom, 0044 Left, 0045 Size, 0046 }; 0047 0048 SvgMeshPatch(QPointF startingPoint); 0049 SvgMeshPatch(const SvgMeshPatch& other); 0050 0051 // NOTE: NO path is created here 0052 // sets a new starting point for the patch 0053 void moveTo(const QPointF& p); 0054 /// Helper to convert to a cubic curve internally. 0055 void lineTo(const QPointF& p); 0056 /// add points as curve. 0057 void curveTo(const QPointF& c1, const QPointF& c2, const QPointF& p); 0058 0059 /// returns the starting point of the stop 0060 SvgMeshStop getStop(Type type) const; 0061 0062 /// returns the midPoint in parametric space 0063 inline QPointF getMidpointParametric(Type type) const { 0064 return (m_parametricCoords[type] + m_parametricCoords[(type + 1) % Size]) * 0.5; 0065 } 0066 0067 /// get the point on a segment using De Casteljau's algorithm 0068 QPointF segmentPointAt(Type type, qreal t) const; 0069 0070 /// split a segment using De Casteljau's algorithm 0071 QPair<std::array<QPointF, 4>, std::array<QPointF, 4>> segmentSplitAt(Type type, qreal t) const; 0072 0073 /// Get a segment of the path in the meshpatch 0074 std::array<QPointF, 4> getSegment(Type type) const; 0075 0076 /// Get full (closed) meshpath 0077 QPainterPath getPath() const; 0078 0079 /// Get size swept by mesh in pts 0080 QSizeF size() const; 0081 0082 QRectF boundingRect() const; 0083 0084 /// Gets the curve passing through the middle of meshpatch 0085 std::array<QPointF, 4> getMidCurve(bool isVertical) const; 0086 0087 void subdivideHorizontally(QVector<SvgMeshPatch*>& subdivided, 0088 const QVector<QColor>& colors) const; 0089 0090 void subdivideVertically(QVector<SvgMeshPatch*>& subdivided, 0091 const QVector<QColor>& colors) const; 0092 0093 void subdivide(QVector<SvgMeshPatch*>& subdivided, 0094 const QVector<QColor>& colors) const; 0095 0096 bool isDivisibleVertically() const; 0097 bool isDivisibleHorizontally() const; 0098 0099 int countPoints() const; 0100 0101 /* Parses raw pathstr and adds path to the shape, if the path isn't 0102 * complete, it will have to be computed and given with pathIncomplete = true 0103 * (Ideal case for std::optional) 0104 */ 0105 void addStop(const QString& pathStr, QColor color, Type edge, bool pathIncomplete = false, QPointF lastPoint = QPointF()); 0106 0107 /// Adds path to the shape 0108 void addStop(const std::array<QPointF, 4>& pathPoints, QColor color, Type edge); 0109 0110 /// Adds linear path to the shape 0111 void addStopLinear(const std::array<QPointF, 2>& pathPoints, QColor color, Type edge); 0112 0113 void modifyPath(SvgMeshPatch::Type type, std::array<QPointF, 4> newPath); 0114 void modifyCorner(SvgMeshPatch::Type type, const QPointF &delta); 0115 0116 void setStopColor(SvgMeshPatch::Type type, const QColor &color); 0117 0118 void setTransform(const QTransform& matrix); 0119 0120 private: 0121 /* Parses path and adds it to m_path and returns the last point of the curve/line 0122 * see also: SvgMeshPatch::addStop 0123 */ 0124 QPointF parseMeshPath(const QString& path, bool pathIncomplete = false, const QPointF lastPoint = QPointF()); 0125 const char* getCoord(const char* ptr, qreal& number); 0126 0127 private: 0128 bool m_newPath; 0129 int counter {0}; 0130 0131 /// This is the starting point for each path 0132 QPointF m_startingPoint; 0133 0134 std::array<SvgMeshStop, Size> m_nodes; 0135 std::array<std::array<QPointF, 4>, 4> controlPoints; 0136 /// Coordinates in UV space 0137 std::array<QPointF, 4> m_parametricCoords; 0138 }; 0139 0140 #endif // SVGMESHPATCH_H