capi: support c interfaces 97/238397/7
authorHermet Park <chuneon.park@samsung.com>
Mon, 13 Jul 2020 11:19:23 +0000 (20:19 +0900)
committerHermet Park <chuneon.park@samsung.com>
Wed, 15 Jul 2020 07:00:09 +0000 (16:00 +0900)
this capi is under the beta,
we quickly provide this working prototype for collaboration.

Change-Id: Ie246abc306feb9a1305d1b593c4f3ef7f40ab5a9

.gitignore
inc/meson.build
inc/thorvg_capi.h [new file with mode: 0644]
meson.build
meson_options.txt
src/bindings/capi/meson.build [new file with mode: 0644]
src/bindings/capi/tvgCapi.cpp [new file with mode: 0644]
src/bindings/meson.build [new file with mode: 0644]
src/meson.build
test/makefile
test/testCapi.c [new file with mode: 0644]

index 9a64520..b796b5e 100644 (file)
@@ -20,3 +20,4 @@ testRadialGradient
 testGradientTransform
 testSvg
 testAsync
+testCapi
index c598ee5..90e3fc4 100644 (file)
@@ -1,3 +1,7 @@
-install_headers([
-                 'thorvg.h',
-                ])
+header_files = ['thorvg.h']
+
+if get_option('bindings').contains('capi') == true
+    header_files += ['thorvg_capi.h']
+endif
+
+install_headers(header_files)
diff --git a/inc/thorvg_capi.h b/inc/thorvg_capi.h
new file mode 100644 (file)
index 0000000..d2f7f85
--- /dev/null
@@ -0,0 +1,111 @@
+#ifndef __THORVG_CAPI_H__
+#define __THORVG_CAPI_H__
+
+#ifdef TVG_EXPORT
+    #undef TVG_EXPORT
+#endif
+
+#ifdef TVG_BUILD
+    #define TVG_EXPORT __attribute__ ((visibility ("default")))
+#else
+    #define TVG_EXPORT
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _Tvg_Canvas Tvg_Canvas;
+typedef struct _Tvg_Paint Tvg_Paint;
+
+#define TVG_ENGINE_SW (1 << 1)
+#define TVG_ENGINE_GL (1 << 2)
+
+typedef enum {
+    TVG_RESULT_SUCCESS = 0,
+    TVG_RESULT_INVALID_ARGUMENT,
+    TVG_RESULT_INSUFFICIENT_CONDITION,
+    TVG_RESULT_FAILED_ALLOCATION,
+    TVG_RESULT_MEMORY_CORRUPTION,
+    TVG_RESULT_NOT_SUPPORTED,
+    TVG_RESULT_UNKNOWN
+} Tvg_Result;
+
+typedef enum {
+    TVG_PATH_COMMAND_CLOSE = 0,
+    TVG_PATH_COMMAND_MOVE_TO,
+    TVG_PATH_COMMAND_LINE_TO,
+    TVG_PATH_COMMAND_CUBIC_TO
+} Tvg_Path_Command;
+
+typedef enum {
+    TVG_STROKE_CAP_SQUARE = 0,
+    TVG_STROKE_CAP_ROUND,
+    TVG_STROKE_CAP_BUTT
+} Tvg_Stroke_Cap;
+
+typedef enum {
+    TVG_STROKE_JOIN_BEVEL = 0,
+    TVG_STROKE_JOIN_ROUND,
+    TVG_STROKE_JOIN_MITER
+} Tvg_Stroke_Join;
+
+typedef enum {
+    TVG_STROKE_FILL_PAD = 0,
+    TVG_STROKE_FILL_REFLECT,
+    TVG_STROKE_FILL_REPEAT
+} Tvg_Stroke_Fill;
+
+
+typedef struct
+{
+    float x, y;
+} Tvg_Point;
+
+typedef struct
+{
+    float e11, e12, e13;
+    float e21, e22, e23;
+    float e31, e32, e33;
+} Tvg_Matrix;
+
+
+
+TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method);
+TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method);
+
+TVG_EXPORT Tvg_Canvas* tvg_swcanvas_create();
+TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
+
+TVG_EXPORT Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas);
+TVG_EXPORT Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint);
+TVG_EXPORT Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n);
+TVG_EXPORT Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas);
+TVG_EXPORT Tvg_Result tvg_canvas_update(Tvg_Canvas* canvas);
+TVG_EXPORT Tvg_Result tvg_canvas_update_paint(Tvg_Canvas* canvas, Tvg_Paint* paint);
+TVG_EXPORT Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas, unsigned char async);
+TVG_EXPORT Tvg_Result tvg_canvas_sync(Tvg_Canvas* canvas);
+
+TVG_EXPORT Tvg_Paint* tvg_shape_new();
+TVG_EXPORT Tvg_Result tvg_shape_del(Tvg_Paint* paint);
+TVG_EXPORT Tvg_Result tvg_shape_reset(Tvg_Paint* paint);
+TVG_EXPORT Tvg_Result tvg_shape_move_to(Tvg_Paint* paint, float x, float y);
+TVG_EXPORT Tvg_Result tvg_shape_line_to(Tvg_Paint* paint, float x, float y);
+TVG_EXPORT Tvg_Result tvg_shape_cubic_to(Tvg_Paint* paint, float cx1, float cy1, float cx2, float cy2, float x, float y);
+TVG_EXPORT Tvg_Result tvg_shape_close(Tvg_Paint* paint);
+TVG_EXPORT Tvg_Result tvg_shape_append_rect(Tvg_Paint* paint, float x, float y, float w, float h, float rx, float ry);
+TVG_EXPORT Tvg_Result tvg_shape_append_circle(Tvg_Paint* paint, float cx, float cy, float rx, float ry);
+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);
+TVG_EXPORT Tvg_Result tvg_shape_set_stroke_width(Tvg_Paint* paint, float width);
+TVG_EXPORT Tvg_Result tvg_shape_set_stroke_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
+TVG_EXPORT Tvg_Result tvg_shape_set_stroke_dash(Tvg_Paint* paint, const float* dashPattern, uint32_t cnt);
+TVG_EXPORT Tvg_Result tvg_shape_set_stroke_cap(Tvg_Paint* paint, Tvg_Stroke_Cap cap);
+TVG_EXPORT Tvg_Result tvg_shape_set_stroke_join(Tvg_Paint* paint, Tvg_Stroke_Join join);
+TVG_EXPORT Tvg_Result tvg_shape_fill_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_THORVG_CAPI_H_
index d1803a3..6da6d26 100644 (file)
@@ -22,6 +22,10 @@ if get_option('vectors').contains('avx') == true
     config_h.set10('THORVG_AVX_VECTOR_SUPPORT', true)
 endif
 
