lottie/vector: move all vector objects to its own namesapce
[platform/core/uifw/lottie-player.git] / src / vector / vraster.cpp
1 #include"vraster.h"
2 #include"v_ft_raster.h"
3 #include"v_ft_stroker.h"
4 #include"vpath.h"
5 #include"vmatrix.h"
6 #include<cstring>
7 #include"vdebug.h"
8
9 V_BEGIN_NAMESPACE
10
11 struct FTOutline
12 {
13 public:
14     FTOutline() = delete;
15     FTOutline(int points, int segments)
16     {
17         ft.points = new SW_FT_Vector[points + segments];
18         ft.tags   = new char[points + segments];
19         ft.contours = new short[segments];
20         ft.n_points = ft.n_contours = 0;
21         ft.flags = 0x0;
22     }
23     void moveTo(const VPointF &pt);
24     void lineTo(const VPointF &pt);
25     void cubicTo(const VPointF &ctr1, const VPointF &ctr2, const VPointF end);
26     void close();
27     void end();
28     void transform(const VMatrix &m);
29     ~FTOutline()
30     {
31         delete[] ft.points;
32         delete[] ft.tags;
33         delete[] ft.contours;
34     }
35     SW_FT_Outline  ft;
36     bool           closed;
37 };
38
39 #define TO_FT_COORD(x) ((x) * 64) // to freetype 26.6 coordinate.
40
41 void FTOutline::transform(const VMatrix &m)
42 {
43     VPointF pt;
44     if (m.isIdentity()) return;
45     for (auto i = 0; i < ft.n_points; i++) {
46         pt = m.map(VPointF(ft.points[i].x/64.0, ft.points[i].y/64.0));
47         ft.points[i].x = TO_FT_COORD(pt.x());
48         ft.points[i].y = TO_FT_COORD(pt.y());
49     }
50 }
51
52 void FTOutline::moveTo(const VPointF &pt)
53 {
54     ft.points[ft.n_points].x = TO_FT_COORD(pt.x());
55     ft.points[ft.n_points].y = TO_FT_COORD(pt.y());
56     ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
57     if (ft.n_points) {
58         ft.contours[ft.n_contours] = ft.n_points - 1;
59         ft.n_contours++;
60     }
61     ft.n_points++;
62     closed = false;
63 }
64
65 void FTOutline::lineTo(const VPointF &pt)
66 {
67     ft.points[ft.n_points].x = TO_FT_COORD(pt.x());
68     ft.points[ft.n_points].y = TO_FT_COORD(pt.y());
69     ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
70     ft.n_points++;
71     closed = false;
72 }
73
74 void FTOutline::cubicTo(const VPointF &cp1, const VPointF &cp2, const VPointF ep)
75 {
76     ft.points[ft.n_points].x = TO_FT_COORD(cp1.x());
77     ft.points[ft.n_points].y = TO_FT_COORD(cp1.y());
78     ft.tags[ft.n_points] = SW_FT_CURVE_TAG_CUBIC;
79     ft.n_points++;
80
81     ft.points[ft.n_points].x = TO_FT_COORD(cp2.x());
82     ft.points[ft.n_points].y = TO_FT_COORD(cp2.y());
83     ft.tags[ft.n_points] = SW_FT_CURVE_TAG_CUBIC;
84     ft.n_points++;
85
86     ft.points[ft.n_points].x = TO_FT_COORD(ep.x());
87     ft.points[ft.n_points].y = TO_FT_COORD(ep.y());
88     ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
89     ft.n_points++;
90     closed = false;
91 }
92 void FTOutline::close()
93 {
94     int index;
95     if (ft.n_contours) {
96         index = ft.contours[ft.n_contours - 1] + 1;
97     } else {
98         index = 0;
99     }
100
101     // make sure atleast 1 point exists in the segment.
102     if (ft.n_points == index) {
103         closed = false;
104         return;
105     }
106
107     ft.points[ft.n_points].x = ft.points[index].x;
108     ft.points[ft.n_points].y = ft.points[index].y;
109     ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
110     ft.n_points++;
111     closed = true;
112 }
113
114 void FTOutline::end()
115 {
116     if (ft.n_points) {
117         ft.contours[ft.n_contours] = ft.n_points - 1;
118         ft.n_contours++;
119     }
120 }
121
122 struct VRasterPrivate
123 {
124 public:
125     VRle generateFillInfoAsync(const SW_FT_Outline *outline);
126     VRle generateStrokeInfoAsync(const SW_FT_Outline *outline, SW_FT_Stroker_LineCap cap,
127                                  SW_FT_Stroker_LineJoin join,
128                                  int width, int meterLimit,
129                                  SW_FT_Bool closed);
130
131     std::mutex        m_rasterAcess;
132     std::mutex        m_strokerAcess;
133     SW_FT_Raster      m_raster;
134     SW_FT_Stroker     m_stroker;
135 };
136
137 struct SpanInfo
138 {
139   VRle::Span *spans;
140   int          size;
141 };
142
143 static void
144 rleGenerationCb( int count, const SW_FT_Span*  spans,void *user)
145 {
146    VRle *rle = (VRle *) user;
147    VRle::Span *rleSpan = (VRle::Span *)spans;
148    rle->addSpan(rleSpan, count);
149 }
150
151 VRle VRasterPrivate::generateFillInfoAsync(const SW_FT_Outline *outline)
152 {
153     m_rasterAcess.lock();
154     VRle rle;
155     SW_FT_Raster_Params params;
156
157     params.flags = SW_FT_RASTER_FLAG_DIRECT | SW_FT_RASTER_FLAG_AA ;
158     params.gray_spans = &rleGenerationCb;
159     params.user = &rle;
160     params.source = outline;
161
162     sw_ft_grays_raster.raster_render(m_raster, &params);
163
164     m_rasterAcess.unlock();
165
166     return rle;
167 }
168
169 VRle VRasterPrivate::generateStrokeInfoAsync(const SW_FT_Outline *outline, SW_FT_Stroker_LineCap cap,
170                                              SW_FT_Stroker_LineJoin join,
171                                              int width, int meterLimit,
172                                              SW_FT_Bool closed)
173 {
174     m_strokerAcess.lock();
175     uint points,contors;
176     SW_FT_Outline strokeOutline = { 0, 0, nullptr, nullptr, nullptr, SW_FT_OUTLINE_NONE };
177
178     SW_FT_Stroker_Set(m_stroker, width, cap, join, meterLimit);
179     SW_FT_Stroker_ParseOutline(m_stroker, outline, !closed);
180     SW_FT_Stroker_GetCounts(m_stroker,&points, &contors);
181
182     strokeOutline.points = (SW_FT_Vector *) calloc(points, sizeof(SW_FT_Vector));
183     strokeOutline.tags = (char *) calloc(points, sizeof(char));
184     strokeOutline.contours = (short *) calloc(contors, sizeof(short));
185
186     SW_FT_Stroker_Export(m_stroker, &strokeOutline);
187
188     m_strokerAcess.unlock();
189
190     VRle rle = generateFillInfoAsync(&strokeOutline);
191
192     // cleanup the outline data.
193     free(strokeOutline.points);
194     free(strokeOutline.tags);
195     free(strokeOutline.contours);
196
197     return rle;
198 }
199
200
201 VRaster::VRaster()
202 {
203     d = new VRasterPrivate;
204     sw_ft_grays_raster.raster_new(&d->m_raster);
205     SW_FT_Stroker_New(&d->m_stroker);
206     SW_FT_Stroker_Set(d->m_stroker, 1 << 6,
207                       SW_FT_STROKER_LINECAP_BUTT, SW_FT_STROKER_LINEJOIN_MITER, 0);
208 }
209
210 VRaster::~VRaster()
211 {
212     sw_ft_grays_raster.raster_done(d->m_raster);
213     SW_FT_Stroker_Done(d->m_stroker);
214 }
215
216 void VRaster::deleteFTOutline(FTOutline *outline)
217 {
218     delete outline;
219 }
220
221 FTOutline *VRaster::toFTOutline(const VPath &path)
222 {
223     if (path.isEmpty())
224         return nullptr;
225
226     const std::vector<VPath::Element> &elements = path.elements();
227     const std::vector<VPointF> &points = path.points();
228
229     FTOutline *outline = new FTOutline(points.size(), path.segments());
230
231     int index = 0;
232     for(auto element : elements) {
233         switch (element){
234         case VPath::Element::MoveTo:
235             outline->moveTo(points[index]);
236             index++;
237             break;
238         case VPath::Element::LineTo:
239             outline->lineTo(points[index]);
240             index++;
241             break;
242         case VPath::Element::CubicTo:
243             outline->cubicTo(points[index], points[index+1], points[index+2]);
244             index = index+3;
245             break;
246         case VPath::Element::Close:
247             outline->close();
248             break;
249         default:
250             break;
251         }
252     }
253     outline->end();
254     return outline;
255 }
256
257 VRle VRaster::generateFillInfo(const FTOutline *outline, FillRule fillRule)
258 {
259     int fillRuleFlag = SW_FT_OUTLINE_NONE;
260     switch (fillRule) {
261     case FillRule::EvenOdd:
262         fillRuleFlag = SW_FT_OUTLINE_EVEN_ODD_FILL;
263         break;
264     default:
265         fillRuleFlag = SW_FT_OUTLINE_NONE;
266         break;
267     }
268     FTOutline *outlineRef = const_cast<FTOutline *>(outline);
269     outlineRef->ft.flags =  fillRuleFlag;
270     return d->generateFillInfoAsync(&outlineRef->ft);
271 }
272
273 VRle VRaster::generateStrokeInfo(const FTOutline *outline, CapStyle cap, JoinStyle join,
274                                  float width, float meterLimit)
275 {
276     SW_FT_Stroker_LineCap ftCap;
277     SW_FT_Stroker_LineJoin ftJoin;
278     int ftWidth;
279     int ftMeterLimit;
280     SW_FT_Bool ftbool = (SW_FT_Bool) outline->closed;
281
282     // map strokeWidth to freetype. It uses as the radius of the pen not the diameter
283     width = width/2.0;
284     // convert to freetype co-ordinate
285     ftWidth = int(width * 64);
286     ftMeterLimit = int(meterLimit * 64);
287
288     // map to freetype capstyle
289     switch (cap)
290       {
291          case CapStyle::Square:
292            ftCap = SW_FT_STROKER_LINECAP_SQUARE;
293            break;
294          case CapStyle::Round:
295            ftCap = SW_FT_STROKER_LINECAP_ROUND;
296            break;
297          default:
298            ftCap = SW_FT_STROKER_LINECAP_BUTT;
299            break;
300       }
301     switch (join)
302       {
303          case JoinStyle::Bevel:
304            ftJoin = SW_FT_STROKER_LINEJOIN_BEVEL;
305            break;
306          case JoinStyle::Round:
307            ftJoin = SW_FT_STROKER_LINEJOIN_ROUND;
308            break;
309          default:
310            ftJoin = SW_FT_STROKER_LINEJOIN_MITER;
311            break;
312       }
313
314     return d->generateStrokeInfoAsync(&outline->ft, ftCap, ftJoin,
315                                       ftWidth, ftMeterLimit, ftbool);
316 }
317
318 V_END_NAMESPACE