capi: support c interfaces

this capi is under the beta,
we quickly provide this working prototype for collaboration.

Change-Id: Ie246abc306feb9a1305d1b593c4f3ef7f40ab5a9
This commit is contained in:
Hermet Park 2020-07-13 20:19:23 +09:00
parent 9e1ba8d2c0
commit 9876d685cf
11 changed files with 438 additions and 4 deletions

1
.gitignore vendored
View file

@ -20,3 +20,4 @@ testRadialGradient
testGradientTransform testGradientTransform
testSvg testSvg
testAsync testAsync
testCapi

View file

@ -1,3 +1,7 @@
install_headers([ header_files = ['thorvg.h']
'thorvg.h',
]) if get_option('bindings').contains('capi') == true
header_files += ['thorvg_capi.h']
endif
install_headers(header_files)

111
inc/thorvg_capi.h Normal file
View file

@ -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_

View file

@ -22,6 +22,10 @@ if get_option('vectors').contains('avx') == true
config_h.set10('THORVG_AVX_VECTOR_SUPPORT', true) config_h.set10('THORVG_AVX_VECTOR_SUPPORT', true)
endif endif
if get_option('bindings').contains('capi') == true
config_h.set10('THORVG_CAPI_BINDING_SUPPORT', true)
endif
configure_file( configure_file(
output: 'config.h', output: 'config.h',
configuration: config_h configuration: config_h

View file

@ -15,3 +15,9 @@ option('vectors',
choices: ['', 'avx'], choices: ['', 'avx'],
value: [''], value: [''],
description: 'Enable CPU Vectorization(SIMD) in thorvg') description: 'Enable CPU Vectorization(SIMD) in thorvg')
option('bindings',
type: 'array',
choices: ['', 'capi'],
value: ['capi'],
description: 'Enable C API binding')

View file

@ -0,0 +1,8 @@
source_file = [
'tvgCapi.cpp',
]
subbinding_dep += [declare_dependency(
include_directories : include_directories('.'),
sources : source_file
)]

View file

@ -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

11
src/bindings/meson.build Normal file
View file

@ -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('.'),
)

View file

@ -11,10 +11,11 @@ endif
subdir('lib') subdir('lib')
subdir('loaders') subdir('loaders')
subdir('bindings')
subdir('examples') subdir('examples')
thread_dep = meson.get_compiler('cpp').find_library('pthread') 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_lib = library(
'thorvg', 'thorvg',

View file

@ -18,3 +18,4 @@ all:
gcc -o testGradientTransform testGradientTransform.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg` 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 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 testAsync testAsync.cpp -g -lstdc++ `pkg-config --cflags --libs elementary thorvg`
gcc -o testCapi testCapi.c -g 'pkg-config --cflags --libs elementary thorvg`

73
test/testCapi.c Normal file
View file

@ -0,0 +1,73 @@
#include <Elementary.h>
#include <thorvg_capi.h>
#define WIDTH 800
#define HEIGHT 800
/************************************************************************/
/* Capi Test Code */
/************************************************************************/
static uint32_t buffer[WIDTH * HEIGHT];
void testCapi()
{
tvg_engine_init(TVG_ENGINE_SW | TVG_ENGINE_GL);
Tvg_Canvas* canvas = tvg_swcanvas_create();
tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT);
Tvg_Paint* shape = tvg_shape_new();
tvg_shape_append_rect(shape, 0, 0, 200, 200, 0, 0);
tvg_shape_append_rect(shape, 100, 100, 300, 300, 100, 100);
tvg_shape_append_circle(shape, 400, 400, 100, 100);
tvg_shape_append_circle(shape, 400, 500, 170, 100);
tvg_shape_fill_color(shape, 255, 255, 0, 255);
tvg_canvas_push(canvas, shape);
tvg_canvas_draw(canvas, 1);
tvg_canvas_sync(canvas);
tvg_canvas_destroy(canvas);
tvg_engine_term(TVG_ENGINE_SW | TVG_ENGINE_GL);
}
/************************************************************************/
/* Main Code */
/************************************************************************/
void win_del(void *data, Evas_Object *o, void *ev)
{
elm_exit();
}
int main(int argc, char **argv)
{
elm_init(argc, argv);
Eo* win = elm_win_util_standard_add(NULL, "ThorVG Test");
evas_object_smart_callback_add(win, "delete,request", win_del, 0);
Eo* view = evas_object_image_filled_add(evas_object_evas_get(win));
evas_object_image_size_set(view, WIDTH, HEIGHT);
evas_object_image_data_set(view, buffer);
evas_object_image_pixels_dirty_set(view, EINA_TRUE);
evas_object_image_data_update_add(view, 0, 0, WIDTH, HEIGHT);
evas_object_size_hint_weight_set(view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_show(view);
elm_win_resize_object_add(win, view);
evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT);
evas_object_show(win);
testCapi();
elm_run();
elm_shutdown();
return 0;
}