diff --git a/src/common/tvgStr.cpp b/src/common/tvgStr.cpp index cf5ee9e4..769c30ff 100644 --- a/src/common/tvgStr.cpp +++ b/src/common/tvgStr.cpp @@ -206,6 +206,7 @@ error: return 0.0f; } + char* duplicate(const char *str, size_t n) { auto len = strlen(str); @@ -217,6 +218,7 @@ char* duplicate(const char *str, size_t n) return (char*)memcpy(ret, str, n); } + char* append(char* lhs, const char* rhs, size_t n) { if (!rhs) return lhs; @@ -225,20 +227,36 @@ char* append(char* lhs, const char* rhs, size_t n) return strncat(lhs, rhs, n); } + char* dirname(const char* path) { - const char *ptr = strrchr(path, '/'); + auto ptr = strrchr(path, '/'); #ifdef _WIN32 - if (ptr) ptr = strrchr(ptr + 1, '\\'); + ptr = strrchr(ptr ? ptr : path, '\\'); #endif - int len = int(ptr + 1 - path); // +1 to include '/' + auto len = ptr ? size_t(ptr - path + 1) : SIZE_MAX; return duplicate(path, len); } -const char* fileext(const char* filename) +char* filename(const char* path) { - auto ext = filename; + const char* ptr = strrchr(path, '/'); +#ifdef _WIN32 + auto ptr2 = strrchr(ptr ? ptr : path, '\\'); + if (ptr2) ptr = ptr2; +#endif + if (ptr) ++ptr; + else ptr = path; + auto dot = fileext(ptr); + auto len = (dot > ptr) ? (size_t)(dot - ptr - 1) : strlen(ptr); + return duplicate(ptr, len); +} + + +const char* fileext(const char* path) +{ + auto ext = path; while (ext) { auto p = strchr(ext, '.'); if (!p) break; diff --git a/src/common/tvgStr.h b/src/common/tvgStr.h index 8678a96f..6e9f188c 100644 --- a/src/common/tvgStr.h +++ b/src/common/tvgStr.h @@ -37,7 +37,8 @@ float toFloat(const char *str, char **end); //convert to floa char* duplicate(const char *str, size_t n = SIZE_MAX); //copy the string char* append(char* lhs, const char* rhs, size_t n); //append the rhs to the lhs char* dirname(const char* path); //return the full directory name -const char* fileext(const char* filename); //return the file extension name +char* filename(const char* path); //return the file name without extension +const char* fileext(const char* path); //return the file extension name } #endif //_TVG_STR_H_ diff --git a/src/loaders/ttf/tvgTtfLoader.cpp b/src/loaders/ttf/tvgTtfLoader.cpp index 11d957e8..65b0f5ca 100644 --- a/src/loaders/ttf/tvgTtfLoader.cpp +++ b/src/loaders/ttf/tvgTtfLoader.cpp @@ -21,6 +21,7 @@ */ +#include "tvgStr.h" #include "tvgTtfLoader.h" #if defined(_WIN32) && (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) @@ -208,6 +209,9 @@ void TtfLoader::clear() _unmap(this); #endif } + + tvg::free(name); + name = nullptr; shape = nullptr; } @@ -247,6 +251,9 @@ bool TtfLoader::open(const char* path) #ifdef THORVG_FILE_IO_SUPPORT clear(); if (!_map(this, path)) return false; + + name = tvg::filename(path); + return reader.header(); #else return false; diff --git a/src/renderer/tvgLoadModule.h b/src/renderer/tvgLoadModule.h index 0352f4bb..4e9bf007 100644 --- a/src/renderer/tvgLoadModule.h +++ b/src/renderer/tvgLoadModule.h @@ -33,20 +33,30 @@ struct LoadModule INLIST_ITEM(LoadModule); //Use either hashkey(data) or hashpath(path) - union { - uintptr_t hashkey; - char* hashpath = nullptr; - }; + uintptr_t hashkey = 0; + char* hashpath = nullptr; FileType type; //current loader file type uint16_t sharing = 0; //reference count bool readied = false; //read done already. - bool pathcache = false; //cached by path + bool cached = false; //cached for sharing LoadModule(FileType type) : type(type) {} virtual ~LoadModule() { - if (pathcache) tvg::free(hashpath); + tvg::free(hashpath); + } + + void cache(uintptr_t data) + { + hashkey = data; + cached = true; + } + + void cache(char* data) + { + hashpath = data; + cached = true; } virtual bool open(const char* path) { return false; } @@ -61,12 +71,6 @@ struct LoadModule return true; } - bool cached() - { - if (hashkey) return true; - return false; - } - virtual bool close() { if (sharing == 0) return true; @@ -99,6 +103,7 @@ struct ImageLoader : LoadModule struct FontLoader : LoadModule { float scale = 1.0f; + char* name = nullptr; FontLoader(FileType type) : LoadModule(type) {} diff --git a/src/renderer/tvgLoader.cpp b/src/renderer/tvgLoader.cpp index ad455c07..2719c727 100644 --- a/src/renderer/tvgLoader.cpp +++ b/src/renderer/tvgLoader.cpp @@ -205,7 +205,7 @@ static LoadModule* _findFromCache(const char* filename) ScopedLock lock(key); INLIST_FOREACH(_activeLoaders, loader) { - if (loader->pathcache && !strcmp(loader->hashpath, filename)) { + if (loader->cached && !strcmp(loader->hashpath, filename)) { ++loader->sharing; return loader; } @@ -260,7 +260,7 @@ bool LoaderMgr::retrieve(LoadModule* loader) { if (!loader) return false; if (loader->close()) { - if (loader->cached()) { + if (loader->cached) { ScopedLock lock(key); _activeLoaders.remove(loader); } @@ -287,8 +287,7 @@ LoadModule* LoaderMgr::loader(const char* filename, bool* invalid) if (auto loader = _findByPath(filename)) { if (loader->open(filename)) { if (allowCache) { - loader->hashpath = duplicate(filename); - loader->pathcache = true; + loader->cache(duplicate(filename)); { ScopedLock lock(key); _activeLoaders.back(loader); @@ -303,8 +302,7 @@ LoadModule* LoaderMgr::loader(const char* filename, bool* invalid) if (auto loader = _find(static_cast(i))) { if (loader->open(filename)) { if (allowCache) { - loader->hashpath = duplicate(filename); - loader->pathcache = true; + loader->cache(duplicate(filename)); { ScopedLock lock(key); _activeLoaders.back(loader); @@ -327,30 +325,6 @@ bool LoaderMgr::retrieve(const char* filename) } -LoadModule* LoaderMgr::loader(const char* key) -{ - INLIST_FOREACH(_activeLoaders, loader) { - if (loader->pathcache && strstr(loader->hashpath, key)) { - ++loader->sharing; - return loader; - } - } - return nullptr; -} - - -LoadModule* LoaderMgr::anyfont() -{ - INLIST_FOREACH(_activeLoaders, loader) { - if ((loader->type == FileType::Ttf) && loader->pathcache) { - ++loader->sharing; - return loader; - } - } - return nullptr; -} - - LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const char* mimeType, const char* rpath, bool copy) { //Note that users could use the same data pointer with the different content. @@ -372,7 +346,7 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const char* mimeT if (auto loader = _findByType(mimeType)) { if (loader->open(data, size, rpath, copy)) { if (allowCache) { - loader->hashkey = HASH_KEY(data); + loader->cache(HASH_KEY(data)); ScopedLock lock(key); _activeLoaders.back(loader); } @@ -389,7 +363,7 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const char* mimeT if (loader) { if (loader->open(data, size, rpath, copy)) { if (allowCache) { - loader->hashkey = HASH_KEY(data); + loader->cache(HASH_KEY(data)); ScopedLock lock(key); _activeLoaders.back(loader); } @@ -415,7 +389,7 @@ LoadModule* LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, Colo auto loader = new RawLoader; if (loader->open(data, w, h, cs, copy)) { if (!copy) { - loader->hashkey = HASH_KEY((const char*)data); + loader->cache(HASH_KEY((const char*)data)); ScopedLock lock(key); _activeLoaders.back(loader); } @@ -431,13 +405,13 @@ LoadModule* LoaderMgr::loader(const char* name, const char* data, uint32_t size, { #ifdef THORVG_TTF_LOADER_SUPPORT //TODO: add check for mimetype ? - if (auto loader = _findFromCache(name)) return loader; + if (auto loader = font(name)) return loader; //function is dedicated for ttf loader (the only supported font loader) auto loader = new TtfLoader; if (loader->open(data, size, "", copy)) { - loader->hashpath = duplicate(name); - loader->pathcache = true; + loader->name = duplicate(name); + loader->cached = true; //force it. ScopedLock lock(key); _activeLoaders.back(loader); return loader; @@ -447,4 +421,29 @@ LoadModule* LoaderMgr::loader(const char* name, const char* data, uint32_t size, delete(loader); #endif return nullptr; -} \ No newline at end of file +} + + +LoadModule* LoaderMgr::font(const char* name) +{ + INLIST_FOREACH(_activeLoaders, loader) { + if (loader->type != FileType::Ttf) continue; + if (loader->cached && tvg::equal(name, static_cast(loader)->name)) { + ++loader->sharing; + return loader; + } + } + return nullptr; +} + + +LoadModule* LoaderMgr::anyfont() +{ + INLIST_FOREACH(_activeLoaders, loader) { + if (loader->cached && loader->type == FileType::Ttf) { + ++loader->sharing; + return loader; + } + } + return nullptr; +} diff --git a/src/renderer/tvgLoader.h b/src/renderer/tvgLoader.h index 8ff940cf..4a345bfe 100644 --- a/src/renderer/tvgLoader.h +++ b/src/renderer/tvgLoader.h @@ -33,7 +33,7 @@ struct LoaderMgr static LoadModule* loader(const char* data, uint32_t size, const char* mimeType, const char* rpath, bool copy); static LoadModule* loader(const uint32_t* data, uint32_t w, uint32_t h, ColorSpace cs, bool copy); static LoadModule* loader(const char* name, const char* data, uint32_t size, const char* mimeType, bool copy); - static LoadModule* loader(const char* key); + static LoadModule* font(const char* name); static LoadModule* anyfont(); static bool retrieve(const char* filename); static bool retrieve(LoadModule* loader); diff --git a/src/renderer/tvgText.cpp b/src/renderer/tvgText.cpp index ae4dca03..35336747 100644 --- a/src/renderer/tvgText.cpp +++ b/src/renderer/tvgText.cpp @@ -67,7 +67,7 @@ Result Text::load(const char* name, const char* data, uint32_t size, const char* //unload font if (!data) { - if (LoaderMgr::retrieve(name)) return Result::Success; + if (LoaderMgr::retrieve(LoaderMgr::font(name))) return Result::Success; return Result::InsufficientCondition; } diff --git a/src/renderer/tvgText.h b/src/renderer/tvgText.h index aa1fc708..e08966cd 100644 --- a/src/renderer/tvgText.h +++ b/src/renderer/tvgText.h @@ -62,7 +62,7 @@ struct Text::Impl : Paint::Impl Result font(const char* name, float size, const char* style) { - auto loader = name ? LoaderMgr::loader(name) : LoaderMgr::anyfont(); + auto loader = name ? LoaderMgr::font(name) : LoaderMgr::anyfont(); if (!loader) return Result::InsufficientCondition; if (style && strstr(style, "italic")) italic = true;