diff --git a/src/common/tvgInlist.h b/src/common/tvgInlist.h index 16eaffd4..d0880c4c 100644 --- a/src/common/tvgInlist.h +++ b/src/common/tvgInlist.h @@ -33,8 +33,8 @@ namespace tvg { template struct Inlist { - T *head = nullptr; - T *tail = nullptr; + T* head = nullptr; + T* tail = nullptr; void free() { @@ -52,6 +52,7 @@ struct Inlist tail->next = element; element->prev = tail; element->next = nullptr; + tail = element; } else { head = tail = element; element->prev = nullptr; @@ -62,9 +63,10 @@ struct Inlist void front(T* element) { if (head) { + head->prev = element; element->prev = nullptr; element->next = head; - head->prev = element; + head = element; } else { head = tail = element; element->prev = nullptr; @@ -90,6 +92,14 @@ struct Inlist return t; } + void remove(T* element) + { + if (element->prev) element->prev->next = element->next; + if (element->next) element->next->prev = element->prev; + if (element == head) head = element->next; + if (element == tail) tail = element->prev; + } + bool empty() { return head ? false : true; diff --git a/src/loaders/external_jpg/tvgJpgLoader.cpp b/src/loaders/external_jpg/tvgJpgLoader.cpp index 572207b4..995d974c 100644 --- a/src/loaders/external_jpg/tvgJpgLoader.cpp +++ b/src/loaders/external_jpg/tvgJpgLoader.cpp @@ -41,7 +41,7 @@ void JpgLoader::clear() /* External Class Implementation */ /************************************************************************/ -JpgLoader::JpgLoader() +JpgLoader::JpgLoader() : LoadModule(FileType::Jpg) { jpegDecompressor = tjInitDecompress(); } @@ -49,7 +49,7 @@ JpgLoader::JpgLoader() JpgLoader::~JpgLoader() { - if (freeData) free(data); + clear(); tjDestroy(jpegDecompressor); //This image is shared with raster engine. @@ -59,8 +59,6 @@ JpgLoader::~JpgLoader() bool JpgLoader::open(const string& path) { - clear(); - auto jpegFile = fopen(path.c_str(), "rb"); if (!jpegFile) return false; @@ -102,8 +100,6 @@ finalize: bool JpgLoader::open(const char* data, uint32_t size, TVG_UNUSED const string& rpath, bool copy) { - clear(); - int width, height, subSample, colorSpace; if (tjDecompressHeader3(jpegDecompressor, (unsigned char *) data, size, &width, &height, &subSample, &colorSpace) < 0) return false; @@ -128,6 +124,10 @@ bool JpgLoader::open(const char* data, uint32_t size, TVG_UNUSED const string& r bool JpgLoader::read() { + if (!LoadModule::read()) return true; + + if (w == 0 || h == 0) return false; + /* OPTIMIZE: We assume the desired colorspace is ColorSpace::ARGB How could we notice the renderer colorspace at this time? */ if (image) tjFree(image); @@ -142,12 +142,6 @@ bool JpgLoader::read() return false; } - return true; -} - - -bool JpgLoader::close() -{ clear(); return true; } diff --git a/src/loaders/external_jpg/tvgJpgLoader.h b/src/loaders/external_jpg/tvgJpgLoader.h index e7ada9b0..75b784c6 100644 --- a/src/loaders/external_jpg/tvgJpgLoader.h +++ b/src/loaders/external_jpg/tvgJpgLoader.h @@ -38,7 +38,6 @@ public: bool open(const string& path) override; bool open(const char* data, uint32_t size, const string& rpath, bool copy) override; bool read() override; - bool close() override; unique_ptr bitmap() override; diff --git a/src/loaders/external_png/tvgPngLoader.cpp b/src/loaders/external_png/tvgPngLoader.cpp index df9c279c..f602abf0 100644 --- a/src/loaders/external_png/tvgPngLoader.cpp +++ b/src/loaders/external_png/tvgPngLoader.cpp @@ -26,12 +26,19 @@ /* Internal Class Implementation */ /************************************************************************/ +void PngLoader::clear() +{ + png_image_free(image); + free(image); + image = nullptr; +} + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ -PngLoader::PngLoader() +PngLoader::PngLoader() : LoadModule(FileType::Png) { image = static_cast(calloc(1, sizeof(png_image))); image->version = PNG_IMAGE_VERSION; @@ -40,13 +47,11 @@ PngLoader::PngLoader() PngLoader::~PngLoader() { - if (content) { - free((void*)content); - content = nullptr; - } - free(image); + clear(); + free((void*)content); } + bool PngLoader::open(const string& path) { image->opaque = NULL; @@ -60,6 +65,7 @@ bool PngLoader::open(const string& path) return true; } + bool PngLoader::open(const char* data, uint32_t size, TVG_UNUSED const string& rpath, bool copy) { image->opaque = NULL; @@ -76,6 +82,10 @@ bool PngLoader::open(const char* data, uint32_t size, TVG_UNUSED const string& r bool PngLoader::read() { + if (!LoadModule::read()) return true; + + if (w == 0 || h == 0) return false; + png_bytep buffer; image->format = PNG_FORMAT_BGRA; buffer = static_cast(malloc(PNG_IMAGE_SIZE((*image)))); @@ -90,14 +100,11 @@ bool PngLoader::read() } content = reinterpret_cast(buffer); + clear(); + return true; } -bool PngLoader::close() -{ - png_image_free(image); - return true; -} unique_ptr PngLoader::bitmap() { @@ -115,5 +122,4 @@ unique_ptr PngLoader::bitmap() surface->premultiplied = false; return unique_ptr(surface); -} - +} \ No newline at end of file diff --git a/src/loaders/external_png/tvgPngLoader.h b/src/loaders/external_png/tvgPngLoader.h index 65a319a5..8fb09c06 100644 --- a/src/loaders/external_png/tvgPngLoader.h +++ b/src/loaders/external_png/tvgPngLoader.h @@ -36,11 +36,12 @@ public: bool open(const string& path) override; bool open(const char* data, uint32_t size, const string& rpath, bool copy) override; bool read() override; - bool close() override; unique_ptr bitmap() override; private: + void clear(); + png_imagep image = nullptr; uint32_t* content = nullptr; }; diff --git a/src/loaders/external_webp/tvgWebpLoader.cpp b/src/loaders/external_webp/tvgWebpLoader.cpp index 11d64f62..86509c30 100644 --- a/src/loaders/external_webp/tvgWebpLoader.cpp +++ b/src/loaders/external_webp/tvgWebpLoader.cpp @@ -30,22 +30,9 @@ /* Internal Class Implementation */ /************************************************************************/ -void WebpLoader::clear() -{ - if (freeData) free(data); - data = nullptr; - size = 0; - freeData = false; -} - void WebpLoader::run(unsigned tid) { - if (image) { - WebPFree(image); - image = nullptr; - } - image = WebPDecodeBGRA(data, size, nullptr, nullptr); } @@ -54,22 +41,25 @@ void WebpLoader::run(unsigned tid) /* External Class Implementation */ /************************************************************************/ -WebpLoader::WebpLoader() +WebpLoader::WebpLoader() : LoadModule(FileType::Webp) { } WebpLoader::~WebpLoader() { + this->done(); + if (freeData) free(data); + data = nullptr; + size = 0; + freeData = false; WebPFree(image); } bool WebpLoader::open(const string& path) { - clear(); - auto webpFile = fopen(path.c_str(), "rb"); if (!webpFile) return false; @@ -85,10 +75,10 @@ bool WebpLoader::open(const string& path) freeData = true; - if (fread(data, size, 1, webpFile) < 1) goto failure; + if (fread(data, size, 1, webpFile) < 1) goto finalize; int width, height; - if (!WebPGetInfo(data, size, &width, &height)) goto failure; + if (!WebPGetInfo(data, size, &width, &height)) goto finalize; w = static_cast(width); h = static_cast(height); @@ -96,11 +86,6 @@ bool WebpLoader::open(const string& path) ret = true; - goto finalize; - -failure: - clear(); - finalize: fclose(webpFile); return ret; @@ -109,8 +94,6 @@ finalize: bool WebpLoader::open(const char* data, uint32_t size, TVG_UNUSED const string& rpath, bool copy) { - clear(); - if (copy) { this->data = (unsigned char *) malloc(size); if (!this->data) return false; @@ -134,21 +117,15 @@ bool WebpLoader::open(const char* data, uint32_t size, TVG_UNUSED const string& bool WebpLoader::read() { - if (!data || w <= 0 || h <= 0) return false; + if (!LoadModule::read()) return true; + + if (!data || w == 0 || h == 0) return false; TaskScheduler::request(this); return true; } -bool WebpLoader::close() -{ - this->done(); - clear(); - return true; -} - - unique_ptr WebpLoader::bitmap() { this->done(); diff --git a/src/loaders/external_webp/tvgWebpLoader.h b/src/loaders/external_webp/tvgWebpLoader.h index 85f3b067..1f9bfd76 100644 --- a/src/loaders/external_webp/tvgWebpLoader.h +++ b/src/loaders/external_webp/tvgWebpLoader.h @@ -36,12 +36,10 @@ public: bool open(const string& path) override; bool open(const char* data, uint32_t size, const string& rpath, bool copy) override; bool read() override; - bool close() override; unique_ptr bitmap() override; private: - void clear(); void run(unsigned tid) override; unsigned char* data = nullptr; diff --git a/src/loaders/jpg/tvgJpgLoader.cpp b/src/loaders/jpg/tvgJpgLoader.cpp index 9e296c81..72357e02 100644 --- a/src/loaders/jpg/tvgJpgLoader.cpp +++ b/src/loaders/jpg/tvgJpgLoader.cpp @@ -44,6 +44,8 @@ void JpgLoader::run(unsigned tid) image = nullptr; } image = jpgdDecompress(decoder); + + clear(); } @@ -51,19 +53,21 @@ void JpgLoader::run(unsigned tid) /* External Class Implementation */ /************************************************************************/ +JpgLoader::JpgLoader() : LoadModule(FileType::Jpg) +{ + +} + JpgLoader::~JpgLoader() { - jpgdDelete(decoder); - if (freeData) free(data); + clear(); free(image); } bool JpgLoader::open(const string& path) { - clear(); - int width, height; decoder = jpgdHeader(path.c_str(), &width, &height); if (!decoder) return false; @@ -78,8 +82,6 @@ bool JpgLoader::open(const string& path) bool JpgLoader::open(const char* data, uint32_t size, TVG_UNUSED const string& rpath, bool copy) { - clear(); - if (copy) { this->data = (char *) malloc(size); if (!this->data) return false; @@ -105,7 +107,9 @@ bool JpgLoader::open(const char* data, uint32_t size, TVG_UNUSED const string& r bool JpgLoader::read() { - if (!decoder || w <= 0 || h <= 0) return false; + if (!LoadModule::read()) return true; + + if (!decoder || w == 0 || h == 0) return false; TaskScheduler::request(this); @@ -115,8 +119,8 @@ bool JpgLoader::read() bool JpgLoader::close() { + if (!LoadModule::close()) return false; this->done(); - clear(); return true; } diff --git a/src/loaders/jpg/tvgJpgLoader.h b/src/loaders/jpg/tvgJpgLoader.h index 3a3da640..8a05a491 100644 --- a/src/loaders/jpg/tvgJpgLoader.h +++ b/src/loaders/jpg/tvgJpgLoader.h @@ -39,6 +39,7 @@ private: void run(unsigned tid) override; public: + JpgLoader(); ~JpgLoader(); using LoadModule::open; diff --git a/src/loaders/lottie/tvgLottieLoader.cpp b/src/loaders/lottie/tvgLottieLoader.cpp index 7b25cb1b..0a9cc71b 100644 --- a/src/loaders/lottie/tvgLottieLoader.cpp +++ b/src/loaders/lottie/tvgLottieLoader.cpp @@ -20,7 +20,6 @@ * SOFTWARE. */ -#include "tvgLoader.h" #include "tvgLottieLoader.h" #include "tvgLottieModel.h" #include "tvgLottieParser.h" @@ -48,17 +47,6 @@ static float _str2float(const char* str, int len) } -void LottieLoader::clear() -{ - if (copy) free((char*)content); - free(dirName); - dirName = nullptr; - size = 0; - content = nullptr; - copy = false; -} - - void LottieLoader::run(unsigned tid) { //update frame @@ -84,21 +72,21 @@ void LottieLoader::run(unsigned tid) /* External Class Implementation */ /************************************************************************/ -LottieLoader::LottieLoader() : builder(new LottieBuilder) +LottieLoader::LottieLoader() : FrameModule(FileType::Lottie), builder(new LottieBuilder) { + } LottieLoader::~LottieLoader() { - close(); + this->done(); + + if (copy) free((char*)content); + free(dirName); //TODO: correct position? - if (comp) { - delete(comp); - comp = nullptr; - } - + delete(comp); delete(builder); } @@ -208,8 +196,6 @@ bool LottieLoader::header() bool LottieLoader::open(const char* data, uint32_t size, const std::string& rpath, bool copy) { - clear(); - //If the format is dotLottie auto dotLottie = _checkDotLottie(data); if (dotLottie) { @@ -236,8 +222,6 @@ bool LottieLoader::open(const char* data, uint32_t size, const std::string& rpat bool LottieLoader::open(const string& path) { - clear(); - auto f = fopen(path.c_str(), "r"); if (!f) return false; @@ -297,6 +281,8 @@ bool LottieLoader::read() { if (!content || size == 0) return false; + if (!LoadModule::read()) return true; + //the loading has been already completed in header() if (comp) return true; @@ -306,16 +292,6 @@ bool LottieLoader::read() } -bool LottieLoader::close() -{ - this->done(); - - clear(); - - return true; -} - - unique_ptr LottieLoader::paint() { this->done(); diff --git a/src/loaders/lottie/tvgLottieLoader.h b/src/loaders/lottie/tvgLottieLoader.h index a087c06a..1bab6a35 100644 --- a/src/loaders/lottie/tvgLottieLoader.h +++ b/src/loaders/lottie/tvgLottieLoader.h @@ -39,7 +39,7 @@ public: float frameCnt = 0.0f; float frameDuration = 0.0f; - LottieBuilder* builder = nullptr; + LottieBuilder* builder; LottieComposition* comp = nullptr; char* dirName = nullptr; //base resource directory @@ -54,7 +54,6 @@ public: bool open(const char* data, uint32_t size, const std::string& rpath, bool copy) override; bool resize(Paint* paint, float w, float h) override; bool read() override; - bool close() override; unique_ptr paint() override; //Frame Controls diff --git a/src/loaders/png/tvgPngLoader.cpp b/src/loaders/png/tvgPngLoader.cpp index dbfc5c97..6f621763 100644 --- a/src/loaders/png/tvgPngLoader.cpp +++ b/src/loaders/png/tvgPngLoader.cpp @@ -29,16 +29,6 @@ /* Internal Class Implementation */ /************************************************************************/ -void PngLoader::clear() -{ - lodepng_state_cleanup(&state); - - if (freeData) free(data); - data = nullptr; - size = 0; - freeData = false; -} - void PngLoader::run(unsigned tid) { @@ -59,7 +49,7 @@ void PngLoader::run(unsigned tid) /* External Class Implementation */ /************************************************************************/ -PngLoader::PngLoader() +PngLoader::PngLoader() : LoadModule(FileType::Png) { lodepng_state_init(&state); } @@ -69,13 +59,12 @@ PngLoader::~PngLoader() { if (freeData) free(data); free(image); + lodepng_state_cleanup(&state); } bool PngLoader::open(const string& path) { - clear(); - auto pngFile = fopen(path.c_str(), "rb"); if (!pngFile) return false; @@ -91,12 +80,12 @@ bool PngLoader::open(const string& path) freeData = true; - if (fread(data, size, 1, pngFile) < 1) goto failure; + if (fread(data, size, 1, pngFile) < 1) goto finalize; lodepng_state_init(&state); unsigned int width, height; - if (lodepng_inspect(&width, &height, &state, data, size) > 0) goto failure; + if (lodepng_inspect(&width, &height, &state, data, size) > 0) goto finalize; w = static_cast(width); h = static_cast(height); @@ -108,9 +97,6 @@ bool PngLoader::open(const string& path) goto finalize; -failure: - clear(); - finalize: fclose(pngFile); return ret; @@ -119,10 +105,6 @@ finalize: bool PngLoader::open(const char* data, uint32_t size, TVG_UNUSED const string& rpath, bool copy) { - clear(); - - lodepng_state_init(&state); - unsigned int width, height; if (lodepng_inspect(&width, &height, &state, (unsigned char*)(data), size) > 0) return false; @@ -148,7 +130,9 @@ bool PngLoader::open(const char* data, uint32_t size, TVG_UNUSED const string& r bool PngLoader::read() { - if (!data || w <= 0 || h <= 0) return false; + if (!data || w == 0 || h == 0) return false; + + if (!LoadModule::read()) return true; TaskScheduler::request(this); @@ -156,14 +140,6 @@ bool PngLoader::read() } -bool PngLoader::close() -{ - this->done(); - clear(); - return true; -} - - unique_ptr PngLoader::bitmap() { this->done(); diff --git a/src/loaders/png/tvgPngLoader.h b/src/loaders/png/tvgPngLoader.h index a59d9d0d..a19aca6f 100644 --- a/src/loaders/png/tvgPngLoader.h +++ b/src/loaders/png/tvgPngLoader.h @@ -36,7 +36,6 @@ private: unsigned long size = 0; bool freeData = false; - void clear(); void run(unsigned tid) override; public: @@ -47,7 +46,6 @@ public: bool open(const string& path) override; bool open(const char* data, uint32_t size, const string& rpath, bool copy) override; bool read() override; - bool close() override; unique_ptr bitmap() override; }; diff --git a/src/loaders/raw/tvgRawLoader.cpp b/src/loaders/raw/tvgRawLoader.cpp index e7ddff85..ca624273 100644 --- a/src/loaders/raw/tvgRawLoader.cpp +++ b/src/loaders/raw/tvgRawLoader.cpp @@ -34,6 +34,11 @@ /* External Class Implementation */ /************************************************************************/ +RawLoader::RawLoader() : LoadModule(FileType::Raw) +{ +} + + RawLoader::~RawLoader() { if (copy && content) { @@ -45,6 +50,8 @@ RawLoader::~RawLoader() bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool premultiplied, bool copy) { + if (!LoadModule::read()) return true; + if (!data || w == 0 || h == 0) return false; this->w = (float)w; @@ -67,12 +74,7 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool premulti bool RawLoader::read() { - return true; -} - - -bool RawLoader::close() -{ + LoadModule::read(); return true; } diff --git a/src/loaders/raw/tvgRawLoader.h b/src/loaders/raw/tvgRawLoader.h index 47f17ac2..45589e83 100644 --- a/src/loaders/raw/tvgRawLoader.h +++ b/src/loaders/raw/tvgRawLoader.h @@ -30,12 +30,12 @@ public: bool copy = false; bool premultiplied = false; + RawLoader(); ~RawLoader(); using LoadModule::open; bool open(const uint32_t* data, uint32_t w, uint32_t h, bool premultiplied, bool copy); bool read() override; - bool close() override; unique_ptr bitmap() override; }; diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 6a4eaf44..183b3421 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -3538,14 +3538,15 @@ void SvgLoader::clear(bool all) /* External Class Implementation */ /************************************************************************/ -SvgLoader::SvgLoader() +SvgLoader::SvgLoader() : LoadModule(FileType::Svg) { } SvgLoader::~SvgLoader() { - close(); + this->done(); + clear(); } @@ -3727,6 +3728,8 @@ bool SvgLoader::read() { if (!content || size == 0) return false; + if (!LoadModule::read()) return true; + //the loading has been already completed in header() if (root) return true; @@ -3738,10 +3741,9 @@ bool SvgLoader::read() bool SvgLoader::close() { + if (!LoadModule::close()) return false; this->done(); - clear(); - return true; } diff --git a/src/loaders/tvg/tvgTvgLoader.cpp b/src/loaders/tvg/tvgTvgLoader.cpp index a5a5a3b1..1c2d3e63 100644 --- a/src/loaders/tvg/tvgTvgLoader.cpp +++ b/src/loaders/tvg/tvgTvgLoader.cpp @@ -39,10 +39,8 @@ void TvgLoader::clear() size = 0; copy = false; - if (interpreter) { - delete(interpreter); - interpreter = nullptr; - } + delete(interpreter); + interpreter = nullptr; } @@ -103,13 +101,37 @@ bool TvgLoader::readHeader() } +void TvgLoader::run(unsigned tid) +{ + if (root) root.reset(); + + auto data = const_cast(ptr); + + if (compressed) { + data = (char*) lzwDecode((uint8_t*) data, compressedSize, compressedSizeBits, uncompressedSize); + root = interpreter->run(data, data + uncompressedSize); + free(data); + } else { + root = interpreter->run(data, this->data + size); + } + + clear(); +} + + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ +TvgLoader::TvgLoader() : LoadModule(FileType::Tvg) +{ +} + + TvgLoader::~TvgLoader() { - close(); + this->done(); + clear(); } @@ -193,38 +215,14 @@ bool TvgLoader::read() { if (!ptr || size == 0) return false; + if (!LoadModule::read()) return true; + TaskScheduler::request(this); return true; } -bool TvgLoader::close() -{ - this->done(); - clear(); - return true; -} - - -void TvgLoader::run(unsigned tid) -{ - if (root) root.reset(); - - auto data = const_cast(ptr); - - if (compressed) { - data = (char*) lzwDecode((uint8_t*) data, compressedSize, compressedSizeBits, uncompressedSize); - root = interpreter->run(data, data + uncompressedSize); - free(data); - } else { - root = interpreter->run(data, this->data + size); - } - - if (!root) clear(); -} - - unique_ptr TvgLoader::paint() { this->done(); diff --git a/src/loaders/tvg/tvgTvgLoader.h b/src/loaders/tvg/tvgTvgLoader.h index ddd895ab..389425e7 100644 --- a/src/loaders/tvg/tvgTvgLoader.h +++ b/src/loaders/tvg/tvgTvgLoader.h @@ -42,13 +42,13 @@ public: bool copy = false; bool compressed = false; + TvgLoader(); ~TvgLoader(); using LoadModule::open; bool open(const string &path) override; bool open(const char *data, uint32_t size, const string& rpath, bool copy) override; bool read() override; - bool close() override; bool resize(Paint* paint, float w, float h) override; unique_ptr paint() override; diff --git a/src/renderer/tvgAnimation.cpp b/src/renderer/tvgAnimation.cpp index b894e00c..5c153b6e 100644 --- a/src/renderer/tvgAnimation.cpp +++ b/src/renderer/tvgAnimation.cpp @@ -64,7 +64,7 @@ Animation::Animation() : pImpl(new Impl) Result Animation::frame(float no) noexcept { - auto loader = pImpl->picture->pImpl->loader.get(); + auto loader = pImpl->picture->pImpl->loader; if (!loader) return Result::InsufficientCondition; if (!loader->animatable()) return Result::NonSupport; @@ -82,7 +82,7 @@ Picture* Animation::picture() const noexcept float Animation::curFrame() const noexcept { - auto loader = pImpl->picture->pImpl->loader.get(); + auto loader = pImpl->picture->pImpl->loader; if (!loader) return 0; if (!loader->animatable()) return 0; @@ -93,7 +93,7 @@ float Animation::curFrame() const noexcept float Animation::totalFrame() const noexcept { - auto loader = pImpl->picture->pImpl->loader.get(); + auto loader = pImpl->picture->pImpl->loader; if (!loader) return 0; if (!loader->animatable()) return 0; @@ -104,7 +104,7 @@ float Animation::totalFrame() const noexcept float Animation::duration() const noexcept { - auto loader = pImpl->picture->pImpl->loader.get(); + auto loader = pImpl->picture->pImpl->loader; if (!loader) return 0; if (!loader->animatable()) return 0; diff --git a/src/renderer/tvgFrameModule.h b/src/renderer/tvgFrameModule.h index 332cca30..728298dd 100644 --- a/src/renderer/tvgFrameModule.h +++ b/src/renderer/tvgFrameModule.h @@ -31,6 +31,7 @@ namespace tvg class FrameModule: public LoadModule { public: + FrameModule(FileType type) : LoadModule(type) {} virtual ~FrameModule() {} virtual bool frame(float no) = 0; //set the current frame number diff --git a/src/renderer/tvgLoadModule.h b/src/renderer/tvgLoadModule.h index de1d0437..9cda65ca 100644 --- a/src/renderer/tvgLoadModule.h +++ b/src/renderer/tvgLoadModule.h @@ -24,16 +24,26 @@ #define _TVG_LOAD_MODULE_H_ #include "tvgRender.h" +#include "tvgInlist.h" namespace tvg { -class LoadModule +struct LoadModule { -public: + INLIST_ITEM(LoadModule); + + //Use either hashkey(data) or hashpath(path) + uint64_t hashkey; + string hashpath; + float w = 0, h = 0; //default image size ColorSpace cs = ColorSpace::Unsupported; //must be clarified at open() + FileType type; //current loader file type + uint16_t sharing = 0; //reference count + bool readied = false; //read done already. + LoadModule(FileType type) : type(type) {} virtual ~LoadModule() {} virtual bool open(const string& path) { return false; } @@ -45,8 +55,19 @@ public: virtual bool animatable() { return false; } //true if this loader supports animation. virtual void sync() {}; //finish immediately if any async update jobs. - virtual bool read() = 0; - virtual bool close() = 0; + virtual bool read() + { + if (readied) return false; + readied = true; + return true; + } + + virtual bool close() + { + if (sharing == 0) return true; + --sharing; + return false; + } virtual unique_ptr bitmap() { return nullptr; } virtual unique_ptr paint() { return nullptr; } diff --git a/src/renderer/tvgLoader.cpp b/src/renderer/tvgLoader.cpp index 57f35be3..a386e2ac 100644 --- a/src/renderer/tvgLoader.cpp +++ b/src/renderer/tvgLoader.cpp @@ -20,6 +20,7 @@ * SOFTWARE. */ +#include "tvgInlist.h" #include "tvgLoader.h" #ifdef THORVG_SVG_LOADER_SUPPORT @@ -48,10 +49,19 @@ #include "tvgRawLoader.h" + +uint64_t HASH_KEY(const char* data, uint64_t size) +{ + return (((uint64_t) data) << 32) | size; +} + /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ +static Inlist _activeLoaders; + + static LoadModule* _find(FileType type) { switch(type) { @@ -156,10 +166,8 @@ static LoadModule* _findByPath(const string& path) } -static LoadModule* _findByType(const string& mimeType) +static FileType _convert(const string& mimeType) { - if (mimeType.empty()) return nullptr; - auto type = FileType::Unknown; if (mimeType == "tvg") type = FileType::Tvg; @@ -169,12 +177,50 @@ static LoadModule* _findByType(const string& mimeType) else if (mimeType == "png") type = FileType::Png; else if (mimeType == "jpg" || mimeType == "jpeg") type = FileType::Jpg; else if (mimeType == "webp") type = FileType::Webp; - else { - TVGLOG("RENDERER", "Given mimetype is unknown = \"%s\".", mimeType.c_str()); - return nullptr; - } + else TVGLOG("RENDERER", "Given mimetype is unknown = \"%s\".", mimeType.c_str()); - return _find(type); + return type; +} + + +static LoadModule* _findByType(const string& mimeType) +{ + return _find(_convert(mimeType)); +} + + +static LoadModule* _findFromCache(const string& path) +{ + auto loader = _activeLoaders.head; + + while (loader) { + if (loader->hashpath == path) { + ++loader->sharing; + return loader; + } + loader = loader->next; + } + return nullptr; +} + + +static LoadModule* _findFromCache(const char* data, uint32_t size, const string& mimeType) +{ + auto type = _convert(mimeType); + if (type == FileType::Unknown) return nullptr; + + auto loader = _activeLoaders.head; + + auto key = HASH_KEY(data, size); + + while (loader) { + if (loader->type == type && loader->hashkey == key) { + ++loader->sharing; + return loader; + } + loader = loader->next; + } + return nullptr; } @@ -185,40 +231,57 @@ static LoadModule* _findByType(const string& mimeType) bool LoaderMgr::init() { - //TODO: - return true; } bool LoaderMgr::term() { - //TODO: - return true; } -shared_ptr LoaderMgr::loader(const string& path, bool* invalid) +void LoaderMgr::retrieve(LoadModule* loader) +{ + if (!loader) return; + + if (loader->close()) { + _activeLoaders.remove(loader); + delete(loader); + } +} + + +LoadModule* LoaderMgr::loader(const string& path, bool* invalid) { *invalid = false; + if (auto loader = _findFromCache(path)) return loader; + if (auto loader = _findByPath(path)) { - if (loader->open(path)) return shared_ptr(loader); - else delete(loader); + if (loader->open(path)) { + loader->hashpath = path; + _activeLoaders.back(loader); + return loader; + } + delete(loader); *invalid = true; } return nullptr; } -shared_ptr LoaderMgr::loader(const char* data, uint32_t size, const string& mimeType, const string& rpath, bool copy) +LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mimeType, const string& rpath, bool copy) { + if (auto loader = _findFromCache(data, size, mimeType)) return loader; + //Try with the given MimeType if (!mimeType.empty()) { if (auto loader = _findByType(mimeType)) { if (loader->open(data, size, rpath, copy)) { - return shared_ptr(loader); + loader->hashkey = HASH_KEY(data, size); + _activeLoaders.back(loader); + return loader; } else { TVGLOG("LOADER", "Given mimetype \"%s\" seems incorrect or not supported.", mimeType.c_str()); delete(loader); @@ -229,8 +292,12 @@ shared_ptr LoaderMgr::loader(const char* data, uint32_t size, const for (int i = 0; i < static_cast(FileType::Unknown); i++) { auto loader = _find(static_cast(i)); if (loader) { - if (loader->open(data, size, rpath, copy)) return shared_ptr(loader); - else delete(loader); + if (loader->open(data, size, rpath, copy)) { + loader->hashkey = HASH_KEY(data, size); + _activeLoaders.back(loader); + return loader; + } + delete(loader); } } } @@ -238,12 +305,18 @@ shared_ptr LoaderMgr::loader(const char* data, uint32_t size, const } -shared_ptr LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool premultiplied, bool copy) +LoadModule* LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool premultiplied, bool copy) { + //TODO: should we check premultiplied?? + if (auto loader = _findFromCache((const char*)(data), w * h, "raw")) return loader; + //function is dedicated for raw images only auto loader = new RawLoader; - if (loader->open(data, w, h, premultiplied, copy)) return shared_ptr(loader); - else delete(loader); - + if (loader->open(data, w, h, premultiplied, copy)) { + loader->hashkey = HASH_KEY((const char*)data, w * h); + _activeLoaders.back(loader); + return loader; + } + delete(loader); return nullptr; -} +} \ No newline at end of file diff --git a/src/renderer/tvgLoader.h b/src/renderer/tvgLoader.h index a94dd501..29f19cf0 100644 --- a/src/renderer/tvgLoader.h +++ b/src/renderer/tvgLoader.h @@ -29,9 +29,10 @@ struct LoaderMgr { static bool init(); static bool term(); - static shared_ptr loader(const string& path, bool* invalid); - static shared_ptr loader(const char* data, uint32_t size, const string& mimeType, const string& rpath, bool copy); - static shared_ptr loader(const uint32_t* data, uint32_t w, uint32_t h, bool premultiplied, bool copy); + static LoadModule* loader(const string& path, bool* invalid); + static LoadModule* loader(const char* data, uint32_t size, const string& mimeType, const string& rpath, bool copy); + static LoadModule* loader(const uint32_t* data, uint32_t w, uint32_t h, bool premultiplied, bool copy); + static void retrieve(LoadModule* loader); }; #endif //_TVG_LOADER_H_ diff --git a/src/renderer/tvgPicture.cpp b/src/renderer/tvgPicture.cpp index 1465f09f..23c6d55b 100644 --- a/src/renderer/tvgPicture.cpp +++ b/src/renderer/tvgPicture.cpp @@ -32,7 +32,6 @@ RenderUpdateFlag Picture::Impl::load() if (!paint) { if (auto p = loader->paint()) { paint = p.release(); - loader->close(); if (w != loader->w || h != loader->h) { if (!resizing) { w = loader->w; @@ -47,7 +46,6 @@ RenderUpdateFlag Picture::Impl::load() if (!surface) { if ((surface = loader->bitmap().release())) { - loader->close(); return RenderUpdateFlag::Image; } } @@ -120,6 +118,28 @@ RenderTransform Picture::Impl::resizeTransform(const RenderTransform* pTransform } +Result Picture::Impl::load(LoadModule* loader) +{ + //Same resource has been loaded. + if (this->loader == loader) { + this->loader->sharing--; //make it sure the reference counting. + return Result::Success; + } else if (this->loader) { + LoaderMgr::retrieve(this->loader); + } + + this->loader = loader; + + if (!loader->read()) return Result::Unknown; + + this->w = loader->w; + this->h = loader->h; + + return Result::Success; +} + + + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ diff --git a/src/renderer/tvgPicture.h b/src/renderer/tvgPicture.h index 94f61510..f4f5ee0b 100644 --- a/src/renderer/tvgPicture.h +++ b/src/renderer/tvgPicture.h @@ -57,7 +57,7 @@ struct PictureIterator : Iterator struct Picture::Impl { - shared_ptr loader = nullptr; + LoadModule* loader = nullptr; Paint* paint = nullptr; //vector picture uses Surface* surface = nullptr; //bitmap picture uses @@ -73,6 +73,7 @@ struct Picture::Impl bool render(RenderMethod &renderer); bool size(float w, float h); RenderRegion bounds(RenderMethod& renderer); + Result load(LoadModule* ploader); Impl(Picture* p) : picture(p) { @@ -80,6 +81,7 @@ struct Picture::Impl ~Impl() { + LoaderMgr::retrieve(loader); delete(paint); delete(surface); } @@ -149,40 +151,32 @@ struct Picture::Impl Result load(const string& path) { if (paint || surface) return Result::InsufficientCondition; - if (loader) loader->close(); + bool invalid; //Invalid Path - loader = LoaderMgr::loader(path, &invalid); + auto loader = LoaderMgr::loader(path, &invalid); if (!loader) { if (invalid) return Result::InvalidArguments; return Result::NonSupport; } - if (!loader->read()) return Result::Unknown; - w = loader->w; - h = loader->h; - return Result::Success; + return load(loader); } Result load(const char* data, uint32_t size, const string& mimeType, const string& rpath, bool copy) { if (paint || surface) return Result::InsufficientCondition; - if (loader) loader->close(); - loader = LoaderMgr::loader(data, size, mimeType, rpath, copy); + auto loader = LoaderMgr::loader(data, size, mimeType, rpath, copy); if (!loader) return Result::NonSupport; - if (!loader->read()) return Result::Unknown; - w = loader->w; - h = loader->h; - return Result::Success; + return load(loader); } Result load(uint32_t* data, uint32_t w, uint32_t h, bool premultiplied, bool copy) { if (paint || surface) return Result::InsufficientCondition; - if (loader) loader->close(); - loader = LoaderMgr::loader(data, w, h, premultiplied, copy); + + auto loader = LoaderMgr::loader(data, w, h, premultiplied, copy); if (!loader) return Result::FailedAllocation; - this->w = loader->w; - this->h = loader->h; - return Result::Success; + + return load(loader); } void mesh(const Polygon* triangles, const uint32_t triangleCnt) @@ -208,10 +202,11 @@ struct Picture::Impl if (paint) dup->paint = paint->duplicate(); dup->loader = loader; + ++dup->loader->sharing; + if (surface) { dup->surface = new Surface; *dup->surface = *surface; - //TODO: A dupilcation is not a proxy... it needs copy of the pixel data? dup->surface->owner = false; } dup->w = w;