+if get_option('bindings').contains('capi') == true
+    config_h.set10('THORVG_CAPI_BINDING_SUPPORT', true)
+endif
+
 configure_file(
     output: 'config.h',
     configuration: config_h
index 5a440fa..59d0130 100644 (file)
@@ -15,3 +15,9 @@ option('vectors',
    choices: ['', 'avx'],
    value: [''],
    description: 'Enable CPU Vectorization(SIMD) in thorvg')
+
+option('bindings',
+   type: 'array',
+   choices: ['', 'capi'],
+   value: ['capi'],
+   description: 'Enable C API binding')
diff --git a/src/bindings/capi/meson.build b/src/bindings/capi/meson.build
new file mode 100644 (file)
index 0000000..919442a
--- /dev/null
@@ -0,0 +1,8 @@
+source_file = [
+   'tvgCapi.cpp',
+]
+
+subbinding_dep += [declare_dependency(
+    include_directories : include_directories('.'),
+    sources : source_file
+)]
diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp
new file mode 100644 (file)
index 0000000..37e01af
--- /dev/null
@@ -0,0 +1,214 @@
+#include <thorvg.h>
+#include "thorvg_capi.h"
+
+using namespace std;
+using namespace tvg;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _Tvg_Canvas
+{
+    //Dummy for Direct Casting
+};
+
+struct _Tvg_Paint
+{
+    //Dummy for Direct Casting
+};
+
+
+/************************************************************************/
+/* Engine API                                                           */
+/************************************************************************/
+
+TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method) {
+    Result ret = Result::Success;
+
+    if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw);
+    if (ret != Result::Success) return (Tvg_Result) ret;
+
+    if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl);
+    return (Tvg_Result) ret;
+}
+
+
+TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method) {
+    Result ret = Result::Success;
+
+    if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw);
+    if (ret != Result::Success) return (Tvg_Result) ret;
+
+    if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl);
+    return (Tvg_Result) ret;
+}
+
+/************************************************************************/
+/* Canvas API                                                           */
+/************************************************************************/
+
+TVG_EXPORT Tvg_Canvas* tvg_swcanvas_create()
+{
+    return (Tvg_Canvas*) SwCanvas::gen().release();
+}
+
+
+TVG_EXPORT Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas)
+{
+    delete(canvas);
+    return TVG_RESULT_SUCCESS;
+}
+
+
+TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h)
+{
+    return (Tvg_Result) reinterpret_cast<SwCanvas*>(canvas)->target(buffer, stride, w, h);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_canvas_push(Tvg_Canvas* canvas, Tvg_Paint* paint)
+{
+    return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->push(unique_ptr<Paint>((Paint*)paint));
+}
+
+
+TVG_EXPORT Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n)
+{
+    return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->reserve(n);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas)
+{
+    return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->clear();
+}
+
+
+TVG_EXPORT Tvg_Result tvg_canvas_update(Tvg_Canvas* canvas)
+{
+     return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->update();
+}
+
+
+TVG_EXPORT Tvg_Result tvg_canvas_update_paint(Tvg_Canvas* canvas, Tvg_Paint* paint)
+{
+    return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->update((Paint*) paint);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_canvas_draw(Tvg_Canvas* canvas, unsigned char async)
+{
+    return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->draw(async);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_canvas_sync(Tvg_Canvas* canvas)
+{
+    return (Tvg_Result) reinterpret_cast<Canvas*>(canvas)->sync();
+}
+
+
+/************************************************************************/
+/* Shape API                                                            */
+/************************************************************************/
+
+TVG_EXPORT Tvg_Paint* tvg_shape_new()
+{
+    return (Tvg_Paint*) Shape::gen().release();
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_del(Tvg_Paint* paint)
+{
+    delete(paint);
+    return TVG_RESULT_SUCCESS;
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_reset(Tvg_Paint* paint)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->reset();
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_move_to(Tvg_Paint* paint, float x, float y)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->moveTo(x, y);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_line_to(Tvg_Paint* paint, float x, float y)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->lineTo(x, y);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_cubic_to(Tvg_Paint* paint, float cx1, float cy1, float cx2, float cy2, float x, float y)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->cubicTo(cx1, cy1, cx2, cy2, x, y);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_close(Tvg_Paint* paint)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->close();
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_append_rect(Tvg_Paint* paint, float x, float y, float w, float h, float rx, float ry)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->appendRect(x, y, w, h, rx, ry);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_append_circle(Tvg_Paint* paint, float cx, float cy, float rx, float ry)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->appendCircle(cx, cy, rx, ry);
+}
+
+
+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)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->appendPath((PathCommand*)cmds, cmdCnt, (Point*)pts, ptsCnt);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_set_stroke_width(Tvg_Paint* paint, float width)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke(width);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_set_stroke_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke(r, g, b, a);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_set_stroke_dash(Tvg_Paint* paint, const float* dashPattern, uint32_t cnt)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke(dashPattern, cnt);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_set_stroke_cap(Tvg_Paint* paint, Tvg_Stroke_Cap cap)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke((StrokeCap)cap);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_set_stroke_join(Tvg_Paint* paint, Tvg_Stroke_Join join)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->stroke((StrokeJoin)join);
+}
+
+
+TVG_EXPORT Tvg_Result tvg_shape_fill_color(Tvg_Paint* paint, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
+{
+    return (Tvg_Result) reinterpret_cast<Shape*>(paint)->fill(r, g, b, a);
+}
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/src/bindings/meson.build b/src/bindings/meson.build
new file mode 100644 (file)
index 0000000..2b3a150
--- /dev/null
@@ -0,0 +1,11 @@
+subbinding_dep = []
+
+if get_option('bindings').contains('capi') == true
+    subdir('capi')
+    message('Enable CAPI Bindings')
+endif
+
+binding_dep = declare_dependency(
+   dependencies: subbinding_dep,
+   include_directories : include_directories('.'),
+)
index 6873870..ced59a5 100644 (file)
@@ -11,10 +11,11 @@ endif
 
 subdir('lib')
 subdir('loaders')
+subdir('bindings')
 subdir('examples')
 
 thread_dep = meson.get_compiler('cpp').find_library('pthread')
-thorvg_lib_dep = [common_dep, loader_dep, thread_dep]
+thorvg_lib_dep = [common_dep, loader_dep, binding_dep, thread_dep]
 
 thorvg_lib = library(
        'thorvg',
index 6455a0a..ef9e28a 100644 (file)
@@ -18,3 +18,4 @@ all:
        gcc -o testGradientTransform testGradientTransform.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
        gcc -o testSvg testSvg.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
        gcc -o testAsync testAsync.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
+       gcc -o testCapi testCapi.c -g 'pkg-config --cflags --libs elementary thorvg`
diff --git a/test/testCapi.c b/test/testCapi.c
new file mode 100644 (file)
index 0000000..5b8b91b
--- /dev/null
@@ -0,0 +1,73 @@
+#include <Elementary.h>\r
+#include <thorvg_capi.h>\r
+\r
+#define WIDTH 800\r
+#define HEIGHT 800\r
+\r
+\r
+/************************************************************************/\r
+/* Capi Test Code                                                       */\r
+/************************************************************************/\r
+\r
+static uint32_t buffer[WIDTH * HEIGHT];\r
+\r
+void testCapi()\r
+{\r
+    tvg_engine_init(TVG_ENGINE_SW | TVG_ENGINE_GL);\r
+\r
+    Tvg_Canvas* canvas = tvg_swcanvas_create();\r
+    tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT);\r
+\r
+    Tvg_Paint* shape = tvg_shape_new();\r
+    tvg_shape_append_rect(shape, 0, 0, 200, 200, 0, 0);\r
+    tvg_shape_append_rect(shape, 100, 100, 300, 300, 100, 100);\r
+    tvg_shape_append_circle(shape, 400, 400, 100, 100);\r
+    tvg_shape_append_circle(shape, 400, 500, 170, 100);\r
+    tvg_shape_fill_color(shape, 255, 255, 0, 255);\r
+    tvg_canvas_push(canvas, shape);\r
+\r
+    tvg_canvas_draw(canvas, 1);\r
+    tvg_canvas_sync(canvas);\r
+\r
+    tvg_canvas_destroy(canvas);\r
+\r
+    tvg_engine_term(TVG_ENGINE_SW | TVG_ENGINE_GL);\r
+}\r
+\r
+\r
+/************************************************************************/\r
+/* Main Code                                                            */\r
+/************************************************************************/\r
+\r
+void win_del(void *data, Evas_Object *o, void *ev)\r
+{\r
+   elm_exit();\r
+}\r
+\r
+\r
+int main(int argc, char **argv)\r
+{\r
+    elm_init(argc, argv);\r
+\r
+    Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test");\r
+    evas_object_smart_callback_add(win, "delete,request", win_del, 0);\r
+\r
+    Eo* view = evas_object_image_filled_add(evas_object_evas_get(win));\r
+    evas_object_image_size_set(view, WIDTH, HEIGHT);\r
+    evas_object_image_data_set(view, buffer);\r
+    evas_object_image_pixels_dirty_set(view, EINA_TRUE);\r
+    evas_object_image_data_update_add(view, 0, 0, WIDTH, HEIGHT);\r
+    evas_object_size_hint_weight_set(view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);\r
+    evas_object_show(view);\r
+\r
+    elm_win_resize_object_add(win, view);\r
+    evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT);\r
+    evas_object_show(win);\r
+\r
+    testCapi();\r
+\r
+    elm_run();\r
+    elm_shutdown();\r
+\r
+    return 0;\r
+}\r