updated copyright.
[platform/core/graphics/tizenvg.git] / src / bindings / capi / tvgCapi.cpp
1 /*
2  * Copyright (c) 2020 - 2023 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 <string>
24 #include <thorvg.h>
25 #include "thorvg_capi.h"
26
27 using namespace std;
28 using namespace tvg;
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34
35 /************************************************************************/
36 /* Engine API                                                           */
37 /************************************************************************/
38
39 TVG_EXPORT Tvg_Result tvg_engine_init(Tvg_Engine engine_method, unsigned threads)
40 {
41     return (Tvg_Result) Initializer::init(CanvasEngine(engine_method), threads);
42 }
43
44
45 TVG_EXPORT Tvg_Result tvg_engine_term(Tvg_Engine engine_method)
46 {
47     return (Tvg_Result) Initializer::term(CanvasEngine(engine_method));
48 }
49
50
51 /************************************************************************/
52 /* Canvas API                                                           */
53 /************************************************************************/
54
55 TVG_EXPORT Tvg_Canvas* tvg_swcanvas_create()
56 {
57     return (Tvg_Canvas*) SwCanvas::gen().release();
58 }
59
60
61 TVG_EXPORT Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas)
62 {
63     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
64     delete(reinterpret_cast<Canvas*>(canvas));
65     return TVG_RESULT_SUCCESS;
66 }
67
68
69 TVG_EXPORT Tvg_Result tvg_swcanvas_set_mempool(Tvg_Canvas* canvas, Tvg_Mempool_Policy policy)
70 {
71     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
72     return (Tvg_Result) reinterpret_cast<SwCanvas*>(canvas)->mempool(static_cast<SwCanvas::MempoolPolicy>(policy));
73 }
74
75
76 TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Tvg_Colorspace cs)
77 {
78     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
79     return (Tvg_Result) reinterpret_cast<SwCanvas*>(canvas)->target(buffer, stride, w, h, static_cast<SwCanvas::Colorspace>(cs));
80 }
81
82
83 TVG_EXPORT Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint)
84 {
85     if (!canvas || !paint) return TVG_RESULT_INVALID_ARGUMENT;
86     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->push(unique_ptr<Paint>((Paint*)paint));
87 }
88
89
90 TVG_EXPORT Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n)
91 {
92     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
93     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->reserve(n);
94 }
95
96
97 TVG_EXPORT Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool free)
98 {
99     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
100     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->clear(free);
101 }
102
103
104 TVG_EXPORT Tvg_Result tvg_canvas_update(Tvg_Canvas* canvas)
105 {
106     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
107     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->update(nullptr);
108 }
109
110
111 TVG_EXPORT Tvg_Result tvg_canvas_update_paint(Tvg_Canvas* canvas, Tvg_Paint* paint)
112 {
113     if (!canvas || !paint) return TVG_RESULT_INVALID_ARGUMENT;
114     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->update((Paint*) paint);
115 }
116
117
118 TVG_EXPORT Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas)
119 {
120     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
121     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->draw();
122 }
123
124
125 TVG_EXPORT Tvg_Result tvg_canvas_sync(Tvg_Canvas* canvas)
126 {
127     if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
128     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->sync();
129 }
130
131
132 /************************************************************************/
133 /* Paint API                                                            */
134 /************************************************************************/
135
136 TVG_EXPORT Tvg_Result tvg_paint_del(Tvg_Paint* paint)
137 {
138     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
139     delete(reinterpret_cast<Paint*>(paint));
140     return TVG_RESULT_SUCCESS;
141 }
142
143
144 TVG_EXPORT Tvg_Result tvg_paint_scale(Tvg_Paint* paint, float factor)
145 {
146     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
147     return (Tvg_Result) reinterpret_cast<Paint*>(paint)->scale(factor);
148 }
149
150
151 TVG_EXPORT Tvg_Result tvg_paint_rotate(Tvg_Paint* paint, float degree)
152 {
153     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
154     return (Tvg_Result) reinterpret_cast<Paint*>(paint)->rotate(degree);
155 }
156
157
158 TVG_EXPORT Tvg_Result tvg_paint_translate(Tvg_Paint* paint, float x, float y)
159 {
160     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
161     return (Tvg_Result) reinterpret_cast<Paint*>(paint)->translate(x, y);
162 }
163
164
165 TVG_EXPORT Tvg_Result tvg_paint_set_transform(Tvg_Paint* paint, const Tvg_Matrix* m)
166 {
167     if (!paint || !m) return TVG_RESULT_INVALID_ARGUMENT;
168     return (Tvg_Result) reinterpret_cast<Paint*>(paint)->transform(*(reinterpret_cast<const Matrix*>(m)));
169 }
170
171
172 TVG_EXPORT Tvg_Result tvg_paint_get_transform(Tvg_Paint* paint, Tvg_Matrix* m)
173 {
174     if (!paint || !m) return TVG_RESULT_INVALID_ARGUMENT;
175     *reinterpret_cast<Matrix*>(m) = reinterpret_cast<Paint*>(paint)->transform();
176     return TVG_RESULT_SUCCESS;
177 }
178
179
180 TVG_EXPORT Tvg_Paint* tvg_paint_duplicate(Tvg_Paint* paint)
181 {
182     if (!paint) return nullptr;
183     return (Tvg_Paint*) reinterpret_cast<Paint*>(paint)->duplicate();
184 }
185
186
187 TVG_EXPORT Tvg_Result tvg_paint_set_opacity(Tvg_Paint* paint, uint8_t opacity)
188 {
189     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
190     return (Tvg_Result) reinterpret_cast<Paint*>(paint)->opacity(opacity);
191 }
192
193
194 TVG_EXPORT Tvg_Result tvg_paint_get_opacity(const Tvg_Paint* paint, uint8_t* opacity)
195 {
196     if (!paint || !opacity)  return TVG_RESULT_INVALID_ARGUMENT;
197     *opacity = reinterpret_cast<const Paint*>(paint)->opacity();
198     return TVG_RESULT_SUCCESS;
199 }
200
201
202 TVG_EXPORT Tvg_Result tvg_paint_get_bounds(const Tvg_Paint* paint, float* x, float* y, float* w, float* h, bool transformed)
203 {
204    if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
205    return (Tvg_Result) reinterpret_cast<const Paint*>(paint)->bounds(x, y, w, h, transformed);
206 }
207
208
209 TVG_EXPORT Tvg_Result tvg_paint_set_composite_method(Tvg_Paint* paint, Tvg_Paint* target, Tvg_Composite_Method method)
210 {
211    if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
212    return (Tvg_Result) reinterpret_cast<Paint*>(paint)->composite(unique_ptr<Paint>((Paint*)(target)), (CompositeMethod)method);
213 }
214
215
216 TVG_EXPORT Tvg_Result tvg_paint_get_composite_method(const Tvg_Paint* paint, const Tvg_Paint** target, Tvg_Composite_Method* method)
217 {
218    if (!paint || !target || !method) return TVG_RESULT_INVALID_ARGUMENT;
219    *reinterpret_cast<CompositeMethod*>(method) = reinterpret_cast<const Paint*>(paint)->composite(reinterpret_cast<const Paint**>(target));
220    return TVG_RESULT_SUCCESS;
221 }
222
223
224 /************************************************************************/
225 /* Shape API                                                            */
226 /************************************************************************/
227
228 TVG_EXPORT Tvg_Paint* tvg_shape_new()
229 {
230     return (Tvg_Paint*) Shape::gen().release();
231 }
232
233
234 TVG_EXPORT Tvg_Result tvg_shape_reset(Tvg_Paint* paint)
235 {
236     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
237     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->reset();
238 }
239
240
241 TVG_EXPORT Tvg_Result tvg_shape_move_to(Tvg_Paint* paint, float x, float y)
242 {
243     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
244     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->moveTo(x, y);
245 }
246
247
248 TVG_EXPORT Tvg_Result tvg_shape_line_to(Tvg_Paint* paint, float x, float y)
249 {
250     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
251     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->lineTo(x, y);
252 }
253
254
255 TVG_EXPORT Tvg_Result tvg_shape_cubic_to(Tvg_Paint* paint, float cx1, float cy1, float cx2, float cy2, float x, float y)
256 {
257     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
258     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->cubicTo(cx1, cy1, cx2, cy2, x, y);
259 }
260
261
262 TVG_EXPORT Tvg_Result tvg_shape_close(Tvg_Paint* paint)
263 {
264     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
265     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->close();
266 }
267
268
269 TVG_EXPORT Tvg_Result tvg_shape_append_rect(Tvg_Paint* paint, float x, float y, float w, float h, float rx, float ry)
270 {
271     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
272     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->appendRect(x, y, w, h, rx, ry);
273 }
274
275
276 TVG_EXPORT Tvg_Result tvg_shape_append_arc(Tvg_Paint* paint, float cx, float cy, float radius, float startAngle, float sweep, uint8_t pie)
277 {
278     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
279     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->appendArc(cx, cy, radius, startAngle, sweep, pie);
280 }
281
282
283 TVG_EXPORT Tvg_Result tvg_shape_append_circle(Tvg_Paint* paint, float cx, float cy, float rx, float ry)
284 {
285     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
286     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->appendCircle(cx, cy, rx, ry);
287 }
288
289
290 TVG_EXPORT Tvg_Result tvg_shape_append_path(Tvg_Paint* paint, const Tvg_Path_Command* cmds, uint32_t cmdCnt, const Tvg_Point* pts, uint32_t ptsCnt)
291 {
292     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
293     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->appendPath((const PathCommand*)cmds, cmdCnt, (const Point*)pts, ptsCnt);
294 }
295
296
297 TVG_EXPORT Tvg_Result tvg_shape_get_path_coords(const Tvg_Paint* paint, const Tvg_Point** pts, uint32_t* cnt)
298 {
299     if (!paint || !pts || !cnt) return TVG_RESULT_INVALID_ARGUMENT;
300     *cnt = reinterpret_cast<const Shape*>(paint)->pathCoords((const Point**)pts);
301     return TVG_RESULT_SUCCESS;
302 }
303
304
305 TVG_EXPORT Tvg_Result tvg_shape_get_path_commands(const Tvg_Paint* paint, const Tvg_Path_Command** cmds, uint32_t* cnt)
306 {
307     if (!paint || !cmds || !cnt) return TVG_RESULT_INVALID_ARGUMENT;
308     *cnt = reinterpret_cast<const Shape*>(paint)->pathCommands((const PathCommand**)cmds);
309     return TVG_RESULT_SUCCESS;
310 }
311
312
313 TVG_EXPORT Tvg_Result tvg_shape_set_stroke_width(Tvg_Paint* paint, float width)
314 {
315     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
316     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke(width);
317 }
318
319
320 TVG_EXPORT Tvg_Result tvg_shape_get_stroke_width(const Tvg_Paint* paint, float* width)
321 {
322     if (!paint || !width) return TVG_RESULT_INVALID_ARGUMENT;
323     *width = reinterpret_cast<const Shape*>(paint)->strokeWidth();
324     return TVG_RESULT_SUCCESS;
325 }
326
327
328 TVG_EXPORT Tvg_Result tvg_shape_set_stroke_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
329 {
330     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
331     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke(r, g, b, a);
332 }
333
334
335 TVG_EXPORT Tvg_Result tvg_shape_get_stroke_color(const Tvg_Paint* paint, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a)
336 {
337     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
338     return (Tvg_Result) reinterpret_cast<const Shape*>(paint)->strokeColor(r, g, b, a);
339 }
340
341
342 TVG_EXPORT Tvg_Result tvg_shape_set_stroke_linear_gradient(Tvg_Paint* paint, Tvg_Gradient* gradient)
343 {
344     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
345     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke(unique_ptr<LinearGradient>((LinearGradient*)(gradient)));
346 }
347
348
349 TVG_EXPORT Tvg_Result tvg_shape_set_stroke_radial_gradient(Tvg_Paint* paint, Tvg_Gradient* gradient)
350 {
351     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
352     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke(unique_ptr<RadialGradient>((RadialGradient*)(gradient)));
353 }
354
355
356 TVG_EXPORT Tvg_Result tvg_shape_get_stroke_gradient(const Tvg_Paint* paint, Tvg_Gradient** gradient)
357 {
358    if (!paint || !gradient) return TVG_RESULT_INVALID_ARGUMENT;
359    *gradient = (Tvg_Gradient*)(reinterpret_cast<const Shape*>(paint)->strokeFill());
360    return TVG_RESULT_SUCCESS;
361 }
362
363
364 TVG_EXPORT Tvg_Result tvg_shape_set_stroke_dash(Tvg_Paint* paint, const float* dashPattern, uint32_t cnt)
365 {
366     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
367     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke(dashPattern, cnt);
368 }
369
370
371 TVG_EXPORT Tvg_Result tvg_shape_get_stroke_dash(const Tvg_Paint* paint, const float** dashPattern, uint32_t* cnt)
372 {
373     if (!paint || !cnt || !dashPattern) return TVG_RESULT_INVALID_ARGUMENT;
374     *cnt = reinterpret_cast<const Shape*>(paint)->strokeDash(dashPattern);
375     return TVG_RESULT_SUCCESS;
376 }
377
378
379 TVG_EXPORT Tvg_Result tvg_shape_set_stroke_cap(Tvg_Paint* paint, Tvg_Stroke_Cap cap)
380 {
381     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
382     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke((StrokeCap)cap);
383 }
384
385
386 TVG_EXPORT Tvg_Result tvg_shape_get_stroke_cap(const Tvg_Paint* paint, Tvg_Stroke_Cap* cap)
387 {
388     if (!paint || !cap) return TVG_RESULT_INVALID_ARGUMENT;
389     *cap = (Tvg_Stroke_Cap) reinterpret_cast<const Shape*>(paint)->strokeCap();
390     return TVG_RESULT_SUCCESS;
391 }
392
393
394 TVG_EXPORT Tvg_Result tvg_shape_set_stroke_join(Tvg_Paint* paint, Tvg_Stroke_Join join)
395 {
396     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
397     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke((StrokeJoin)join);
398 }
399
400
401 TVG_EXPORT Tvg_Result tvg_shape_get_stroke_join(const Tvg_Paint* paint, Tvg_Stroke_Join* join)
402 {
403     if (!paint || !join) return TVG_RESULT_INVALID_ARGUMENT;
404     *join = (Tvg_Stroke_Join) reinterpret_cast<const Shape*>(paint)->strokeJoin();
405     return TVG_RESULT_SUCCESS;
406 }
407
408
409 TVG_EXPORT Tvg_Result tvg_shape_set_fill_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
410 {
411     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
412     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->fill(r, g, b, a);
413 }
414
415
416 TVG_EXPORT Tvg_Result tvg_shape_get_fill_color(const Tvg_Paint* paint, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a)
417 {
418     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
419     return (Tvg_Result) reinterpret_cast<const Shape*>(paint)->fillColor(r, g, b, a);
420 }
421
422
423 TVG_EXPORT Tvg_Result tvg_shape_set_fill_rule(Tvg_Paint* paint, Tvg_Fill_Rule rule)
424 {
425     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
426     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->fill((FillRule)rule);
427 }
428
429
430 TVG_EXPORT Tvg_Result tvg_shape_get_fill_rule(const Tvg_Paint* paint, Tvg_Fill_Rule* rule)
431 {
432     if (!paint || !rule) return TVG_RESULT_INVALID_ARGUMENT;
433     *rule = (Tvg_Fill_Rule) reinterpret_cast<const Shape*>(paint)->fillRule();
434     return TVG_RESULT_SUCCESS;
435 }
436
437
438 TVG_EXPORT Tvg_Result tvg_shape_set_linear_gradient(Tvg_Paint* paint, Tvg_Gradient* gradient)
439 {
440     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
441     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->fill(unique_ptr<LinearGradient>((LinearGradient*)(gradient)));
442 }
443
444
445 TVG_EXPORT Tvg_Result tvg_shape_set_radial_gradient(Tvg_Paint* paint, Tvg_Gradient* gradient)
446 {
447     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
448     return (Tvg_Result) reinterpret_cast<Shape*>(paint)->fill(unique_ptr<RadialGradient>((RadialGradient*)(gradient)));
449 }
450
451
452 TVG_EXPORT Tvg_Result tvg_shape_get_gradient(const Tvg_Paint* paint, Tvg_Gradient** gradient)
453 {
454    if (!paint || !gradient) return TVG_RESULT_INVALID_ARGUMENT;
455    *gradient = (Tvg_Gradient*)(reinterpret_cast<const Shape*>(paint)->fill());
456    return TVG_RESULT_SUCCESS;
457 }
458
459 /************************************************************************/
460 /* Picture API                                                          */
461 /************************************************************************/
462
463 TVG_EXPORT Tvg_Paint* tvg_picture_new()
464 {
465     return (Tvg_Paint*) Picture::gen().release();
466 }
467
468
469 TVG_EXPORT Tvg_Result tvg_picture_load(Tvg_Paint* paint, const char* path)
470 {
471     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
472     return (Tvg_Result) reinterpret_cast<Picture*>(paint)->load(path);
473 }
474
475
476 TVG_EXPORT Tvg_Result tvg_picture_load_raw(Tvg_Paint* paint, uint32_t *data, uint32_t w, uint32_t h, bool copy)
477 {
478     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
479     return (Tvg_Result) reinterpret_cast<Picture*>(paint)->load(data, w, h, copy);
480 }
481
482
483 TVG_EXPORT Tvg_Result tvg_picture_load_data(Tvg_Paint* paint, const char *data, uint32_t size, const char *mimetype, bool copy)
484 {
485     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
486     return (Tvg_Result) reinterpret_cast<Picture*>(paint)->load(data, size, mimetype ? mimetype : "", copy);
487 }
488
489
490 TVG_EXPORT Tvg_Result tvg_picture_set_size(Tvg_Paint* paint, float w, float h)
491 {
492     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
493     return (Tvg_Result) reinterpret_cast<Picture*>(paint)->size(w, h);
494 }
495
496
497 TVG_EXPORT Tvg_Result tvg_picture_get_size(const Tvg_Paint* paint, float* w, float* h)
498 {
499     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
500     return (Tvg_Result) reinterpret_cast<const Picture*>(paint)->size(w, h);
501 }
502
503
504 TVG_EXPORT Tvg_Result tvg_picture_get_viewbox(const Tvg_Paint* paint, float* x, float* y, float* w, float* h)
505 {
506     if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
507     return (Tvg_Result) reinterpret_cast<const Picture*>(paint)->viewbox(x, y, w, h);
508 }
509
510
511 /************************************************************************/
512 /* Gradient API                                                         */
513 /************************************************************************/
514
515 TVG_EXPORT Tvg_Gradient* tvg_linear_gradient_new()
516 {
517     return (Tvg_Gradient*)LinearGradient::gen().release();
518 }
519
520
521 TVG_EXPORT Tvg_Gradient* tvg_radial_gradient_new()
522 {
523     return (Tvg_Gradient*)RadialGradient::gen().release();
524 }
525
526
527 TVG_EXPORT Tvg_Gradient* tvg_gradient_duplicate(Tvg_Gradient* grad)
528 {
529     if (!grad) return nullptr;
530     return (Tvg_Gradient*) reinterpret_cast<Fill*>(grad)->duplicate();
531 }
532
533
534 TVG_EXPORT Tvg_Result tvg_gradient_del(Tvg_Gradient* grad)
535 {
536     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
537     delete(reinterpret_cast<Fill*>(grad));
538     return TVG_RESULT_SUCCESS;
539 }
540
541
542 TVG_EXPORT Tvg_Result tvg_linear_gradient_set(Tvg_Gradient* grad, float x1, float y1, float x2, float y2)
543 {
544     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
545     return (Tvg_Result) reinterpret_cast<LinearGradient*>(grad)->linear(x1, y1, x2, y2);
546 }
547
548
549 TVG_EXPORT Tvg_Result tvg_linear_gradient_get(Tvg_Gradient* grad, float* x1, float* y1, float* x2, float* y2)
550 {
551     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
552     return (Tvg_Result) reinterpret_cast<LinearGradient*>(grad)->linear(x1, y1, x2, y2);
553 }
554
555
556 TVG_EXPORT Tvg_Result tvg_radial_gradient_set(Tvg_Gradient* grad, float cx, float cy, float radius)
557 {
558     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
559     return (Tvg_Result) reinterpret_cast<RadialGradient*>(grad)->radial(cx, cy, radius);
560 }
561
562
563 TVG_EXPORT Tvg_Result tvg_radial_gradient_get(Tvg_Gradient* grad, float* cx, float* cy, float* radius)
564 {
565     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
566     return (Tvg_Result) reinterpret_cast<RadialGradient*>(grad)->radial(cx, cy, radius);
567 }
568
569
570 TVG_EXPORT Tvg_Result tvg_gradient_set_color_stops(Tvg_Gradient* grad, const Tvg_Color_Stop* color_stop, uint32_t cnt)
571 {
572     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
573     return (Tvg_Result) reinterpret_cast<Fill*>(grad)->colorStops(reinterpret_cast<const Fill::ColorStop*>(color_stop), cnt);
574 }
575
576
577 TVG_EXPORT Tvg_Result tvg_gradient_get_color_stops(const Tvg_Gradient* grad, const Tvg_Color_Stop** color_stop, uint32_t* cnt)
578 {
579     if (!grad || !color_stop || !cnt) return TVG_RESULT_INVALID_ARGUMENT;
580     *cnt = reinterpret_cast<const Fill*>(grad)->colorStops(reinterpret_cast<const Fill::ColorStop**>(color_stop));
581     return TVG_RESULT_SUCCESS;
582 }
583
584
585 TVG_EXPORT Tvg_Result tvg_gradient_set_spread(Tvg_Gradient* grad, const Tvg_Stroke_Fill spread)
586 {
587     if (!grad) return TVG_RESULT_INVALID_ARGUMENT;
588     return (Tvg_Result) reinterpret_cast<Fill*>(grad)->spread((FillSpread)spread);
589 }
590
591
592 TVG_EXPORT Tvg_Result tvg_gradient_get_spread(const Tvg_Gradient* grad, Tvg_Stroke_Fill* spread)
593 {
594     if (!grad || !spread) return TVG_RESULT_INVALID_ARGUMENT;
595     *spread = (Tvg_Stroke_Fill) reinterpret_cast<const Fill*>(grad)->spread();
596     return TVG_RESULT_SUCCESS;
597 }
598
599
600 TVG_EXPORT Tvg_Result tvg_gradient_set_transform(Tvg_Gradient* grad, const Tvg_Matrix* m)
601 {
602     if (!grad || !m) return TVG_RESULT_INVALID_ARGUMENT;
603     return (Tvg_Result) reinterpret_cast<Fill*>(grad)->transform(*(reinterpret_cast<const Matrix*>(m)));
604 }
605
606
607 TVG_EXPORT Tvg_Result tvg_gradient_get_transform(const Tvg_Gradient* grad, Tvg_Matrix* m)
608 {
609     if (!grad || !m) return TVG_RESULT_INVALID_ARGUMENT;
610     *reinterpret_cast<Matrix*>(m) = reinterpret_cast<Fill*>(const_cast<Tvg_Gradient*>(grad))->transform();
611     return TVG_RESULT_SUCCESS;
612 }
613
614 /************************************************************************/
615 /* Scene API                                                            */
616 /************************************************************************/
617
618 TVG_EXPORT Tvg_Paint* tvg_scene_new()
619 {
620     return (Tvg_Paint*) Scene::gen().release();
621 }
622
623
624 TVG_EXPORT Tvg_Result tvg_scene_reserve(Tvg_Paint* scene, uint32_t size)
625 {
626     if (!scene) return TVG_RESULT_INVALID_ARGUMENT;
627     return (Tvg_Result) reinterpret_cast<Scene*>(scene)->reserve(size);
628 }
629
630
631 TVG_EXPORT Tvg_Result tvg_scene_push(Tvg_Paint* scene, Tvg_Paint* paint)
632 {
633     if (!scene || !paint) return TVG_RESULT_INVALID_ARGUMENT;
634     return (Tvg_Result) reinterpret_cast<Scene*>(scene)->push(unique_ptr<Paint>((Paint*)paint));
635 }
636
637
638 TVG_EXPORT Tvg_Result tvg_scene_clear(Tvg_Paint* scene, bool free)
639 {
640     if (!scene) return TVG_RESULT_INVALID_ARGUMENT;
641     return (Tvg_Result) reinterpret_cast<Scene*>(scene)->clear(free);
642 }
643
644
645 /************************************************************************/
646 /* Saver API                                                            */
647 /************************************************************************/
648
649 TVG_EXPORT Tvg_Saver* tvg_saver_new()
650 {
651     return (Tvg_Saver*) Saver::gen().release();
652 }
653
654
655 TVG_EXPORT Tvg_Result tvg_saver_save(Tvg_Saver* saver, Tvg_Paint* paint, const char* path, bool compress)
656 {
657     if (!saver || !paint || !path) return TVG_RESULT_INVALID_ARGUMENT;
658     return (Tvg_Result) reinterpret_cast<Saver*>(saver)->save(unique_ptr<Paint>((Paint*)paint), path, compress);
659 }
660
661
662 TVG_EXPORT Tvg_Result tvg_saver_sync(Tvg_Saver* saver)
663 {
664     if (!saver) return TVG_RESULT_INVALID_ARGUMENT;
665     return (Tvg_Result) reinterpret_cast<Saver*>(saver)->sync();
666 }
667
668
669 TVG_EXPORT Tvg_Result tvg_saver_del(Tvg_Saver* saver)
670 {
671     if (!saver) return TVG_RESULT_INVALID_ARGUMENT;
672     delete(reinterpret_cast<Saver*>(saver));
673     return TVG_RESULT_SUCCESS;
674 }
675
676 #ifdef __cplusplus
677 }
678 #endif