implement shape basics sw engine.
[platform/core/graphics/tizenvg.git] / src / lib / sw_engine / tvgSwShape.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_SW_SHAPE_H_
18 #define _TVG_SW_SHAPE_H_
19
20 #include "tvgSwCommon.h"
21
22 /************************************************************************/
23 /* Internal Class Implementation                                        */
24 /************************************************************************/
25
26 static void growOutlineContour(SwOutline& outline, size_t n)
27 {
28     if (n == 0) {
29         free(outline.cntrs);
30         outline.cntrs = nullptr;
31         outline.cntrsCnt = 0;
32         outline.reservedCntrsCnt = 0;
33         return;
34     }
35     if (outline.reservedCntrsCnt >= outline.cntrsCnt + n) return;
36
37     cout << "Grow Cntrs: " << outline.reservedCntrsCnt << " -> " << outline.cntrsCnt + n << endl;;
38     outline.reservedCntrsCnt = n;
39     outline.cntrs = static_cast<size_t*>(realloc(outline.cntrs, n * sizeof(size_t)));
40     assert(outline.cntrs);
41 }
42
43
44 static void growOutlinePoint(SwOutline& outline, size_t n)
45 {
46     if (n == 0) {
47         free(outline.pts);
48         outline.pts = nullptr;
49         free(outline.tags);
50         outline.tags = nullptr;
51         outline.reservedPtsCnt = 0;
52         outline.ptsCnt = 0;
53         return;
54     }
55
56     if (outline.reservedPtsCnt >= outline.ptsCnt + n) return;
57
58     cout << "Grow Pts: " << outline.reservedPtsCnt << " -> " << outline.ptsCnt + n << endl;
59     outline.reservedPtsCnt = n;
60     outline.pts = static_cast<Point*>(realloc(outline.pts, n * sizeof(Point)));
61     assert(outline.pts);
62     outline.tags = static_cast<char*>(realloc(outline.tags, n * sizeof(char)));
63     assert(outline.tags);
64 }
65
66
67 static void outlineEnd(SwOutline& outline)
68 {
69     growOutlineContour(outline, 1);
70     if (outline.ptsCnt > 0) {
71         outline.cntrs[outline.cntrsCnt] = outline.ptsCnt - 1;
72         ++outline.cntrs;
73     }
74 }
75
76
77 static void outlineMoveTo(SwOutline& outline, const Point* pt)
78 {
79     assert(pt);
80
81     growOutlinePoint(outline, 1);
82
83     outline.pts[outline.ptsCnt] = *pt;
84     outline.tags[outline.ptsCnt] = SW_CURVE_TAG_ON;
85
86     if (outline.ptsCnt > 0) {
87         growOutlineContour(outline, 1);
88         outline.cntrs[outline.cntrsCnt] = outline.ptsCnt - 1;
89         ++outline.cntrsCnt;
90     }
91
92     ++outline.ptsCnt;
93 }
94
95
96 static void outlineLineTo(SwOutline& outline, const Point* pt)
97 {
98     assert(pt);
99
100     growOutlinePoint(outline, 1);
101
102     outline.pts[outline.ptsCnt] = *pt;
103     outline.tags[outline.ptsCnt] = SW_CURVE_TAG_ON;
104
105     ++outline.ptsCnt;
106 }
107
108
109 static void outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point* ctrl2, const Point* pt)
110 {
111     assert(ctrl1 && ctrl2 && pt);
112
113     growOutlinePoint(outline, 3);
114
115     outline.pts[outline.ptsCnt] = *ctrl1;
116     outline.tags[outline.ptsCnt] = SW_CURVE_TAG_CUBIC;
117     ++outline.ptsCnt;
118
119     outline.pts[outline.ptsCnt] = *ctrl2;
120     outline.tags[outline.ptsCnt] = SW_CURVE_TAG_CUBIC;
121     ++outline.ptsCnt;
122
123     outline.pts[outline.ptsCnt] = *ctrl1;
124     outline.tags[outline.ptsCnt] = SW_CURVE_TAG_ON;
125     ++outline.ptsCnt;
126 }
127
128
129 static bool outlineClose(SwOutline& outline)
130 {
131     size_t i = 0;
132
133     if (outline.cntrsCnt > 0) {
134         i = outline.cntrs[outline.cntrsCnt - 1] + 1;
135     } else {
136         i = 0;   //First Path
137     }
138
139     //Make sure there is at least one point in the current path
140     if (outline.ptsCnt == i) return false;
141
142     //Close the path
143     growOutlinePoint(outline, 1);
144
145     outline.pts[outline.ptsCnt] = outline.pts[i];
146     outline.tags[outline.ptsCnt] = SW_CURVE_TAG_ON;
147     ++outline.ptsCnt;
148
149     return true;
150 }
151
152
153 /************************************************************************/
154 /* External Class Implementation                                        */
155 /************************************************************************/
156
157 bool shapeGenRle(const ShapeNode& shape, SwShape& sdata)
158 {
159     //TODO: rle
160
161     return true;
162 }
163
164
165 bool shapeUpdateBBox(const ShapeNode& shape, SwShape& sdata)
166 {
167     //TODO:
168     return true;
169 }
170
171
172 void shapeDelOutline(const ShapeNode& shape, SwShape& sdata)
173 {
174     if (!sdata.outline) return;
175
176     SwOutline* outline = sdata.outline;
177     if (outline->cntrs) free(outline->cntrs);
178     if (outline->pts) free(outline->pts);
179     if (outline->tags) free(outline->tags);
180     free(outline);
181
182     sdata.outline = nullptr;
183 }
184
185
186 bool shapeGenOutline(const ShapeNode& shape, SwShape& sdata)
187 {
188     const PathCommand* cmds = nullptr;
189     auto cmdCnt = shape.pathCommands(&cmds);
190
191     const Point* pts = nullptr;
192     auto ptsCnt = shape.pathCoords(&pts);
193
194     //No actual shape data
195     if (cmdCnt == 0 || ptsCnt == 0) return false;
196
197     //smart reservation
198     auto outlinePtsCnt = 0;
199     auto outlineCntrsCnt = 0;
200 //    auto closed = false;
201
202     for (auto i = 0; i < cmdCnt; ++i) {
203         switch(*(cmds + i)) {
204             case PathCommand::Close: {
205                 ++outlinePtsCnt;
206                 break;
207             }
208             case PathCommand::MoveTo: {
209                 ++outlineCntrsCnt;
210                 ++outlinePtsCnt;
211                 break;
212             }
213             case PathCommand::LineTo: {
214                 ++outlinePtsCnt;
215                 break;
216             }
217             case PathCommand::CubicTo: {
218                 outlinePtsCnt += 3;
219                 break;
220             }
221         }
222     }
223
224     ++outlinePtsCnt;    //for close
225     ++outlineCntrsCnt;  //for end
226
227     SwOutline* outline = sdata.outline;
228
229     if (!outline) {
230         outline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline)));
231         assert(outline);
232     } else {
233         cout << "Outline was already allocated? How?" << endl;
234     }
235
236     growOutlinePoint(*outline, outlinePtsCnt);
237     growOutlineContour(*outline, outlineCntrsCnt);
238
239     //Generate Outlines
240     while (cmdCnt-- > 0) {
241         switch(*cmds) {
242             case PathCommand::Close: {
243                 outlineClose(*outline);
244                 break;
245             }
246             case PathCommand::MoveTo: {
247                 outlineMoveTo(*outline, pts);
248                 ++pts;
249                 break;
250             }
251             case PathCommand::LineTo: {
252                 outlineLineTo(*outline, pts);
253                 ++pts;
254                 break;
255             }
256             case PathCommand::CubicTo: {
257                 outlineCubicTo(*outline, pts, pts + 1, pts + 2);
258                 pts += 3;
259                 break;
260             }
261         }
262         ++cmds;
263     }
264
265     outlineEnd(*outline);
266
267     sdata.outline = outline;
268
269     return true;
270 }
271
272
273 #endif /* _TVG_SW_SHAPE_H_ */