diff --git a/inc/thorvg.h b/inc/thorvg.h index 44eec561..74000119 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -1804,6 +1804,15 @@ class TVG_API Saver final public: ~Saver(); + /** + * @brief Sets the base background content for the saved image. + * + * @param[in] paint The paint to be drawn as the background image for the saving paint. + * + * @note Experimental API + */ + Result background(std::unique_ptr paint) noexcept; + /** * @brief Exports the given @p paint data to the given @p path * diff --git a/src/renderer/tvgSaveModule.h b/src/renderer/tvgSaveModule.h index 09e7bde7..b605410a 100644 --- a/src/renderer/tvgSaveModule.h +++ b/src/renderer/tvgSaveModule.h @@ -34,7 +34,7 @@ public: virtual ~SaveModule() {} virtual bool save(Paint* paint, const string& path, bool compress) = 0; - virtual bool save(Animation* animation, const string& path, uint32_t quality, uint32_t fps) = 0; + virtual bool save(Animation* animation, Paint* bg, const string& path, uint32_t quality, uint32_t fps) = 0; virtual bool close() = 0; }; diff --git a/src/renderer/tvgSaver.cpp b/src/renderer/tvgSaver.cpp index 038d1ad0..cff3a386 100644 --- a/src/renderer/tvgSaver.cpp +++ b/src/renderer/tvgSaver.cpp @@ -37,9 +37,12 @@ struct Saver::Impl { SaveModule* saveModule = nullptr; + Paint* bg = nullptr; + ~Impl() { delete(saveModule); + delete(bg); } }; @@ -139,7 +142,16 @@ Result Saver::save(std::unique_ptr paint, const string& path, bool compre } -Result Saver::save(std::unique_ptr animation, const string& path, uint32_t quality, uint32_t fps) noexcept +Result Saver::background(unique_ptr paint) noexcept +{ + delete(pImpl->bg); + pImpl->bg = paint.release(); + + return Result::Success; +} + + +Result Saver::save(unique_ptr animation, const string& path, uint32_t quality, uint32_t fps) noexcept { auto a = animation.release(); if (!a) return Result::MemoryCorruption; @@ -156,7 +168,7 @@ Result Saver::save(std::unique_ptr animation, const string& path, uin } if (auto saveModule = _find(path)) { - if (saveModule->save(a, path, quality, fps)) { + if (saveModule->save(a, pImpl->bg, path, quality, fps)) { pImpl->saveModule = saveModule; return Result::Success; } else { diff --git a/src/savers/gif/tvgGifSaver.cpp b/src/savers/gif/tvgGifSaver.cpp index 53427b26..78924d3b 100644 --- a/src/savers/gif/tvgGifSaver.cpp +++ b/src/savers/gif/tvgGifSaver.cpp @@ -42,13 +42,7 @@ void GifSaver::run(unsigned tid) buffer = (uint32_t*)realloc(buffer, sizeof(uint32_t) * w * h); canvas->target(buffer, w, w, h, tvg::SwCanvas::ABGR8888); - - //base white background - auto bg = Shape::gen(); - bg->appendRect(0, 0, vsize[0], vsize[1]); - bg->fill(255, 255, 255); - canvas->push(std::move(bg)); - + canvas->push(cast(bg)); canvas->push(cast(animation->picture())); //use the default fps @@ -81,6 +75,8 @@ void GifSaver::run(unsigned tid) } if (!GifEnd(&writer)) TVGERR("GIF_SAVER", "Failed gif encoding"); + + this->bg = nullptr; } @@ -98,6 +94,9 @@ bool GifSaver::close() { this->done(); + delete(bg); + bg = nullptr; + delete(animation); animation = nullptr; @@ -118,7 +117,7 @@ bool GifSaver::save(TVG_UNUSED Paint* paint, TVG_UNUSED const string& path, TVG_ } -bool GifSaver::save(Animation* animation, const string& path, TVG_UNUSED uint32_t quality, uint32_t fps) +bool GifSaver::save(Animation* animation, Paint* bg, const string& path, TVG_UNUSED uint32_t quality, uint32_t fps) { close(); @@ -140,6 +139,7 @@ bool GifSaver::save(Animation* animation, const string& path, TVG_UNUSED uint32_ if (!this->path) return false; this->animation = animation; + if (bg) this->bg = bg->duplicate(); this->fps = static_cast(fps); TaskScheduler::request(this); diff --git a/src/savers/gif/tvgGifSaver.h b/src/savers/gif/tvgGifSaver.h index 8fea6a49..a03b5766 100644 --- a/src/savers/gif/tvgGifSaver.h +++ b/src/savers/gif/tvgGifSaver.h @@ -34,6 +34,7 @@ class GifSaver : public SaveModule, public Task private: uint32_t* buffer = nullptr; Animation* animation = nullptr; + Paint* bg = nullptr; char *path = nullptr; float vsize[2] = {0.0f, 0.0f}; float fps = 0.0f; @@ -44,7 +45,7 @@ public: ~GifSaver(); bool save(Paint* paint, const string& path, bool compress) override; - bool save(Animation* animation, const string& path, uint32_t quality, uint32_t fps) override; + bool save(Animation* animation, Paint* bg, const string& path, uint32_t quality, uint32_t fps) override; bool close() override; }; diff --git a/src/savers/tvg/tvgTvgSaver.cpp b/src/savers/tvg/tvgTvgSaver.cpp index dbd24b0b..cea144ec 100644 --- a/src/savers/tvg/tvgTvgSaver.cpp +++ b/src/savers/tvg/tvgTvgSaver.cpp @@ -780,15 +780,14 @@ bool TvgSaver::close() { this->done(); - if (paint) { - delete(paint); - paint = nullptr; - } - if (path) { - free(path); - path = nullptr; - } + delete(paint); + paint = nullptr; + + free(path); + path = nullptr; + buffer.reset(); + return true; } @@ -822,7 +821,7 @@ bool TvgSaver::save(Paint* paint, const string& path, bool compress) } -bool TvgSaver::save(TVG_UNUSED Animation* animation, TVG_UNUSED const string& path, TVG_UNUSED uint32_t quality, TVG_UNUSED uint32_t fps) +bool TvgSaver::save(TVG_UNUSED Animation* animation, TVG_UNUSED Paint* bg, TVG_UNUSED const string& path, TVG_UNUSED uint32_t quality, TVG_UNUSED uint32_t fps) { TVGLOG("TVG_SAVER", "Animation is not supported."); return false; diff --git a/src/savers/tvg/tvgTvgSaver.h b/src/savers/tvg/tvgTvgSaver.h index c23de831..3d35d5a5 100644 --- a/src/savers/tvg/tvgTvgSaver.h +++ b/src/savers/tvg/tvgTvgSaver.h @@ -35,6 +35,7 @@ class TvgSaver : public SaveModule, public Task private: Array buffer; Paint* paint = nullptr; + Paint* bg = nullptr; char *path = nullptr; uint32_t headerSize; float vsize[2] = {0.0f, 0.0f}; @@ -71,7 +72,7 @@ public: ~TvgSaver(); bool save(Paint* paint, const string& path, bool compress) override; - bool save(Animation* animation, const string& path, uint32_t quality, uint32_t fps) override; + bool save(Animation* animation, Paint* bg, const string& path, uint32_t quality, uint32_t fps) override; bool close() override; };