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