432a8a666da012156142cb51fb21333f49b72781
[platform/core/graphics/tizenvg.git] / src / lib / tvgShape.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *               http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  *
16  */
17 #ifndef _TVG_SHAPE_CPP_
18 #define _TVG_SHAPE_CPP_
19
20 #include "tvgCommon.h"
21 #include "tvgShapeImpl.h"
22
23 /************************************************************************/
24 /* Internal Class Implementation                                        */
25 /************************************************************************/
26 constexpr auto PATH_KAPPA = 0.552284f;
27
28
29 /************************************************************************/
30 /* External Class Implementation                                        */
31 /************************************************************************/
32
33 Shape :: Shape() : pImpl(make_unique<Impl>())
34 {
35 }
36
37
38 Shape :: ~Shape()
39 {
40 }
41
42
43 unique_ptr<Shape> Shape::gen() noexcept
44 {
45     return unique_ptr<Shape>(new Shape);
46 }
47
48
49 int Shape::reset() noexcept
50 {
51     auto impl = pImpl.get();
52     assert(impl && impl->path);
53
54     impl->path->reset();
55
56     impl->flag |= RenderUpdateFlag::Path;
57
58     return 0;
59 }
60
61
62 size_t Shape::pathCommands(const PathCommand** cmds) const noexcept
63 {
64     auto impl = pImpl.get();
65     assert(impl && impl->path && cmds);
66
67     *cmds = impl->path->cmds;
68
69     return impl->path->cmdCnt;
70 }
71
72
73 size_t Shape::pathCoords(const Point** pts) const noexcept
74 {
75     auto impl = pImpl.get();
76     assert(impl && impl->path && pts);
77
78     *pts = impl->path->pts;
79
80     return impl->path->ptsCnt;
81 }
82
83
84 int Shape::appendPath(const PathCommand *cmds, size_t cmdCnt, const Point* pts, size_t ptsCnt) noexcept
85 {
86     if (cmdCnt < 0 || ptsCnt < 0) return -1;
87     assert(cmds && pts);
88
89     auto impl = pImpl.get();
90     assert(impl && impl->path);
91
92     impl->path->grow(cmdCnt, ptsCnt);
93     impl->path->append(cmds, cmdCnt, pts, ptsCnt);
94
95     impl->flag |= RenderUpdateFlag::Path;
96
97     return 0;
98 }
99
100
101 int Shape::moveTo(float x, float y) noexcept
102 {
103     auto impl = pImpl.get();
104     assert(impl && impl->path);
105
106     impl->path->moveTo(x, y);
107
108     impl->flag |= RenderUpdateFlag::Path;
109
110     return 0;
111 }
112
113
114 int Shape::lineTo(float x, float y) noexcept
115 {
116     auto impl = pImpl.get();
117     assert(impl && impl->path);
118
119     impl->path->lineTo(x, y);
120
121     impl->flag |= RenderUpdateFlag::Path;
122
123     return 0;
124 }
125
126
127 int Shape::cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) noexcept
128 {
129     auto impl = pImpl.get();
130     assert(impl && impl->path);
131
132     impl->path->cubicTo(cx1, cy1, cx2, cy2, x, y);
133
134     impl->flag |= RenderUpdateFlag::Path;
135
136     return 0;
137 }
138
139
140 int Shape::close() noexcept
141 {
142     auto impl = pImpl.get();
143     assert(impl && impl->path);
144
145     impl->path->close();
146
147     impl->flag |= RenderUpdateFlag::Path;
148
149     return 0;
150 }
151
152
153 int Shape::appendCircle(float cx, float cy, float radiusW, float radiusH) noexcept
154 {
155     auto impl = pImpl.get();
156     assert(impl && impl->path);
157
158     auto halfKappaW = radiusW * PATH_KAPPA;
159     auto halfKappaH = radiusH * PATH_KAPPA;
160
161     impl->path->grow(6, 13);
162     impl->path->moveTo(cx, cy - radiusH);
163     impl->path->cubicTo(cx + halfKappaW, cy - radiusH, cx + radiusW, cy - halfKappaH, cx + radiusW, cy);
164     impl->path->cubicTo(cx + radiusW, cy + halfKappaH, cx + halfKappaW, cy + radiusH, cx, cy + radiusH);
165     impl->path->cubicTo(cx - halfKappaW, cy + radiusH, cx - radiusW, cy + halfKappaH, cx - radiusW, cy);
166     impl->path->cubicTo(cx - radiusW, cy - halfKappaH, cx - halfKappaW, cy - radiusH, cx, cy - radiusH);
167     impl->path->close();
168
169     impl->flag |= RenderUpdateFlag::Path;
170
171     return 0;
172 }
173
174
175 int Shape::appendRect(float x, float y, float w, float h, float cornerRadius) noexcept
176 {
177     auto impl = pImpl.get();
178     assert(impl && impl->path);
179
180     //clamping cornerRadius by minimum size
181     auto min = (w < h ? w : h) * 0.5f;
182     if (cornerRadius > min) cornerRadius = min;
183
184     //rectangle
185     if (cornerRadius == 0) {
186         impl->path->grow(5, 4);
187         impl->path->moveTo(x, y);
188         impl->path->lineTo(x + w, y);
189         impl->path->lineTo(x + w, y + h);
190         impl->path->lineTo(x, y + h);
191         impl->path->close();
192     //circle
193     } else if (w == h && cornerRadius * 2 == w) {
194         return appendCircle(x + (w * 0.5f), y + (h * 0.5f), cornerRadius, cornerRadius);
195     } else {
196         auto halfKappa = cornerRadius * 0.5;
197         impl->path->grow(10, 17);
198         impl->path->moveTo(x + cornerRadius, y);
199         impl->path->lineTo(x + w - cornerRadius, y);
200         impl->path->cubicTo(x + w - cornerRadius + halfKappa, y, x + w, y + cornerRadius - halfKappa, x + w, y + cornerRadius);
201         impl->path->lineTo(x + w, y + h - cornerRadius);
202         impl->path->cubicTo(x + w, y + h - cornerRadius + halfKappa, x + w - cornerRadius + halfKappa, y + h, x + w - cornerRadius, y + h);
203         impl->path->lineTo(x + cornerRadius, y + h);
204         impl->path->cubicTo(x + cornerRadius - halfKappa, y + h, x, y + h - cornerRadius + halfKappa, x, y + h - cornerRadius);
205         impl->path->lineTo(x, y + cornerRadius);
206         impl->path->cubicTo(x, y + cornerRadius - halfKappa, x + cornerRadius - halfKappa, y, x + cornerRadius, y);
207         impl->path->close();
208     }
209
210     impl->flag |= RenderUpdateFlag::Path;
211
212     return 0;
213 }
214
215
216 int Shape::fill(size_t r, size_t g, size_t b, size_t a) noexcept
217 {
218     auto impl = pImpl.get();
219     assert(impl);
220
221     impl->color[0] = r;
222     impl->color[1] = g;
223     impl->color[2] = b;
224     impl->color[3] = a;
225     impl->flag |= RenderUpdateFlag::Fill;
226
227     return 0;
228 }
229
230
231 int Shape::fill(size_t* r, size_t* g, size_t* b, size_t* a) const noexcept
232 {
233     auto impl = pImpl.get();
234     assert(impl);
235
236     if (r) *r = impl->color[0];
237     if (g) *g = impl->color[1];
238     if (b) *b = impl->color[2];
239     if (a) *a = impl->color[3];
240
241     return 0;
242 }
243
244
245 int Shape::scale(float factor) noexcept
246 {
247     auto impl = pImpl.get();
248     assert(impl);
249
250     return impl->scale(factor);
251 }
252
253
254 int Shape::rotate(float degree) noexcept
255 {
256     auto impl = pImpl.get();
257     assert(impl);
258
259     return impl->rotate(degree);
260 }
261
262
263 int Shape::translate(float x, float y) noexcept
264 {
265     auto impl = pImpl.get();
266     assert(impl);
267
268     return impl->translate(x, y);
269 }
270
271
272 int Shape::bounds(float& x, float& y, float& w, float& h) const noexcept
273 {
274     auto impl = pImpl.get();
275     assert(impl);
276
277     if (!impl->bounds(x, y, w, h)) return -1;
278
279     return 0;
280 }
281
282
283 #endif //_TVG_SHAPE_CPP_