binding wasm: support the animation.

This commit is contained in:
Hermet Park 2023-08-03 00:30:54 +09:00 committed by Hermet Park
parent cee59dcd0e
commit 496ec72f2a

View file

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