1 /*
2  * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved.
3 
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10 
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13 
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22 
23 #include "../../lv_conf_internal.h"
24 #if LV_USE_THORVG_INTERNAL
25 
26 #include "config.h"
27 #include <string>
28 #include "thorvg.h"
29 #include "thorvg_capi.h"
30 #ifdef THORVG_LOTTIE_LOADER_SUPPORT
31 #include "thorvg_lottie.h"
32 #endif
33 
34 using namespace std;
35 using namespace tvg;
36 
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40 
41 
42 /************************************************************************/
43 /* Engine API                                                           */
44 /************************************************************************/
45 
tvg_engine_init(Tvg_Engine engine_method,unsigned threads)46 TVG_API Tvg_Result tvg_engine_init(Tvg_Engine engine_method, unsigned threads)
47 {
48     return (Tvg_Result) Initializer::init(CanvasEngine(engine_method), threads);
49 }
50 
51 
tvg_engine_term(Tvg_Engine engine_method)52 TVG_API Tvg_Result tvg_engine_term(Tvg_Engine engine_method)
53 {
54     return (Tvg_Result) Initializer::term(CanvasEngine(engine_method));
55 }
56 
57 
tvg_engine_version(uint32_t * major,uint32_t * minor,uint32_t * micro,const char ** version)58 TVG_API Tvg_Result tvg_engine_version(uint32_t* major, uint32_t* minor, uint32_t* micro, const char** version)
59 {
60     if (version) *version = Initializer::version(major, minor, micro);
61     return TVG_RESULT_SUCCESS;
62 }
63 
64 /************************************************************************/
65 /* Canvas API                                                           */
66 /************************************************************************/
67 
tvg_swcanvas_create()68 TVG_API Tvg_Canvas* tvg_swcanvas_create()
69 {
70     return (Tvg_Canvas*) SwCanvas::gen().release();
71 }
72 
73 
tvg_canvas_destroy(Tvg_Canvas * canvas)74 TVG_API Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas)
75 {
76     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
77     delete(reinterpret_cast<Canvas*>(canvas));
78     return TVG_RESULT_SUCCESS;
79 }
80 
81 
tvg_swcanvas_set_mempool(Tvg_Canvas * canvas,Tvg_Mempool_Policy policy)82 TVG_API Tvg_Result tvg_swcanvas_set_mempool(Tvg_Canvas* canvas, Tvg_Mempool_Policy policy)
83 {
84     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
85     return (Tvg_Result) reinterpret_cast<SwCanvas*>(canvas)->mempool(static_cast<SwCanvas::MempoolPolicy>(policy));
86 }
87 
88 
tvg_swcanvas_set_target(Tvg_Canvas * canvas,uint32_t * buffer,uint32_t stride,uint32_t w,uint32_t h,Tvg_Colorspace cs)89 TVG_API Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Tvg_Colorspace cs)
90 {
91     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
92     return (Tvg_Result) reinterpret_cast<SwCanvas*>(canvas)->target(buffer, stride, w, h, static_cast<SwCanvas::Colorspace>(cs));
93 }
94 
95 
tvg_canvas_push(Tvg_Canvas * canvas,Tvg_Paint * paint)96 TVG_API Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint)
97 {
98     if (!canvas || !paint) return TVG_RESULT_INVALID_ARGUMENT;
99     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->push(unique_ptr<Paint>((Paint*)paint));
100 }
101 
102 
tvg_canvas_reserve(Tvg_Canvas * canvas,uint32_t n)103 TVG_API Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n)
104 {
105     return TVG_RESULT_NOT_SUPPORTED;
106 }
107 
108 
tvg_canvas_clear(Tvg_Canvas * canvas,bool free)109 TVG_API Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool free)
110 {
111     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
112     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->clear(free);
113 }
114 
115 
tvg_canvas_update(Tvg_Canvas * canvas)116 TVG_API Tvg_Result tvg_canvas_update(Tvg_Canvas* canvas)
117 {
118     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
119     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->update(nullptr);
120 }
121 
122 
tvg_canvas_update_paint(Tvg_Canvas * canvas,Tvg_Paint * paint)123 TVG_API Tvg_Result tvg_canvas_update_paint(Tvg_Canvas* canvas, Tvg_Paint* paint)
124 {
125     if (!canvas || !paint) return TVG_RESULT_INVALID_ARGUMENT;
126     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->update((Paint*) paint);
127 }
128 
129 
tvg_canvas_draw(Tvg_Canvas * canvas)130 TVG_API Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas)
131 {
132     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
133     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->draw();
134 }
135 
136 
tvg_canvas_sync(Tvg_Canvas * canvas)137 TVG_API Tvg_Result tvg_canvas_sync(Tvg_Canvas* canvas)
138 {
139     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
140     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->sync();
141 }
142 
143 
tvg_canvas_set_viewport(Tvg_Canvas * canvas,int32_t x,int32_t y,int32_t w,int32_t h)144 TVG_API Tvg_Result tvg_canvas_set_viewport(Tvg_Canvas* canvas, int32_t x, int32_t y, int32_t w, int32_t h)
145 {
146     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
147     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->viewport(x, y, w, h);
148 }
149 
150 
151 /************************************************************************/
152 /* Paint API                                                            */
153 /************************************************************************/
154 
tvg_paint_del(Tvg_Paint * paint)155 TVG_API Tvg_Result tvg_paint_del(Tvg_Paint* paint)
156 {
157     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
158     delete(reinterpret_cast<Paint*>(paint));
159     return TVG_RESULT_SUCCESS;
160 }
161 
162 
tvg_paint_scale(Tvg_Paint * paint,float factor)163 TVG_API Tvg_Result tvg_paint_scale(Tvg_Paint* paint, float factor)
164 {
165     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
166     return (Tvg_Result) reinterpret_cast<Paint*>(paint)->scale(factor);
167 }
168 
169 
tvg_paint_rotate(Tvg_Paint * paint,float degree)170 TVG_API Tvg_Result tvg_paint_rotate(Tvg_Paint* paint, float degree)
171 {
172     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
173     return (Tvg_Result) reinterpret_cast<Paint*>(paint)->rotate(degree);
174 }
175 
176 
tvg_paint_translate(Tvg_Paint * paint,float x,float y)177 TVG_API Tvg_Result tvg_paint_translate(Tvg_Paint* paint, float x, float y)
178 {
179     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
180     return (Tvg_Result) reinterpret_cast<Paint*>(paint)->translate(x, y);
181 }
182 
183 
tvg_paint_set_transform(Tvg_Paint * paint,const Tvg_Matrix * m)184 TVG_API Tvg_Result tvg_paint_set_transform(Tvg_Paint* paint, const Tvg_Matrix* m)
185 {
186     if (!paint || !m) return TVG_RESULT_INVALID_ARGUMENT;
187     return (Tvg_Result) reinterpret_cast<Paint*>(paint)->transform(*(reinterpret_cast<const Matrix*>(m)));
188 }
189 
190 
tvg_paint_get_transform(Tvg_Paint * paint,Tvg_Matrix * m)191 TVG_API Tvg_Result tvg_paint_get_transform(Tvg_Paint* paint, Tvg_Matrix* m)
192 {
193     if (!paint || !m) return TVG_RESULT_INVALID_ARGUMENT;
194     *reinterpret_cast<Matrix*>(m) = reinterpret_cast<Paint*>(paint)->transform();
195     return TVG_RESULT_SUCCESS;
196 }
197 
198 
tvg_paint_duplicate(Tvg_Paint * paint)199 TVG_API Tvg_Paint* tvg_paint_duplicate(Tvg_Paint* paint)
200 {
201     if (!paint) return nullptr;
202     return (Tvg_Paint*) reinterpret_cast<Paint*>(paint)->duplicate();
203 }
204 
205 
tvg_paint_set_opacity(Tvg_Paint * paint,uint8_t opacity)206 TVG_API Tvg_Result tvg_paint_set_opacity(Tvg_Paint* paint, uint8_t opacity)
207 {
208     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
209     return (Tvg_Result) reinterpret_cast<Paint*>(paint)->opacity(opacity);
210 }
211 
212 
tvg_paint_get_opacity(const Tvg_Paint * paint,uint8_t * opacity)213 TVG_API Tvg_Result tvg_paint_get_opacity(const Tvg_Paint* paint, uint8_t* opacity)
214 {
215     if (!paint || !opacity)  return TVG_RESULT_INVALID_ARGUMENT;
216     *opacity = reinterpret_cast<const Paint*>(paint)->opacity();
217     return TVG_RESULT_SUCCESS;
218 }
219 
220 
tvg_paint_get_bounds(const Tvg_Paint * paint,float * x,float * y,float * w,float * h,bool transformed)221 TVG_API Tvg_Result tvg_paint_get_bounds(const Tvg_Paint* paint, float* x, float* y, float* w, float* h, bool transformed)
222 {
223    if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
224    return (Tvg_Result) reinterpret_cast<const Paint*>(paint)->bounds(x, y, w, h, transformed);
225 }
226 
227 
tvg_paint_set_composite_method(Tvg_Paint * paint,Tvg_Paint * target,Tvg_Composite_Method method)228 TVG_API Tvg_Result tvg_paint_set_composite_method(Tvg_Paint* paint, Tvg_Paint* target, Tvg_Composite_Method method)
229 {
230    if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
231    return (Tvg_Result) reinterpret_cast<Paint*>(paint)->composite(unique_ptr<Paint>((Paint*)(target)), (CompositeMethod)method);
232 }
233 
234 
tvg_paint_get_composite_method(const Tvg_Paint * paint,const Tvg_Paint ** target,Tvg_Composite_Method * method)235 TVG_API Tvg_Result tvg_paint_get_composite_method(const Tvg_Paint* paint, const Tvg_Paint** target, Tvg_Composite_Method* method)
236 {
237    if (!paint || !target || !method) return TVG_RESULT_INVALID_ARGUMENT;
238    *reinterpret_cast<CompositeMethod*>(method) = reinterpret_cast<const Paint*>(paint)->composite(reinterpret_cast<const Paint**>(target));
239    return TVG_RESULT_SUCCESS;
240 }
241 
242 
tvg_paint_set_blend_method(Tvg_Paint * paint,Tvg_Blend_Method method)243 TVG_API Tvg_Result tvg_paint_set_blend_method(Tvg_Paint* paint, Tvg_Blend_Method method)
244 {
245    if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
246    return (Tvg_Result) reinterpret_cast<Paint*>(paint)->blend((BlendMethod)method);
247 }
248 
249 
tvg_paint_get_type(const Tvg_Paint * paint,Tvg_Type * type)250 TVG_API Tvg_Result tvg_paint_get_type(const Tvg_Paint* paint, Tvg_Type* type)
251 {
252     if (!paint || !type) return TVG_RESULT_INVALID_ARGUMENT;
253     *type = static_cast<Tvg_Type>(reinterpret_cast<const Paint*>(paint)->type());
254     return TVG_RESULT_SUCCESS;
255 }
256 
257 
tvg_paint_set_clip(Tvg_Paint * paint,Tvg_Paint * clipper)258 TVG_API Tvg_Result tvg_paint_set_clip(Tvg_Paint* paint, Tvg_Paint* clipper)
259 {
260    if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
261    return (Tvg_Result) reinterpret_cast<Paint*>(paint)->clip(unique_ptr<Paint>((Paint*)(clipper)));
262 }
263 
264 
tvg_paint_get_identifier(const Tvg_Paint * paint,Tvg_Identifier * identifier)265 TVG_DEPRECATED TVG_API Tvg_Result tvg_paint_get_identifier(const Tvg_Paint* paint, Tvg_Identifier* identifier)
266 {
267     return tvg_paint_get_type(paint, (Tvg_Type*) identifier);
268 }
269 
270 /************************************************************************/
271 /* Shape API                                                            */
272 /************************************************************************/
273 
tvg_shape_new()274 TVG_API Tvg_Paint* tvg_shape_new()
275 {
276     return (Tvg_Paint*) Shape::gen().release();
277 }
278 
279 
tvg_shape_reset(Tvg_Paint * paint)280 TVG_API Tvg_Result tvg_shape_reset(Tvg_Paint* paint)
281 {
282     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
283     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->reset();
284 }
285 
286 
tvg_shape_move_to(Tvg_Paint * paint,float x,float y)287 TVG_API Tvg_Result tvg_shape_move_to(Tvg_Paint* paint, float x, float y)
288 {
289     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
290     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->moveTo(x, y);
291 }
292 
293 
tvg_shape_line_to(Tvg_Paint * paint,float x,float y)294 TVG_API Tvg_Result tvg_shape_line_to(Tvg_Paint* paint, float x, float y)
295 {
296     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
297     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->lineTo(x, y);
298 }
299 
300 
tvg_shape_cubic_to(Tvg_Paint * paint,float cx1,float cy1,float cx2,float cy2,float x,float y)301 TVG_API Tvg_Result tvg_shape_cubic_to(Tvg_Paint* paint, float cx1, float cy1, float cx2, float cy2, float x, float y)
302 {
303     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
304     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->cubicTo(cx1, cy1, cx2, cy2, x, y);
305 }
306 
307 
tvg_shape_close(Tvg_Paint * paint)308 TVG_API Tvg_Result tvg_shape_close(Tvg_Paint* paint)
309 {
310     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
311     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->close();
312 }
313 
314 
tvg_shape_append_rect(Tvg_Paint * paint,float x,float y,float w,float h,float rx,float ry)315 TVG_API Tvg_Result tvg_shape_append_rect(Tvg_Paint* paint, float x, float y, float w, float h, float rx, float ry)
316 {
317     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
318     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->appendRect(x, y, w, h, rx, ry);
319 }
320 
321 
tvg_shape_append_arc(Tvg_Paint * paint,float cx,float cy,float radius,float startAngle,float sweep,uint8_t pie)322 TVG_API Tvg_Result tvg_shape_append_arc(Tvg_Paint* paint, float cx, float cy, float radius, float startAngle, float sweep, uint8_t pie)
323 {
324     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
325     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->appendArc(cx, cy, radius, startAngle, sweep, pie);
326 }
327 
328 
tvg_shape_append_circle(Tvg_Paint * paint,float cx,float cy,float rx,float ry)329 TVG_API Tvg_Result tvg_shape_append_circle(Tvg_Paint* paint, float cx, float cy, float rx, float ry)
330 {
331     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
332     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->appendCircle(cx, cy, rx, ry);
333 }
334 
335 
tvg_shape_append_path(Tvg_Paint * paint,const Tvg_Path_Command * cmds,uint32_t cmdCnt,const Tvg_Point * pts,uint32_t ptsCnt)336 TVG_API Tvg_Result tvg_shape_append_path(Tvg_Paint* paint, const Tvg_Path_Command* cmds, uint32_t cmdCnt, const Tvg_Point* pts, uint32_t ptsCnt)
337 {
338     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
339     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->appendPath((const PathCommand*)cmds, cmdCnt, (const Point*)pts, ptsCnt);
340 }
341 
342 
tvg_shape_get_path_coords(const Tvg_Paint * paint,const Tvg_Point ** pts,uint32_t * cnt)343 TVG_API Tvg_Result tvg_shape_get_path_coords(const Tvg_Paint* paint, const Tvg_Point** pts, uint32_t* cnt)
344 {
345     if (!paint || !pts || !cnt) return TVG_RESULT_INVALID_ARGUMENT;
346     *cnt = reinterpret_cast<const Shape*>(paint)->pathCoords((const Point**)pts);
347     return TVG_RESULT_SUCCESS;
348 }
349 
350 
tvg_shape_get_path_commands(const Tvg_Paint * paint,const Tvg_Path_Command ** cmds,uint32_t * cnt)351 TVG_API Tvg_Result tvg_shape_get_path_commands(const Tvg_Paint* paint, const Tvg_Path_Command** cmds, uint32_t* cnt)
352 {
353     if (!paint || !cmds || !cnt) return TVG_RESULT_INVALID_ARGUMENT;
354     *cnt = reinterpret_cast<const Shape*>(paint)->pathCommands((const PathCommand**)cmds);
355     return TVG_RESULT_SUCCESS;
356 }
357 
358 
tvg_shape_set_stroke_width(Tvg_Paint * paint,float width)359 TVG_API Tvg_Result tvg_shape_set_stroke_width(Tvg_Paint* paint, float width)
360 {
361     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
362     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke(width);
363 }
364 
365 
tvg_shape_get_stroke_width(const Tvg_Paint * paint,float * width)366 TVG_API Tvg_Result tvg_shape_get_stroke_width(const Tvg_Paint* paint, float* width)
367 {
368     if (!paint || !width) return TVG_RESULT_INVALID_ARGUMENT;
369     *width = reinterpret_cast<const Shape*>(paint)->strokeWidth();
370     return TVG_RESULT_SUCCESS;
371 }
372 
373 
tvg_shape_set_stroke_color(Tvg_Paint * paint,uint8_t r,uint8_t g,uint8_t b,uint8_t a)374 TVG_API Tvg_Result tvg_shape_set_stroke_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
375 {
376     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
377     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke(r, g, b, a);
378 }
379 
380 
tvg_shape_get_stroke_color(const Tvg_Paint * paint,uint8_t * r,uint8_t * g,uint8_t * b,uint8_t * a)381 TVG_API Tvg_Result tvg_shape_get_stroke_color(const Tvg_Paint* paint, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a)
382 {
383     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
384     return (Tvg_Result) reinterpret_cast<const Shape*>(paint)->strokeColor(r, g, b, a);
385 }
386 
387 
tvg_shape_set_stroke_linear_gradient(Tvg_Paint * paint,Tvg_Gradient * gradient)388 TVG_API Tvg_Result tvg_shape_set_stroke_linear_gradient(Tvg_Paint* paint, Tvg_Gradient* gradient)
389 {
390     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
391     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke(unique_ptr<LinearGradient>((LinearGradient*)(gradient)));
392 }
393 
394 
tvg_shape_set_stroke_radial_gradient(Tvg_Paint * paint,Tvg_Gradient * gradient)395 TVG_API Tvg_Result tvg_shape_set_stroke_radial_gradient(Tvg_Paint* paint, Tvg_Gradient* gradient)
396 {
397     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
398     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke(unique_ptr<RadialGradient>((RadialGradient*)(gradient)));
399 }
400 
401 
tvg_shape_get_stroke_gradient(const Tvg_Paint * paint,Tvg_Gradient ** gradient)402 TVG_API Tvg_Result tvg_shape_get_stroke_gradient(const Tvg_Paint* paint, Tvg_Gradient** gradient)
403 {
404    if (!paint || !gradient) return TVG_RESULT_INVALID_ARGUMENT;
405    *gradient = (Tvg_Gradient*)(reinterpret_cast<const Shape*>(paint)->strokeFill());
406    return TVG_RESULT_SUCCESS;
407 }
408 
409 
tvg_shape_set_stroke_dash(Tvg_Paint * paint,const float * dashPattern,uint32_t cnt)410 TVG_API Tvg_Result tvg_shape_set_stroke_dash(Tvg_Paint* paint, const float* dashPattern, uint32_t cnt)
411 {
412     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
413     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke(dashPattern, cnt);
414 }
415 
416 
tvg_shape_get_stroke_dash(const Tvg_Paint * paint,const float ** dashPattern,uint32_t * cnt)417 TVG_API Tvg_Result tvg_shape_get_stroke_dash(const Tvg_Paint* paint, const float** dashPattern, uint32_t* cnt)
418 {
419     if (!paint || !cnt || !dashPattern) return TVG_RESULT_INVALID_ARGUMENT;
420     *cnt = reinterpret_cast<const Shape*>(paint)->strokeDash(dashPattern);
421     return TVG_RESULT_SUCCESS;
422 }
423 
424 
tvg_shape_set_stroke_cap(Tvg_Paint * paint,Tvg_Stroke_Cap cap)425 TVG_API Tvg_Result tvg_shape_set_stroke_cap(Tvg_Paint* paint, Tvg_Stroke_Cap cap)
426 {
427     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
428     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke((StrokeCap)cap);
429 }
430 
431 
tvg_shape_get_stroke_cap(const Tvg_Paint * paint,Tvg_Stroke_Cap * cap)432 TVG_API Tvg_Result tvg_shape_get_stroke_cap(const Tvg_Paint* paint, Tvg_Stroke_Cap* cap)
433 {
434     if (!paint || !cap) return TVG_RESULT_INVALID_ARGUMENT;
435     *cap = (Tvg_Stroke_Cap) reinterpret_cast<const Shape*>(paint)->strokeCap();
436     return TVG_RESULT_SUCCESS;
437 }
438 
439 
tvg_shape_set_stroke_join(Tvg_Paint * paint,Tvg_Stroke_Join join)440 TVG_API Tvg_Result tvg_shape_set_stroke_join(Tvg_Paint* paint, Tvg_Stroke_Join join)
441 {
442     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
443     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke((StrokeJoin)join);
444 }
445 
446 
tvg_shape_get_stroke_join(const Tvg_Paint * paint,Tvg_Stroke_Join * join)447 TVG_API Tvg_Result tvg_shape_get_stroke_join(const Tvg_Paint* paint, Tvg_Stroke_Join* join)
448 {
449     if (!paint || !join) return TVG_RESULT_INVALID_ARGUMENT;
450     *join = (Tvg_Stroke_Join) reinterpret_cast<const Shape*>(paint)->strokeJoin();
451     return TVG_RESULT_SUCCESS;
452 }
453 
454 
tvg_shape_set_stroke_miterlimit(Tvg_Paint * paint,float ml)455 TVG_API Tvg_Result tvg_shape_set_stroke_miterlimit(Tvg_Paint* paint, float ml)
456 {
457     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
458     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->strokeMiterlimit(ml);
459 }
460 
461 
tvg_shape_get_stroke_miterlimit(const Tvg_Paint * paint,float * ml)462 TVG_API Tvg_Result tvg_shape_get_stroke_miterlimit(const Tvg_Paint* paint, float* ml)
463 {
464     if (!paint || !ml) return TVG_RESULT_INVALID_ARGUMENT;
465     *ml = reinterpret_cast<const Shape*>(paint)->strokeMiterlimit();
466     return TVG_RESULT_SUCCESS;
467 }
468 
469 
tvg_shape_set_stroke_trim(Tvg_Paint * paint,float begin,float end,bool simultaneous)470 TVG_API Tvg_Result tvg_shape_set_stroke_trim(Tvg_Paint* paint, float begin, float end, bool simultaneous)
471 {
472     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
473     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->strokeTrim(begin, end, simultaneous);
474 }
475 
476 
tvg_shape_set_fill_color(Tvg_Paint * paint,uint8_t r,uint8_t g,uint8_t b,uint8_t a)477 TVG_API Tvg_Result tvg_shape_set_fill_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
478 {
479     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
480     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->fill(r, g, b, a);
481 }
482 
483 
tvg_shape_get_fill_color(const Tvg_Paint * paint,uint8_t * r,uint8_t * g,uint8_t * b,uint8_t * a)484 TVG_API Tvg_Result tvg_shape_get_fill_color(const Tvg_Paint* paint, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a)
485 {
486     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
487     return (Tvg_Result) reinterpret_cast<const Shape*>(paint)->fillColor(r, g, b, a);
488 }
489 
490 
tvg_shape_set_fill_rule(Tvg_Paint * paint,Tvg_Fill_Rule rule)491 TVG_API Tvg_Result tvg_shape_set_fill_rule(Tvg_Paint* paint, Tvg_Fill_Rule rule)
492 {
493     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
494     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->fill((FillRule)rule);
495 }
496 
497 
tvg_shape_get_fill_rule(const Tvg_Paint * paint,Tvg_Fill_Rule * rule)498 TVG_API Tvg_Result tvg_shape_get_fill_rule(const Tvg_Paint* paint, Tvg_Fill_Rule* rule)
499 {
500     if (!paint || !rule) return TVG_RESULT_INVALID_ARGUMENT;
501     *rule = (Tvg_Fill_Rule) reinterpret_cast<const Shape*>(paint)->fillRule();
502     return TVG_RESULT_SUCCESS;
503 }
504 
505 
tvg_shape_set_paint_order(Tvg_Paint * paint,bool strokeFirst)506 TVG_API Tvg_Result tvg_shape_set_paint_order(Tvg_Paint* paint, bool strokeFirst)
507 {
508     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
509     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->order(strokeFirst);
510 }
511 
512 
tvg_shape_set_linear_gradient(Tvg_Paint * paint,Tvg_Gradient * gradient)513 TVG_API Tvg_Result tvg_shape_set_linear_gradient(Tvg_Paint* paint, Tvg_Gradient* gradient)
514 {
515     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
516     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->fill(unique_ptr<LinearGradient>((LinearGradient*)(gradient)));
517 }
518 
519 
tvg_shape_set_radial_gradient(Tvg_Paint * paint,Tvg_Gradient * gradient)520 TVG_API Tvg_Result tvg_shape_set_radial_gradient(Tvg_Paint* paint, Tvg_Gradient* gradient)
521 {
522     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
523     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->fill(unique_ptr<RadialGradient>((RadialGradient*)(gradient)));
524 }
525 
526 
tvg_shape_get_gradient(const Tvg_Paint * paint,Tvg_Gradient ** gradient)527 TVG_API Tvg_Result tvg_shape_get_gradient(const Tvg_Paint* paint, Tvg_Gradient** gradient)
528 {
529    if (!paint || !gradient) return TVG_RESULT_INVALID_ARGUMENT;
530    *gradient = (Tvg_Gradient*)(reinterpret_cast<const Shape*>(paint)->fill());
531    return TVG_RESULT_SUCCESS;
532 }
533 
534 /************************************************************************/
535 /* Picture API                                                          */
536 /************************************************************************/
537 
tvg_picture_new()538 TVG_API Tvg_Paint* tvg_picture_new()
539 {
540     return (Tvg_Paint*) Picture::gen().release();
541 }
542 
543 
tvg_picture_load(Tvg_Paint * paint,const char * path)544 TVG_API Tvg_Result tvg_picture_load(Tvg_Paint* paint, const char* path)
545 {
546     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
547     return (Tvg_Result) reinterpret_cast<Picture*>(paint)->load(path);
548 }
549 
550 
tvg_picture_load_raw(Tvg_Paint * paint,uint32_t * data,uint32_t w,uint32_t h,bool copy)551 TVG_API Tvg_Result tvg_picture_load_raw(Tvg_Paint* paint, uint32_t *data, uint32_t w, uint32_t h, bool copy)
552 {
553     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
554     return (Tvg_Result) reinterpret_cast<Picture*>(paint)->load(data, w, h, copy);
555 }
556 
557 
tvg_picture_load_data(Tvg_Paint * paint,const char * data,uint32_t size,const char * mimetype,bool copy)558 TVG_API Tvg_Result tvg_picture_load_data(Tvg_Paint* paint, const char *data, uint32_t size, const char *mimetype, bool copy)
559 {
560     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
561     return (Tvg_Result) reinterpret_cast<Picture*>(paint)->load(data, size, mimetype ? mimetype : "", copy);
562 }
563 
564 
tvg_picture_set_size(Tvg_Paint * paint,float w,float h)565 TVG_API Tvg_Result tvg_picture_set_size(Tvg_Paint* paint, float w, float h)
566 {
567     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
568     return (Tvg_Result) reinterpret_cast<Picture*>(paint)->size(w, h);
569 }
570 
571 
tvg_picture_get_size(const Tvg_Paint * paint,float * w,float * h)572 TVG_API Tvg_Result tvg_picture_get_size(const Tvg_Paint* paint, float* w, float* h)
573 {
574     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
575     return (Tvg_Result) reinterpret_cast<const Picture*>(paint)->size(w, h);
576 }
577 
578 
tvg_picture_get_paint(Tvg_Paint * paint,uint32_t id)579 TVG_API const Tvg_Paint* tvg_picture_get_paint(Tvg_Paint* paint, uint32_t id)
580 {
581     if (!paint) return nullptr;
582     return (Tvg_Paint*) reinterpret_cast<Picture*>(paint)->paint(id);
583 }
584 
585 
586 /************************************************************************/
587 /* Gradient API                                                         */
588 /************************************************************************/
589 
tvg_linear_gradient_new()590 TVG_API Tvg_Gradient* tvg_linear_gradient_new()
591 {
592     return (Tvg_Gradient*)LinearGradient::gen().release();
593 }
594 
595 
tvg_radial_gradient_new()596 TVG_API Tvg_Gradient* tvg_radial_gradient_new()
597 {
598     return (Tvg_Gradient*)RadialGradient::gen().release();
599 }
600 
601 
tvg_gradient_duplicate(Tvg_Gradient * grad)602 TVG_API Tvg_Gradient* tvg_gradient_duplicate(Tvg_Gradient* grad)
603 {
604     if (!grad) return nullptr;
605     return (Tvg_Gradient*) reinterpret_cast<Fill*>(grad)->duplicate();
606 }
607 
608 
tvg_gradient_del(Tvg_Gradient * grad)609 TVG_API Tvg_Result tvg_gradient_del(Tvg_Gradient* grad)
610 {
611     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
612     delete(reinterpret_cast<Fill*>(grad));
613     return TVG_RESULT_SUCCESS;
614 }
615 
616 
tvg_linear_gradient_set(Tvg_Gradient * grad,float x1,float y1,float x2,float y2)617 TVG_API Tvg_Result tvg_linear_gradient_set(Tvg_Gradient* grad, float x1, float y1, float x2, float y2)
618 {
619     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
620     return (Tvg_Result) reinterpret_cast<LinearGradient*>(grad)->linear(x1, y1, x2, y2);
621 }
622 
623 
tvg_linear_gradient_get(Tvg_Gradient * grad,float * x1,float * y1,float * x2,float * y2)624 TVG_API Tvg_Result tvg_linear_gradient_get(Tvg_Gradient* grad, float* x1, float* y1, float* x2, float* y2)
625 {
626     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
627     return (Tvg_Result) reinterpret_cast<LinearGradient*>(grad)->linear(x1, y1, x2, y2);
628 }
629 
630 
tvg_radial_gradient_set(Tvg_Gradient * grad,float cx,float cy,float radius)631 TVG_API Tvg_Result tvg_radial_gradient_set(Tvg_Gradient* grad, float cx, float cy, float radius)
632 {
633     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
634     return (Tvg_Result) reinterpret_cast<RadialGradient*>(grad)->radial(cx, cy, radius);
635 }
636 
637 
tvg_radial_gradient_get(Tvg_Gradient * grad,float * cx,float * cy,float * radius)638 TVG_API Tvg_Result tvg_radial_gradient_get(Tvg_Gradient* grad, float* cx, float* cy, float* radius)
639 {
640     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
641     return (Tvg_Result) reinterpret_cast<RadialGradient*>(grad)->radial(cx, cy, radius);
642 }
643 
644 
tvg_gradient_set_color_stops(Tvg_Gradient * grad,const Tvg_Color_Stop * color_stop,uint32_t cnt)645 TVG_API Tvg_Result tvg_gradient_set_color_stops(Tvg_Gradient* grad, const Tvg_Color_Stop* color_stop, uint32_t cnt)
646 {
647     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
648     return (Tvg_Result) reinterpret_cast<Fill*>(grad)->colorStops(reinterpret_cast<const Fill::ColorStop*>(color_stop), cnt);
649 }
650 
651 
tvg_gradient_get_color_stops(const Tvg_Gradient * grad,const Tvg_Color_Stop ** color_stop,uint32_t * cnt)652 TVG_API Tvg_Result tvg_gradient_get_color_stops(const Tvg_Gradient* grad, const Tvg_Color_Stop** color_stop, uint32_t* cnt)
653 {
654     if (!grad || !color_stop || !cnt) return TVG_RESULT_INVALID_ARGUMENT;
655     *cnt = reinterpret_cast<const Fill*>(grad)->colorStops(reinterpret_cast<const Fill::ColorStop**>(color_stop));
656     return TVG_RESULT_SUCCESS;
657 }
658 
659 
tvg_gradient_set_spread(Tvg_Gradient * grad,const Tvg_Stroke_Fill spread)660 TVG_API Tvg_Result tvg_gradient_set_spread(Tvg_Gradient* grad, const Tvg_Stroke_Fill spread)
661 {
662     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
663     return (Tvg_Result) reinterpret_cast<Fill*>(grad)->spread((FillSpread)spread);
664 }
665 
666 
tvg_gradient_get_spread(const Tvg_Gradient * grad,Tvg_Stroke_Fill * spread)667 TVG_API Tvg_Result tvg_gradient_get_spread(const Tvg_Gradient* grad, Tvg_Stroke_Fill* spread)
668 {
669     if (!grad || !spread) return TVG_RESULT_INVALID_ARGUMENT;
670     *spread = (Tvg_Stroke_Fill) reinterpret_cast<const Fill*>(grad)->spread();
671     return TVG_RESULT_SUCCESS;
672 }
673 
674 
tvg_gradient_set_transform(Tvg_Gradient * grad,const Tvg_Matrix * m)675 TVG_API Tvg_Result tvg_gradient_set_transform(Tvg_Gradient* grad, const Tvg_Matrix* m)
676 {
677     if (!grad || !m) return TVG_RESULT_INVALID_ARGUMENT;
678     return (Tvg_Result) reinterpret_cast<Fill*>(grad)->transform(*(reinterpret_cast<const Matrix*>(m)));
679 }
680 
681 
tvg_gradient_get_transform(const Tvg_Gradient * grad,Tvg_Matrix * m)682 TVG_API Tvg_Result tvg_gradient_get_transform(const Tvg_Gradient* grad, Tvg_Matrix* m)
683 {
684     if (!grad || !m) return TVG_RESULT_INVALID_ARGUMENT;
685     *reinterpret_cast<Matrix*>(m) = reinterpret_cast<Fill*>(const_cast<Tvg_Gradient*>(grad))->transform();
686     return TVG_RESULT_SUCCESS;
687 }
688 
689 
tvg_gradient_get_type(const Tvg_Gradient * grad,Tvg_Type * type)690 TVG_API Tvg_Result tvg_gradient_get_type(const Tvg_Gradient* grad, Tvg_Type* type)
691 {
692     if (!grad || !type) return TVG_RESULT_INVALID_ARGUMENT;
693     *type = static_cast<Tvg_Type>(reinterpret_cast<const Fill*>(grad)->type());
694     return TVG_RESULT_SUCCESS;
695 }
696 
697 
tvg_gradient_get_identifier(const Tvg_Gradient * grad,Tvg_Identifier * identifier)698 TVG_DEPRECATED TVG_API Tvg_Result tvg_gradient_get_identifier(const Tvg_Gradient* grad, Tvg_Identifier* identifier)
699 {
700     return tvg_gradient_get_type(grad, (Tvg_Type*) identifier);
701 }
702 
703 /************************************************************************/
704 /* Scene API                                                            */
705 /************************************************************************/
706 
tvg_scene_new()707 TVG_API Tvg_Paint* tvg_scene_new()
708 {
709     return (Tvg_Paint*) Scene::gen().release();
710 }
711 
712 
tvg_scene_reserve(Tvg_Paint * scene,uint32_t size)713 TVG_API Tvg_Result tvg_scene_reserve(Tvg_Paint* scene, uint32_t size)
714 {
715     return TVG_RESULT_NOT_SUPPORTED;
716 }
717 
718 
tvg_scene_push(Tvg_Paint * scene,Tvg_Paint * paint)719 TVG_API Tvg_Result tvg_scene_push(Tvg_Paint* scene, Tvg_Paint* paint)
720 {
721     if (!scene || !paint) return TVG_RESULT_INVALID_ARGUMENT;
722     return (Tvg_Result) reinterpret_cast<Scene*>(scene)->push(unique_ptr<Paint>((Paint*)paint));
723 }
724 
725 
tvg_scene_clear(Tvg_Paint * scene,bool free)726 TVG_API Tvg_Result tvg_scene_clear(Tvg_Paint* scene, bool free)
727 {
728     if (!scene) return TVG_RESULT_INVALID_ARGUMENT;
729     return (Tvg_Result) reinterpret_cast<Scene*>(scene)->clear(free);
730 }
731 
732 
733 /************************************************************************/
734 /* Text API                                                            */
735 /************************************************************************/
736 
tvg_text_new()737 TVG_API Tvg_Paint* tvg_text_new()
738 {
739     return (Tvg_Paint*)Text::gen().release();
740 }
741 
742 
tvg_text_set_font(Tvg_Paint * paint,const char * name,float size,const char * style)743 TVG_API Tvg_Result tvg_text_set_font(Tvg_Paint* paint, const char* name, float size, const char* style)
744 {
745     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
746     return (Tvg_Result) reinterpret_cast<Text*>(paint)->font(name, size, style);
747 }
748 
749 
tvg_text_set_text(Tvg_Paint * paint,const char * text)750 TVG_API Tvg_Result tvg_text_set_text(Tvg_Paint* paint, const char* text)
751 {
752     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
753     return (Tvg_Result) reinterpret_cast<Text*>(paint)->text(text);
754 }
755 
756 
tvg_text_set_fill_color(Tvg_Paint * paint,uint8_t r,uint8_t g,uint8_t b)757 TVG_API Tvg_Result tvg_text_set_fill_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b)
758 {
759     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
760     return (Tvg_Result) reinterpret_cast<Text*>(paint)->fill(r, g, b);
761 }
762 
763 
tvg_text_set_gradient(Tvg_Paint * paint,Tvg_Gradient * gradient)764 TVG_API Tvg_Result tvg_text_set_gradient(Tvg_Paint* paint, Tvg_Gradient* gradient)
765 {
766     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
767     return (Tvg_Result) reinterpret_cast<Text*>(paint)->fill(unique_ptr<Fill>((Fill*)(gradient)));
768 }
769 
770 
tvg_font_load(const char * path)771 TVG_API Tvg_Result tvg_font_load(const char* path)
772 {
773     return (Tvg_Result) Text::load(path);
774 }
775 
776 
tvg_font_load_data(const char * name,const char * data,uint32_t size,const char * mimetype,bool copy)777 TVG_API Tvg_Result tvg_font_load_data(const char* name, const char* data, uint32_t size, const char *mimetype, bool copy)
778 {
779     return (Tvg_Result) Text::load(name, data, size, mimetype ? mimetype : "", copy);
780 }
781 
782 
tvg_font_unload(const char * path)783 TVG_API Tvg_Result tvg_font_unload(const char* path)
784 {
785     return (Tvg_Result) Text::unload(path);
786 }
787 
788 
789 /************************************************************************/
790 /* Saver API                                                            */
791 /************************************************************************/
792 
tvg_saver_new()793 TVG_API Tvg_Saver* tvg_saver_new()
794 {
795     return (Tvg_Saver*) Saver::gen().release();
796 }
797 
798 
tvg_saver_save(Tvg_Saver * saver,Tvg_Paint * paint,const char * path,bool compress)799 TVG_API Tvg_Result tvg_saver_save(Tvg_Saver* saver, Tvg_Paint* paint, const char* path, bool compress)
800 {
801     if (!saver || !paint || !path) return TVG_RESULT_INVALID_ARGUMENT;
802     return (Tvg_Result) reinterpret_cast<Saver*>(saver)->save(unique_ptr<Paint>((Paint*)paint), path, compress);
803 }
804 
805 
tvg_saver_sync(Tvg_Saver * saver)806 TVG_API Tvg_Result tvg_saver_sync(Tvg_Saver* saver)
807 {
808     if (!saver) return TVG_RESULT_INVALID_ARGUMENT;
809     return (Tvg_Result) reinterpret_cast<Saver*>(saver)->sync();
810 }
811 
812 
tvg_saver_del(Tvg_Saver * saver)813 TVG_API Tvg_Result tvg_saver_del(Tvg_Saver* saver)
814 {
815     if (!saver) return TVG_RESULT_INVALID_ARGUMENT;
816     delete(reinterpret_cast<Saver*>(saver));
817     return TVG_RESULT_SUCCESS;
818 }
819 
820 
821 /************************************************************************/
822 /* Animation API                                                        */
823 /************************************************************************/
824 
tvg_animation_new()825 TVG_API Tvg_Animation* tvg_animation_new()
826 {
827     return (Tvg_Animation*) Animation::gen().release();
828 }
829 
830 
tvg_animation_set_frame(Tvg_Animation * animation,float no)831 TVG_API Tvg_Result tvg_animation_set_frame(Tvg_Animation* animation, float no)
832 {
833     if (!animation) return TVG_RESULT_INVALID_ARGUMENT;
834     return (Tvg_Result) reinterpret_cast<Animation*>(animation)->frame(no);
835 }
836 
837 
tvg_animation_get_frame(Tvg_Animation * animation,float * no)838 TVG_API Tvg_Result tvg_animation_get_frame(Tvg_Animation* animation, float* no)
839 {
840     if (!animation || !no) return TVG_RESULT_INVALID_ARGUMENT;
841     *no = reinterpret_cast<Animation*>(animation)->curFrame();
842     return TVG_RESULT_SUCCESS;
843 }
844 
845 
tvg_animation_get_total_frame(Tvg_Animation * animation,float * cnt)846 TVG_API Tvg_Result tvg_animation_get_total_frame(Tvg_Animation* animation, float* cnt)
847 {
848     if (!animation || !cnt) return TVG_RESULT_INVALID_ARGUMENT;
849     *cnt = reinterpret_cast<Animation*>(animation)->totalFrame();
850     return TVG_RESULT_SUCCESS;
851 }
852 
853 
tvg_animation_get_picture(Tvg_Animation * animation)854 TVG_API Tvg_Paint* tvg_animation_get_picture(Tvg_Animation* animation)
855 {
856     if (!animation) return nullptr;
857     return (Tvg_Paint*) reinterpret_cast<Animation*>(animation)->picture();
858 }
859 
860 
tvg_animation_get_duration(Tvg_Animation * animation,float * duration)861 TVG_API Tvg_Result tvg_animation_get_duration(Tvg_Animation* animation, float* duration)
862 {
863     if (!animation || !duration) return TVG_RESULT_INVALID_ARGUMENT;
864     *duration = reinterpret_cast<Animation*>(animation)->duration();
865     return TVG_RESULT_SUCCESS;
866 }
867 
868 
tvg_animation_set_segment(Tvg_Animation * animation,float start,float end)869 TVG_API Tvg_Result tvg_animation_set_segment(Tvg_Animation* animation, float start, float end)
870 {
871     if (!animation) return TVG_RESULT_INVALID_ARGUMENT;
872     return (Tvg_Result) reinterpret_cast<Animation*>(animation)->segment(start, end);
873 }
874 
875 
tvg_animation_get_segment(Tvg_Animation * animation,float * start,float * end)876 TVG_API Tvg_Result tvg_animation_get_segment(Tvg_Animation* animation, float* start, float* end)
877 {
878     if (!animation) return TVG_RESULT_INVALID_ARGUMENT;
879     return (Tvg_Result) reinterpret_cast<Animation*>(animation)->segment(start, end);
880 }
881 
882 
tvg_animation_del(Tvg_Animation * animation)883 TVG_API Tvg_Result tvg_animation_del(Tvg_Animation* animation)
884 {
885     if (!animation) return TVG_RESULT_INVALID_ARGUMENT;
886     delete(reinterpret_cast<Animation*>(animation));
887     return TVG_RESULT_SUCCESS;
888 }
889 
890 
891 /************************************************************************/
892 /* Accessor API                                                         */
893 /************************************************************************/
894 
tvg_accessor_generate_id(const char * name)895 TVG_API uint32_t tvg_accessor_generate_id(const char* name)
896 {
897     return Accessor::id(name);
898 }
899 
900 
901 /************************************************************************/
902 /* Lottie Animation API                                                 */
903 /************************************************************************/
904 
tvg_lottie_animation_new()905 TVG_API Tvg_Animation* tvg_lottie_animation_new()
906 {
907 #ifdef THORVG_LOTTIE_LOADER_SUPPORT
908     return (Tvg_Animation*) LottieAnimation::gen().release();
909 #endif
910     return nullptr;
911 }
912 
913 
tvg_lottie_animation_override(Tvg_Animation * animation,const char * slot)914 TVG_API Tvg_Result tvg_lottie_animation_override(Tvg_Animation* animation, const char* slot)
915 {
916 #ifdef THORVG_LOTTIE_LOADER_SUPPORT
917     if (!animation) return TVG_RESULT_INVALID_ARGUMENT;
918     return (Tvg_Result) reinterpret_cast<LottieAnimation*>(animation)->override(slot);
919 #endif
920     return TVG_RESULT_NOT_SUPPORTED;
921 }
922 
923 
tvg_lottie_animation_set_marker(Tvg_Animation * animation,const char * marker)924 TVG_API Tvg_Result tvg_lottie_animation_set_marker(Tvg_Animation* animation, const char* marker)
925 {
926 #ifdef THORVG_LOTTIE_LOADER_SUPPORT
927     if (!animation) return TVG_RESULT_INVALID_ARGUMENT;
928     return (Tvg_Result) reinterpret_cast<LottieAnimation*>(animation)->segment(marker);
929 #endif
930     return TVG_RESULT_NOT_SUPPORTED;
931 }
932 
933 
tvg_lottie_animation_get_markers_cnt(Tvg_Animation * animation,uint32_t * cnt)934 TVG_API Tvg_Result tvg_lottie_animation_get_markers_cnt(Tvg_Animation* animation, uint32_t* cnt)
935 {
936 #ifdef THORVG_LOTTIE_LOADER_SUPPORT
937     if (!animation || !cnt) return TVG_RESULT_INVALID_ARGUMENT;
938     *cnt = reinterpret_cast<LottieAnimation*>(animation)->markersCnt();
939     return TVG_RESULT_SUCCESS;
940 #endif
941     return TVG_RESULT_NOT_SUPPORTED;
942 }
943 
944 
tvg_lottie_animation_get_marker(Tvg_Animation * animation,uint32_t idx,const char ** name)945 TVG_API Tvg_Result tvg_lottie_animation_get_marker(Tvg_Animation* animation, uint32_t idx, const char** name)
946 {
947 #ifdef THORVG_LOTTIE_LOADER_SUPPORT
948     if (!animation || !name) return TVG_RESULT_INVALID_ARGUMENT;
949     *name = reinterpret_cast<LottieAnimation*>(animation)->marker(idx);
950     if (!(*name)) return TVG_RESULT_INVALID_ARGUMENT;
951     return TVG_RESULT_SUCCESS;
952 #endif
953     return TVG_RESULT_NOT_SUPPORTED;
954 }
955 
956 #ifdef __cplusplus
957 }
958 #endif
959 
960 #endif /* LV_USE_THORVG_INTERNAL */
961 
962