Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions dev/test/premake5.lua
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,10 @@ buildoptions {"-Wall", "-fno-exceptions", "-fno-rtti"}

includedirs {"./include", "../../include"}

files {"../../src/**.cpp", -- the Rive runtime source
"../../test/**.cpp" -- the tests
files {
"../../src/**.cpp", -- the Rive runtime source
"../../test/**.cpp", -- the tests
"../../include/capi/**.cpp",
}

defines {"TESTING", "ENABLE_QUERY_FLAT_VERTICES"}
Expand All @@ -97,4 +99,4 @@ symbols "On"
filter "system:windows"
architecture "x64"
defines {"_USE_MATH_DEFINES"}
buildoptions {WINDOWS_CLANG_CL_SUPPRESSED_WARNINGS}
buildoptions {WINDOWS_CLANG_CL_SUPPRESSED_WARNINGS}
113 changes: 113 additions & 0 deletions include/capi/rive_api.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#include "capi/rive_api.h"

#include "rive/file.hpp"
#include "rive/artboard.hpp"
#include "rive/span.hpp"
#include "rive/scene.hpp"
#include "rive/animation/linear_animation_instance.hpp"
#include "rive/animation/state_machine_instance.hpp"
#include "rive/math/aabb.hpp"

static inline rive_file_t* toC(rive::File* file) { return (rive_file_t*)file; }
static inline rive_artboard_t* toC(rive::ArtboardInstance* abi) { return (rive_artboard_t*)abi; }
static inline rive_scene_t* toC(rive::Scene* scene) { return (rive_scene_t*)scene; }
static inline rive_animation_t* toC(rive::LinearAnimationInstance* anim) {
return (rive_animation_t*)anim;
}
static inline rive_statemachine_t* toC(rive::StateMachineInstance* smi) {
return (rive_statemachine_t*)smi;
}

static inline rive::Factory* toRive(rive_factory_t* factory) { return (rive::Factory*)factory; }
static inline rive::Renderer* toRive(rive_renderer_t* renderer) { return (rive::Renderer*)renderer; }

static inline rive::File* toRive(rive_file_t* file) { return (rive::File*)file; }
static inline rive::ArtboardInstance* toRive(rive_artboard_t* abi) { return (rive::ArtboardInstance*)abi; }
static inline rive::Scene* toRive(rive_scene_t* scene) { return (rive::Scene*)scene; }

#if 0
static inline rive_factory_t* toC(rive::Factory* factory) { return (rive_factory_t*)factory; }
static inline rive_renderer_t* toC(rive::Renderer* renderer) { return (rive_renderer_t*)renderer; }
static inline rive::LinearAnimationInstance* toRive(rive_animation_t* anim) {
return (rive::LinearAnimationInstance*)anim;
}
static inline rive::StateMachineInstance* toRive(rive_statemachine_t* smi) {
return (rive::StateMachineInstance*)smi;
}
#endif

//////////////////////////////////////

void rive_file_delete(rive_file_t* file) { delete toRive(file); }
void rive_artboard_delete(rive_artboard_t* abi) { delete toRive(abi); }
void rive_scene_delete(rive_scene_t* scene) { delete toRive(scene); }

rive_file_t* rive_file_import(rive_span_t cspan, rive_factory_t* factory) {
rive::Span<const uint8_t> span((const uint8_t*)cspan.buffer, cspan.size);
return toC(rive::File::import(span, toRive(factory)).release());
}

int32_t rive_file_artboard_count(rive_file_t* file) {
return toRive(file)->artboardCount();
}

rive_artboard_t* rive_file_artboard_default(rive_file_t* file) {
return toC(toRive(file)->artboardDefault().release());
}

rive_artboard_t* rive_file_artboard_at(rive_file_t* file, int32_t index) {
return toC(toRive(file)->artboardAt(index).release());
}

rive_artboard_t* rive_file_artboard_named(rive_file_t* file, const char name[]) {
return toC(toRive(file)->artboardNamed(name).release());
}

///////////////////////////

int32_t rive_artboard_animation_count(rive_artboard_t* abi) {
return toRive(abi)->animationCount();
}

rive_animation_t* rive_artboard_animation_at(rive_artboard_t* abi, int32_t index) {
return toC(toRive(abi)->animationAt(index).release());
}

rive_animation_t* rive_artboard_animation_named(rive_artboard_t* abi, const char name[]) {
return toC(toRive(abi)->animationNamed(name).release());
}

int32_t rive_artboard_statemachine_count(rive_artboard_t* abi) {
return toRive(abi)->stateMachineCount();
}

rive_statemachine_t* rive_artboard_statemachine_at(rive_artboard_t* abi, int32_t index) {
return toC(toRive(abi)->stateMachineAt(index).release());
}

rive_statemachine_t* rive_artboard_statemachine_named(rive_artboard_t* abi, const char name[]) {
return toC(toRive(abi)->stateMachineNamed(name).release());
}

rive_statemachine_t* rive_artboard_statemachine_default(rive_artboard_t* abi) {
return toC(toRive(abi)->defaultStateMachine().release());
}

rive_scene_t* rive_artboard_scene_default(rive_artboard_t* abi) {
return toC(toRive(abi)->defaultScene().release());
}

////////////////////////////////

rive_aabb_t rive_scene_bounds(rive_scene_t* scene) {
auto aabb = toRive(scene)->bounds();
return {aabb.left(), aabb.top(), aabb.right(), aabb.bottom()};
}

void rive_scene_draw(rive_scene_t* scene, rive_renderer_t* renderer) {
toRive(scene)->draw(toRive(renderer));
}

bool rive_scene_advance(rive_scene_t* scene, float seconds) {
return toRive(scene)->advanceAndApply(seconds);
}
36 changes: 36 additions & 0 deletions include/capi/rive_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef _RIVE_FILE_H_
#define _RIVE_FILE_H_

#include "capi/rive_types.h"

RIVE_C_PLUS_PLUS_BEGIN_GUARD

rive_file_t* rive_file_import(rive_span_t, rive_factory_t*);

int32_t rive_file_artboard_count(rive_file_t*);
rive_artboard_t* rive_file_artboard_default(rive_file_t*);
rive_artboard_t* rive_file_artboard_at(rive_file_t*, int32_t index);
rive_artboard_t* rive_file_artboard_named(rive_file_t*, const char name[]);

rive_statemachine_t* rive_artboard_statemachine_default(rive_artboard_t*);
rive_scene_t* rive_artboard_scene_default(rive_artboard_t*);

int32_t rive_artboard_animation_count(rive_artboard_t*);
rive_animation_t* rive_artboard_animation_at(rive_artboard_t*, int32_t index);
rive_animation_t* rive_artboard_animation_named(rive_artboard_t*, const char name[]);

int32_t rive_artboard_count_statemachines(rive_artboard_t*);
rive_statemachine_t* rive_artboard_statemachine_at(rive_artboard_t*, int32_t index);
rive_statemachine_t* rive_artboard_statemachine_named(rive_artboard_t*, const char name[]);

rive_aabb_t rive_scene_bounds(rive_scene_t*);
void rive_scene_draw(rive_scene_t*, rive_renderer_t*);
bool rive_scene_advance(rive_scene_t*, float seconds);

void rive_file_delete(rive_file_t*);
void rive_artboard_delete(rive_artboard_t*);
void rive_scene_delete(rive_scene_t*);

RIVE_C_PLUS_PLUS_END_GUARD

#endif
48 changes: 48 additions & 0 deletions include/capi/rive_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef _RIVE_TYPES_H_
#define _RIVE_TYPES_H_

#include <stdint.h>
#include <stddef.h>

#ifdef __cplusplus
#define RIVE_C_PLUS_PLUS_BEGIN_GUARD extern "C" {
#define RIVE_C_PLUS_PLUS_END_GUARD }
#else
#include <stdbool.h>
#define RIVE_C_PLUS_PLUS_BEGIN_GUARD
#define RIVE_C_PLUS_PLUS_END_GUARD
#endif

RIVE_C_PLUS_PLUS_BEGIN_GUARD

typedef uint32_t rive_colorint_t;

typedef struct {
float x, y;
} rive_vec2d_t;

typedef struct {
float left, top, right, bottom;
} rive_aabb_t;

typedef struct {
float mat[6];
} rive_mat2d_t;

typedef struct {
void* buffer;
size_t size;
} rive_span_t;

typedef struct rive_file_t rive_file_t;
typedef struct rive_artboard_t rive_artboard_t;
typedef struct rive_scene_t rive_scene_t;
typedef struct rive_animation_t rive_animation_t;
typedef struct rive_statemachine_t rive_statemachine_t;

typedef struct rive_factory_t rive_factory_t;
typedef struct rive_renderer_t rive_renderer_t;

RIVE_C_PLUS_PLUS_END_GUARD

#endif
30 changes: 30 additions & 0 deletions test/capi_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "capi/rive_api.h"

#include "no_op_factory.hpp"
#include <catch.hpp>
#include <cstdio>

static rive::NoOpFactory gNoOpFactory;

static rive_file_t* loadfile(const char path[]) {
FILE* fp = fopen(path, "rb");
REQUIRE(fp != nullptr);

fseek(fp, 0, SEEK_END);
const size_t length = ftell(fp);
fseek(fp, 0, SEEK_SET);
std::vector<uint8_t> bytes(length);
REQUIRE(fread(bytes.data(), 1, length, fp) == length);
fclose(fp);

rive_span_t span = {bytes.data(), length};
return rive_file_import(span, (rive_factory_t*)&gNoOpFactory);
}

TEST_CASE("capi", "[file]") {
auto file = loadfile("../../test/assets/two_artboards.riv");

REQUIRE(rive_file_artboard_count(file) == 2);

rive_file_delete(file);
}