lottie: optimize VPath::length() api implementation.
[platform/core/uifw/lottie-player.git] / src / vector / vpath.h
1 #ifndef VPATH_H
2 #define VPATH_H
3 #include <vector>
4 #include "vcowptr.h"
5 #include "vmatrix.h"
6 #include "vpoint.h"
7 #include "vrect.h"
8
9 V_BEGIN_NAMESPACE
10
11 struct VPathData;
12 class VPath {
13 public:
14     enum class Direction { CCW, CW };
15
16     enum class Element : uchar { MoveTo, LineTo, CubicTo, Close };
17     bool  empty() const;
18     void  moveTo(const VPointF &p);
19     void  moveTo(float x, float y);
20     void  lineTo(const VPointF &p);
21     void  lineTo(float x, float y);
22     void  cubicTo(const VPointF &c1, const VPointF &c2, const VPointF &e);
23     void  cubicTo(float c1x, float c1y, float c2x, float c2y, float ex,
24                   float ey);
25     void  arcTo(const VRectF &rect, float startAngle, float sweepLength,
26                 bool forceMoveTo);
27     void  close();
28     void  reset();
29     void  reserve(int pts, int elms);
30     int   segments() const;
31     void  addCircle(float cx, float cy, float radius,
32                     VPath::Direction dir = Direction::CW);
33     void  addOval(const VRectF &rect, VPath::Direction dir = Direction::CW);
34     void  addRoundRect(const VRectF &rect, float rx, float ry,
35                        VPath::Direction dir = Direction::CW);
36     void  addRoundRect(const VRectF &rect, float roundness,
37                        VPath::Direction dir = Direction::CW);
38     void  addRect(const VRectF &rect, VPath::Direction dir = Direction::CW);
39     void  addPolystar(float points, float innerRadius, float outerRadius,
40                       float innerRoundness, float outerRoundness,
41                       float startAngle, float cx, float cy,
42                       VPath::Direction dir = Direction::CW);
43     void  addPolygon(float points, float radius, float roundness,
44                      float startAngle, float cx, float cy,
45                      VPath::Direction dir = Direction::CW);
46     void addPath(const VPath &path);
47     void  transform(const VMatrix &m);
48     float length() const;
49     const std::vector<VPath::Element> &elements() const;
50     const std::vector<VPointF> &       points() const;
51     void  clone(const VPath &srcPath);
52
53 private:
54     struct VPathData {
55         bool  empty() const { return m_elements.empty(); }
56         void  moveTo(float x, float y);
57         void  lineTo(float x, float y);
58         void  cubicTo(float cx1, float cy1, float cx2, float cy2, float ex, float ey);
59         void  close();
60         void  reset();
61         void  reserve(int, int);
62         void  checkNewSegment();
63         int   segments() const;
64         void  transform(const VMatrix &m);
65         float length() const;
66         void  addRoundRect(const VRectF &, float, float, VPath::Direction);
67         void  addRoundRect(const VRectF &, float, VPath::Direction);
68         void  addRect(const VRectF &, VPath::Direction);
69         void  arcTo(const VRectF &, float, float, bool);
70         void  addCircle(float, float, float, VPath::Direction);
71         void  addOval(const VRectF &, VPath::Direction);
72         void  addPolystar(float points, float innerRadius, float outerRadius,
73                           float innerRoundness, float outerRoundness,
74                           float startAngle, float cx, float cy,
75                           VPath::Direction dir = Direction::CW);
76         void  addPolygon(float points, float radius, float roundness,
77                          float startAngle, float cx, float cy,
78                          VPath::Direction dir = Direction::CW);
79         void  addPath(const VPathData &path);
80         const std::vector<VPath::Element> &elements() const
81         {
82             return m_elements;
83         }
84         const std::vector<VPointF> &points() const { return m_points; }
85         std::vector<VPointF>        m_points;
86         std::vector<VPath::Element> m_elements;
87         int                         m_segments;
88         VPointF                     mStartPoint;
89         mutable float               mLength{0};
90         mutable bool                mLengthDirty{true};
91         bool                        mNewSegment;
92     };
93
94     vcow_ptr<VPathData> d;
95 };
96
97 inline bool VPath::empty() const
98 {
99     return d->empty();
100 }
101
102 inline void VPath::moveTo(const VPointF &p)
103 {
104     d.write().moveTo(p.x(), p.y());
105 }
106
107 inline void VPath::lineTo(const VPointF &p)
108 {
109     d.write().lineTo(p.x(), p.y());
110 }
111
112 inline void VPath::close()
113 {
114     d.write().close();
115 }
116
117 inline void VPath::reset()
118 {
119     d.write().reset();
120 }
121
122 inline void VPath::reserve(int pts, int elms)
123 {
124     d.write().reserve(pts, elms);
125 }
126
127 inline int VPath::segments() const
128 {
129     return d->segments();
130 }
131
132 inline float VPath::length() const
133 {
134     // TODO re-calculate when there is a change
135     return d->length();
136 }
137
138 inline void VPath::cubicTo(const VPointF &c1, const VPointF &c2,
139                            const VPointF &e)
140 {
141     d.write().cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y());
142 }
143
144 inline void VPath::lineTo(float x, float y)
145 {
146     d.write().lineTo(x, y);
147 }
148
149 inline void VPath::moveTo(float x, float y)
150 {
151     d.write().moveTo(x, y);
152 }
153
154 inline void VPath::cubicTo(float c1x, float c1y, float c2x, float c2y, float ex,
155                            float ey)
156 {
157     d.write().cubicTo(c1x, c1y, c2x, c2y, ex, ey);
158 }
159
160 inline void VPath::transform(const VMatrix &m)
161 {
162     d.write().transform(m);
163 }
164
165 inline void VPath::arcTo(const VRectF &rect, float startAngle,
166                          float sweepLength, bool forceMoveTo)
167 {
168     d.write().arcTo(rect, startAngle, sweepLength, forceMoveTo);
169 }
170
171 inline void VPath::addRect(const VRectF &rect, VPath::Direction dir)
172 {
173     d.write().addRect(rect, dir);
174 }
175
176 inline void VPath::addRoundRect(const VRectF &rect, float rx, float ry,
177                                 VPath::Direction dir)
178 {
179     d.write().addRoundRect(rect, rx, ry, dir);
180 }
181
182 inline void VPath::addRoundRect(const VRectF &rect, float roundness,
183                                 VPath::Direction dir)
184 {
185     d.write().addRoundRect(rect, roundness, dir);
186 }
187
188 inline void VPath::addCircle(float cx, float cy, float radius,
189                              VPath::Direction dir)
190 {
191     d.write().addCircle(cx, cy, radius, dir);
192 }
193
194 inline void VPath::addOval(const VRectF &rect, VPath::Direction dir)
195 {
196     d.write().addOval(rect, dir);
197 }
198
199 inline void VPath::addPolystar(float points, float innerRadius,
200                                float outerRadius, float innerRoundness,
201                                float outerRoundness, float startAngle, float cx,
202                                float cy, VPath::Direction dir)
203 {
204     d.write().addPolystar(points, innerRadius, outerRadius, innerRoundness,
205                           outerRoundness, startAngle, cx, cy, dir);
206 }
207
208 inline void VPath::addPolygon(float points, float radius, float roundness,
209                               float startAngle, float cx, float cy,
210                               VPath::Direction dir)
211 {
212     d.write().addPolygon(points, radius, roundness, startAngle, cx, cy, dir);
213 }
214
215 inline void VPath::addPath(const VPath &path)
216 {
217     if (path.empty()) return;
218
219     if (empty()) {
220         *this = path;
221     } else {
222         d.write().addPath(path.d.read());
223     }
224 }
225
226 inline const std::vector<VPath::Element> &VPath::elements() const
227 {
228     return d->elements();
229 }
230
231 inline const std::vector<VPointF> &VPath::points() const
232 {
233     return d->points();
234 }
235
236 inline void VPath::clone(const VPath &srcPath)
237 {
238    d.write() = srcPath.d.read();
239 }
240
241 V_END_NAMESPACE
242
243 #endif  // VPATH_H