mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
binding wasm: support the animation.
This commit is contained in:
parent
cee59dcd0e
commit
496ec72f2a
1 changed files with 93 additions and 74 deletions
|
@ -33,6 +33,7 @@ static const char* NoError = "None";
|
||||||
|
|
||||||
class __attribute__((visibility("default"))) TvgWasm
|
class __attribute__((visibility("default"))) TvgWasm
|
||||||
{
|
{
|
||||||
|
//This structure data should be aligned with the ThorVG Viewer implementation.
|
||||||
struct Layer
|
struct Layer
|
||||||
{
|
{
|
||||||
uint32_t paint; //cast of a paint pointer
|
uint32_t paint; //cast of a paint pointer
|
||||||
|
@ -63,32 +64,23 @@ public:
|
||||||
{
|
{
|
||||||
errorMsg = NoError;
|
errorMsg = NoError;
|
||||||
|
|
||||||
if (!canvas) {
|
if (!canvas) return false;
|
||||||
errorMsg = "Invalid canvas";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.empty()) {
|
if (data.empty()) {
|
||||||
errorMsg = "Invalid data";
|
errorMsg = "Invalid data";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
picture = Picture::gen().release();
|
canvas->clear(true);
|
||||||
if (!picture) {
|
|
||||||
errorMsg = "Invalid picture";
|
animation = Animation::gen();
|
||||||
|
|
||||||
|
if (animation->picture()->load(data.c_str(), data.size(), mimetype, false) != Result::Success) {
|
||||||
|
errorMsg = "load() fail";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas->clear();
|
animation->picture()->size(&psize[0], &psize[1]);
|
||||||
|
|
||||||
if (picture->load(data.c_str(), data.size(), mimetype, false) != Result::Success) {
|
|
||||||
delete(picture);
|
|
||||||
picture = nullptr;
|
|
||||||
errorMsg = "Fail, load()";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
picture->size(&psize[0], &psize[1]);
|
|
||||||
|
|
||||||
/* need to reset size to calculate scale in Picture.size internally before calling resize() */
|
/* need to reset size to calculate scale in Picture.size internally before calling resize() */
|
||||||
this->width = 0;
|
this->width = 0;
|
||||||
|
@ -96,33 +88,23 @@ public:
|
||||||
|
|
||||||
resize(width, height);
|
resize(width, height);
|
||||||
|
|
||||||
if (canvas->push(cast<Picture>(picture)) != Result::Success) {
|
if (canvas->push(cast<Picture>(animation->picture())) != Result::Success) {
|
||||||
errorMsg = "Fail, push()";
|
errorMsg = "push() fail";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool update(int width, int height, bool force)
|
bool update()
|
||||||
{
|
{
|
||||||
errorMsg = NoError;
|
errorMsg = NoError;
|
||||||
|
|
||||||
if (!canvas || !picture) {
|
if (canvas->update() != Result::Success) {
|
||||||
errorMsg = "Invalid Conditions";
|
errorMsg = "update() fail";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!force && this->width == width && this->height == height) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
resize(width, height);
|
|
||||||
|
|
||||||
if (canvas->update(picture) != Result::Success) {
|
|
||||||
errorMsg = "Fail, update()";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,13 +112,10 @@ public:
|
||||||
{
|
{
|
||||||
errorMsg = NoError;
|
errorMsg = NoError;
|
||||||
|
|
||||||
if (!canvas) {
|
if (!canvas || !animation) return val(typed_memory_view<uint8_t>(0, nullptr));
|
||||||
errorMsg = "Invalid canvas";
|
|
||||||
return val(typed_memory_view<uint8_t>(0, nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canvas->draw() != Result::Success) {
|
if (canvas->draw() != Result::Success) {
|
||||||
errorMsg = "Fail, draw()";
|
errorMsg = "draw() fail";
|
||||||
return val(typed_memory_view<uint8_t>(0, nullptr));
|
return val(typed_memory_view<uint8_t>(0, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,49 +129,107 @@ public:
|
||||||
return val(typed_memory_view(2, psize));
|
return val(typed_memory_view(2, psize));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val duration()
|
||||||
|
{
|
||||||
|
if (!canvas || !animation) return val(0);
|
||||||
|
return val(animation->duration());
|
||||||
|
}
|
||||||
|
|
||||||
|
val totalFrame()
|
||||||
|
{
|
||||||
|
if (!canvas || !animation) return val(0);
|
||||||
|
return val(animation->totalFrame());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool frame(uint32_t no)
|
||||||
|
{
|
||||||
|
if (!canvas || !animation) return false;
|
||||||
|
if (animation->frame(no) != Result::Success) {
|
||||||
|
errorMsg = "frame() fail";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(int width, int height)
|
||||||
|
{
|
||||||
|
if (!canvas || !animation) return;
|
||||||
|
if (this->width == width && this->height == height) return;
|
||||||
|
|
||||||
|
this->width = width;
|
||||||
|
this->height = height;
|
||||||
|
|
||||||
|
buffer = (uint8_t*)malloc(width * height * sizeof(uint32_t));
|
||||||
|
canvas->target((uint32_t *)buffer, width, width, height, SwCanvas::ABGR8888S);
|
||||||
|
|
||||||
|
float scale;
|
||||||
|
float shiftX = 0.0f, shiftY = 0.0f;
|
||||||
|
if (psize[0] > psize[1]) {
|
||||||
|
scale = width / psize[0];
|
||||||
|
shiftY = (height - psize[1] * scale) * 0.5f;
|
||||||
|
} else {
|
||||||
|
scale = height / psize[1];
|
||||||
|
shiftX = (width - psize[0] * scale) * 0.5f;
|
||||||
|
}
|
||||||
|
animation->picture()->scale(scale);
|
||||||
|
animation->picture()->translate(shiftX, shiftY);
|
||||||
|
}
|
||||||
|
|
||||||
bool save(bool compress)
|
bool save(bool compress)
|
||||||
{
|
{
|
||||||
errorMsg = NoError;
|
errorMsg = NoError;
|
||||||
|
|
||||||
|
if (!canvas || !animation) return false;
|
||||||
|
|
||||||
auto saver = Saver::gen();
|
auto saver = Saver::gen();
|
||||||
if (!saver) {
|
if (!saver) {
|
||||||
errorMsg = "Invalid saver";
|
errorMsg = "Invalid saver";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto duplicate = cast<Picture>(picture->duplicate());
|
|
||||||
|
auto duplicate = cast<Picture>(animation->picture()->duplicate());
|
||||||
|
|
||||||
if (!duplicate) {
|
if (!duplicate) {
|
||||||
errorMsg = "Invalid dupliate";
|
errorMsg = "duplicate(), fail";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (saver->save(std::move(duplicate), "output.tvg", compress) != tvg::Result::Success) {
|
if (saver->save(std::move(duplicate), "output.tvg", compress) != tvg::Result::Success) {
|
||||||
errorMsg = "Fail, save()";
|
errorMsg = "save(), fail";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
saver->sync();
|
saver->sync();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
val layers()
|
val layers()
|
||||||
{
|
{
|
||||||
|
if (!canvas || !animation) return val(nullptr);
|
||||||
|
|
||||||
//returns an array of a structure Layer: [id] [depth] [type] [composite]
|
//returns an array of a structure Layer: [id] [depth] [type] [composite]
|
||||||
children.reset();
|
children.reset();
|
||||||
sublayers(&children, picture, 0);
|
sublayers(&children, animation->picture(), 0);
|
||||||
|
|
||||||
return val(typed_memory_view(children.count * sizeof(Layer) / sizeof(uint32_t), (uint32_t *)(children.data)));
|
return val(typed_memory_view(children.count * sizeof(Layer) / sizeof(uint32_t), (uint32_t *)(children.data)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool opacity(uint32_t pid, uint8_t opacity)
|
bool opacity(uint32_t id, uint8_t opacity)
|
||||||
{
|
{
|
||||||
auto paint = findPaintById(picture, pid, nullptr);
|
if (!canvas || !animation) return false;
|
||||||
|
|
||||||
|
auto paint = findPaintById(animation->picture(), id, nullptr);
|
||||||
if (!paint) return false;
|
if (!paint) return false;
|
||||||
const_cast<Paint*>(paint)->opacity(opacity);
|
const_cast<Paint*>(paint)->opacity(opacity);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
val geometry(uint32_t pid)
|
val geometry(uint32_t id)
|
||||||
{
|
{
|
||||||
|
if (!canvas || !animation) return val(typed_memory_view<float>(0, nullptr));
|
||||||
|
|
||||||
Array<const Paint*> parents;
|
Array<const Paint*> parents;
|
||||||
auto paint = findPaintById(picture, pid, &parents);
|
auto paint = findPaintById(animation->picture(), id, &parents);
|
||||||
if (!paint) return val(typed_memory_view<float>(0, nullptr));
|
if (!paint) return val(typed_memory_view<float>(0, nullptr));
|
||||||
paint->bounds(&bounds[0], &bounds[1], &bounds[2], &bounds[3], false);
|
paint->bounds(&bounds[0], &bounds[1], &bounds[2], &bounds[3], false);
|
||||||
|
|
||||||
|
@ -225,38 +262,16 @@ private:
|
||||||
{
|
{
|
||||||
errorMsg = NoError;
|
errorMsg = NoError;
|
||||||
|
|
||||||
Initializer::init(CanvasEngine::Sw, 0);
|
if (Initializer::init(CanvasEngine::Sw, 0) != Result::Success) {
|
||||||
canvas = SwCanvas::gen();
|
errorMsg = "init() fail";
|
||||||
if (!canvas) {
|
|
||||||
errorMsg = "Invalid canvas";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void resize(int width, int height)
|
canvas = SwCanvas::gen();
|
||||||
{
|
if (!canvas) errorMsg = "Invalid canvas";
|
||||||
if (!canvas) return;
|
|
||||||
if (this->width == width && this->height == height) return;
|
|
||||||
|
|
||||||
this->width = width;
|
animation = Animation::gen();
|
||||||
this->height = height;
|
if (!animation) errorMsg = "Invalid animation";
|
||||||
|
|
||||||
buffer = (uint8_t*)malloc(width * height * sizeof(uint32_t));
|
|
||||||
canvas->target((uint32_t *)buffer, width, width, height, SwCanvas::ABGR8888S);
|
|
||||||
|
|
||||||
if (picture) {
|
|
||||||
float scale;
|
|
||||||
float shiftX = 0.0f, shiftY = 0.0f;
|
|
||||||
if (psize[0] > psize[1]) {
|
|
||||||
scale = width / psize[0];
|
|
||||||
shiftY = (height - psize[1] * scale) * 0.5f;
|
|
||||||
} else {
|
|
||||||
scale = height / psize[1];
|
|
||||||
shiftX = (width - psize[0] * scale) * 0.5f;
|
|
||||||
}
|
|
||||||
picture->scale(scale);
|
|
||||||
picture->translate(shiftX, shiftY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sublayers(Array<Layer>* layers, const Paint* paint, uint32_t depth)
|
void sublayers(Array<Layer>* layers, const Paint* paint, uint32_t depth)
|
||||||
|
@ -317,7 +332,7 @@ private:
|
||||||
private:
|
private:
|
||||||
string errorMsg;
|
string errorMsg;
|
||||||
unique_ptr<SwCanvas> canvas = nullptr;
|
unique_ptr<SwCanvas> canvas = nullptr;
|
||||||
Picture* picture = nullptr;
|
unique_ptr<Animation> animation = nullptr;
|
||||||
uint8_t* buffer = nullptr;
|
uint8_t* buffer = nullptr;
|
||||||
Array<Layer> children;
|
Array<Layer> children;
|
||||||
uint32_t width = 0;
|
uint32_t width = 0;
|
||||||
|
@ -333,8 +348,12 @@ EMSCRIPTEN_BINDINGS(thorvg_bindings) {
|
||||||
.function("error", &TvgWasm::error, allow_raw_pointers())
|
.function("error", &TvgWasm::error, allow_raw_pointers())
|
||||||
.function("load", &TvgWasm::load)
|
.function("load", &TvgWasm::load)
|
||||||
.function("update", &TvgWasm::update)
|
.function("update", &TvgWasm::update)
|
||||||
|
.function("resize", &TvgWasm::resize)
|
||||||
.function("render", &TvgWasm::render)
|
.function("render", &TvgWasm::render)
|
||||||
.function("size", &TvgWasm::size)
|
.function("size", &TvgWasm::size)
|
||||||
|
.function("duration", &TvgWasm::duration)
|
||||||
|
.function("totalFrame", &TvgWasm::totalFrame)
|
||||||
|
.function("frame", &TvgWasm::frame)
|
||||||
.function("save", &TvgWasm::save)
|
.function("save", &TvgWasm::save)
|
||||||
.function("layers", &TvgWasm::layers)
|
.function("layers", &TvgWasm::layers)
|
||||||
.function("geometry", &TvgWasm::geometry)
|
.function("geometry", &TvgWasm::geometry)
|
||||||
|
|
Loading…
Add table
Reference in a new issue