diff --git a/examples/StrokeMiterlimit.cpp b/examples/StrokeMiterlimit.cpp index a3f245a3..594118bb 100644 --- a/examples/StrokeMiterlimit.cpp +++ b/examples/StrokeMiterlimit.cpp @@ -73,7 +73,7 @@ struct UserExample : tvgexam::Example //blueprint { // Load png file from path. - string path = EXAMPLE_DIR"/image/stroke-miterlimit.png"; + const char* path = EXAMPLE_DIR"/image/stroke-miterlimit.png"; auto picture = tvg::Picture::gen(); if (!tvgexam::verify(picture->load(path))) return false; diff --git a/inc/thorvg.h b/inc/thorvg.h index 8d7504e4..7ad73c14 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -3,7 +3,6 @@ #include #include -#include #include #ifdef TVG_API @@ -1233,7 +1232,7 @@ public: * This means that loading the same file again will not result in duplicate operations; * instead, ThorVG will reuse the previously loaded picture data. * - * @param[in] path A path to the picture file. + * @param[in] filename A file name, including the path, for the picture file. * * @retval Result::InvalidArguments In case the @p path is invalid. * @retval Result::NonSupport When trying to load a file with an unknown extension. @@ -1241,7 +1240,7 @@ public: * @note The Load behavior can be asynchronous if the assigned thread number is greater than zero. * @see Initializer::init() */ - Result load(const std::string& path) noexcept; + Result load(const char* filename) noexcept; /** * @brief Loads a picture data from a memory block of a given size. @@ -1264,7 +1263,7 @@ public: * @note If you are unsure about the MIME type, you can provide an empty value like @c "", and thorvg will attempt to figure it out. * @since 0.5 */ - Result load(const char* data, uint32_t size, const std::string& mimeType, const std::string& rpath = "", bool copy = false) noexcept; + Result load(const char* data, uint32_t size, const char* mimeType, const char* rpath = "", bool copy = false) noexcept; /** * @brief Resizes the picture content to the given width and height. @@ -1510,16 +1509,16 @@ public: * This means that loading the same file again will not result in duplicate operations; * instead, ThorVG will reuse the previously loaded font data. * - * @param[in] path The path to the font file. + * @param[in] filename A file name, including the path, for the font file. * * @retval Result::InvalidArguments In case the @p path is invalid. * @retval Result::NonSupport When trying to load a file with an unknown extension. * - * @see Text::unload(const std::string& path) + * @see Text::unload(const char* filename) * * @since 0.15 */ - static Result load(const std::string& path) noexcept; + static Result load(const char* filename) noexcept; /** * @brief Loads a scalable font data (ttf) from a memory block of a given size. @@ -1546,23 +1545,23 @@ public: * * @note 0.15 */ - static Result load(const char* name, const char* data, uint32_t size, const std::string& mimeType = "ttf", bool copy = false) noexcept; + static Result load(const char* name, const char* data, uint32_t size, const char* mimeType = "ttf", bool copy = false) noexcept; /** * @brief Unloads the specified scalable font data (TTF) that was previously loaded. * * This function is used to release resources associated with a font file that has been loaded into memory. * - * @param[in] path The file path of the loaded font. + * @param[in] filename The file name of the loaded font, including the path. * * @retval Result::InsufficientCondition Fails if the loader is not initialized. * * @note If the font data is currently in use, it will not be immediately unloaded. - * @see Text::load(const std::string& path) + * @see Text::load(const char* filename) * * @since 0.15 */ - static Result unload(const std::string& path) noexcept; + static Result unload(const char* filename) noexcept; /** * @brief Creates a new Text object. @@ -1979,7 +1978,7 @@ public: * if you wish to optimize for speed. * * @param[in] paint The paint to be saved with all its associated properties. - * @param[in] path A path to the file, in which the paint data is to be saved. + * @param[in] filename A file name, including the path, where the paint data will be saved. * @param[in] quality The encoded quality level. @c 0 is the minimum, @c 100 is the maximum value(recommended). * * @retval Result::InsufficientCondition If currently saving other resources. @@ -1991,7 +1990,7 @@ public: * * @since 0.5 */ - Result save(std::unique_ptr paint, const std::string& path, uint32_t quality = 100) noexcept; + Result save(std::unique_ptr paint, const char* filename, uint32_t quality = 100) noexcept; /** * @brief Export the provided animation data to the specified file path. @@ -1999,7 +1998,7 @@ public: * This function exports the given animation data to the provided file path. You can also specify the desired frame rate in frames per second (FPS) by providing the fps parameter. * * @param[in] animation The animation to be saved, including all associated properties. - * @param[in] path The path to the file where the animation will be saved. + * @param[in] filename A file name, including the path, where the animation will be saved. * @param[in] quality The encoded quality level. @c 0 is the minimum, @c 100 is the maximum value(recommended). * @param[in] fps The desired frames per second (FPS). For example, to encode data at 60 FPS, pass 60. Pass 0 to keep the original frame data. * @@ -2014,7 +2013,7 @@ public: * * @note Experimental API */ - Result save(std::unique_ptr animation, const std::string& path, uint32_t quality = 100, uint32_t fps = 0) noexcept; + Result save(std::unique_ptr animation, const char* filename, uint32_t quality = 100, uint32_t fps = 0) noexcept; /** * @brief Guarantees that the saving task is finished. diff --git a/src/bindings/wasm/tvgWasmLottieAnimation.cpp b/src/bindings/wasm/tvgWasmLottieAnimation.cpp index 6538a838..78810c26 100644 --- a/src/bindings/wasm/tvgWasmLottieAnimation.cpp +++ b/src/bindings/wasm/tvgWasmLottieAnimation.cpp @@ -228,6 +228,7 @@ public: return false; } + //FIXME: remove this copy, save with a file passing. this->data = data; //back up for saving canvas->clear(true); @@ -239,7 +240,7 @@ public: filetype = "lottie"; } - if (animation->picture()->load(data.c_str(), data.size(), filetype, rpath, false) != Result::Success) { + if (animation->picture()->load(data.c_str(), data.size(), filetype.c_str(), rpath.c_str(), false) != Result::Success) { errorMsg = "load() fail"; return false; } diff --git a/src/common/tvgStr.cpp b/src/common/tvgStr.cpp index 1ebdd41c..ea2062fc 100644 --- a/src/common/tvgStr.cpp +++ b/src/common/tvgStr.cpp @@ -237,4 +237,16 @@ char* strDirname(const char* path) return strDuplicate(path, len); } + +const char* strExtension(const char* filename) +{ + auto ext = filename; + while (ext) { + auto p = strchr(ext, '.'); + if (!p) break; + ext = p + 1; + } + return ext; +} + } diff --git a/src/common/tvgStr.h b/src/common/tvgStr.h index 6b16b4c7..6b1a2be2 100644 --- a/src/common/tvgStr.h +++ b/src/common/tvgStr.h @@ -28,10 +28,11 @@ namespace tvg { -float strToFloat(const char *nPtr, char **endPtr); //convert to float -char* strDuplicate(const char *str, size_t n); //copy the string +float strToFloat(const char *nPtr, char **endPtr); //convert to float +char* strDuplicate(const char *str, size_t n); //copy the string char* strAppend(char* lhs, const char* rhs, size_t n); //append the rhs to the lhs -char* strDirname(const char* path); //return the full directory name +char* strDirname(const char* path); //return the full directory name +const char* strExtension(const char* filename); //return the file extension name } #endif //_TVG_STR_H_ diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index 26952b4f..b2df401b 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -564,7 +564,7 @@ static Paint* _imageBuildHelper(SvgLoaderData& loaderData, SvgNode* node, const auto last = svgPath.find_last_of("/"); imagePath = svgPath.substr(0, (last == string::npos ? 0 : last + 1)) + imagePath; } - if (picture->load(imagePath) != Result::Success) { + if (picture->load(imagePath.c_str()) != Result::Success) { TaskScheduler::async(true); return nullptr; } diff --git a/src/renderer/tvgCommon.h b/src/renderer/tvgCommon.h index 5b3a904a..75e26b3a 100644 --- a/src/renderer/tvgCommon.h +++ b/src/renderer/tvgCommon.h @@ -23,6 +23,7 @@ #ifndef _TVG_COMMON_H_ #define _TVG_COMMON_H_ +#include #include "config.h" #include "thorvg.h" diff --git a/src/renderer/tvgLoader.cpp b/src/renderer/tvgLoader.cpp index 20add2a4..d4bd8ba0 100644 --- a/src/renderer/tvgLoader.cpp +++ b/src/renderer/tvgLoader.cpp @@ -23,6 +23,7 @@ #include #include "tvgInlist.h" +#include "tvgStr.h" #include "tvgLoader.h" #include "tvgLock.h" @@ -158,51 +159,55 @@ static LoadModule* _find(FileType type) } -static LoadModule* _findByPath(const string& path) +static LoadModule* _findByPath(const char* filename) { - auto ext = path.substr(path.find_last_of(".") + 1); - if (!ext.compare("svg")) return _find(FileType::Svg); - if (!ext.compare("json")) return _find(FileType::Lottie); - if (!ext.compare("png")) return _find(FileType::Png); - if (!ext.compare("jpg")) return _find(FileType::Jpg); - if (!ext.compare("webp")) return _find(FileType::Webp); - if (!ext.compare("ttf") || !ext.compare("ttc")) return _find(FileType::Ttf); - if (!ext.compare("otf") || !ext.compare("otc")) return _find(FileType::Ttf); + auto ext = strExtension(filename); + if (!ext) return nullptr; + + if (!strcmp(ext, "svg")) return _find(FileType::Svg); + if (!strcmp(ext, "json")) return _find(FileType::Lottie); + if (!strcmp(ext, "png")) return _find(FileType::Png); + if (!strcmp(ext, "jpg")) return _find(FileType::Jpg); + if (!strcmp(ext, "webp")) return _find(FileType::Webp); + if (!strcmp(ext, "ttf") || !strcmp(ext, "ttc")) return _find(FileType::Ttf); + if (!strcmp(ext, "otf") || !strcmp(ext, "otc")) return _find(FileType::Ttf); return nullptr; } -static FileType _convert(const string& mimeType) +static FileType _convert(const char* mimeType) { + if (!mimeType) return FileType::Unknown; + auto type = FileType::Unknown; - if (mimeType == "svg" || mimeType == "svg+xml") type = FileType::Svg; - else if (mimeType == "ttf" || mimeType == "otf") type = FileType::Ttf; - else if (mimeType == "lottie") type = FileType::Lottie; - else if (mimeType == "raw") type = FileType::Raw; - 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()); + if (!strcmp(mimeType, "svg") || !strcmp(mimeType, "svg+xml")) type = FileType::Svg; + else if (!strcmp(mimeType, "ttf") || !strcmp(mimeType, "otf")) type = FileType::Ttf; + else if (!strcmp(mimeType, "lottie")) type = FileType::Lottie; + else if (!strcmp(mimeType, "raw")) type = FileType::Raw; + else if (!strcmp(mimeType, "png")) type = FileType::Png; + else if (!strcmp(mimeType, "jpg") || !strcmp(mimeType, "jpeg")) type = FileType::Jpg; + else if (!strcmp(mimeType, "webp")) type = FileType::Webp; + else TVGLOG("RENDERER", "Given mimetype is unknown = \"%s\".", mimeType); return type; } -static LoadModule* _findByType(const string& mimeType) +static LoadModule* _findByType(const char* mimeType) { return _find(_convert(mimeType)); } -static LoadModule* _findFromCache(const string& path) +static LoadModule* _findFromCache(const char* filename) { ScopedLock lock(key); auto loader = _activeLoaders.head; while (loader) { - if (loader->pathcache && !strcmp(loader->hashpath, path.c_str())) { + if (loader->pathcache && !strcmp(loader->hashpath, filename)) { ++loader->sharing; return loader; } @@ -212,7 +217,7 @@ static LoadModule* _findFromCache(const string& path) } -static LoadModule* _findFromCache(const char* data, uint32_t size, const string& mimeType) +static LoadModule* _findFromCache(const char* data, uint32_t size, const char* mimeType) { auto type = _convert(mimeType); if (type == FileType::Unknown) return nullptr; @@ -274,23 +279,23 @@ bool LoaderMgr::retrieve(LoadModule* loader) } -LoadModule* LoaderMgr::loader(const string& path, bool* invalid) +LoadModule* LoaderMgr::loader(const char* filename, bool* invalid) { *invalid = false; //TODO: svg & lottie is not sharable. auto allowCache = true; - auto ext = path.substr(path.find_last_of(".") + 1); - if (!ext.compare("svg") || !ext.compare("json")) allowCache = false; + auto ext = strExtension(filename); + if (ext && (!strcmp(ext, "svg") || !strcmp(ext, "json"))) allowCache = false; if (allowCache) { - if (auto loader = _findFromCache(path)) return loader; + if (auto loader = _findFromCache(filename)) return loader; } - if (auto loader = _findByPath(path)) { - if (loader->open(path)) { + if (auto loader = _findByPath(filename)) { + if (loader->open(filename)) { if (allowCache) { - loader->hashpath = strdup(path.c_str()); + loader->hashpath = strdup(filename); loader->pathcache = true; { ScopedLock lock(key); @@ -304,9 +309,9 @@ LoadModule* LoaderMgr::loader(const string& path, bool* invalid) //Unknown MimeType. Try with the candidates in the order for (int i = 0; i < static_cast(FileType::Raw); i++) { if (auto loader = _find(static_cast(i))) { - if (loader->open(path)) { + if (loader->open(filename)) { if (allowCache) { - loader->hashpath = strdup(path.c_str()); + loader->hashpath = strdup(filename); loader->pathcache = true; { ScopedLock lock(key); @@ -323,9 +328,9 @@ LoadModule* LoaderMgr::loader(const string& path, bool* invalid) } -bool LoaderMgr::retrieve(const string& path) +bool LoaderMgr::retrieve(const char* filename) { - return retrieve(_findFromCache(path)); + return retrieve(_findFromCache(filename)); } @@ -344,7 +349,7 @@ LoadModule* LoaderMgr::loader(const char* key) } -LoadModule* 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 char* mimeType, const char* rpath, bool copy) { //Note that users could use the same data pointer with the different content. //Thus caching is only valid for shareable. @@ -361,7 +366,7 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mim } //Try with the given MimeType - if (!mimeType.empty()) { + if (!mimeType) { if (auto loader = _findByType(mimeType)) { if (loader->open(data, size, rpath, copy)) { if (allowCache) { @@ -371,7 +376,7 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mim } return loader; } else { - TVGLOG("LOADER", "Given mimetype \"%s\" seems incorrect or not supported.", mimeType.c_str()); + TVGLOG("LOADER", "Given mimetype \"%s\" seems incorrect or not supported.", mimeType); delete(loader); } } @@ -420,7 +425,7 @@ LoadModule* LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, Colo //loads fonts from memory - loader is cached (regardless of copy value) in order to access it while setting font -LoadModule* LoaderMgr::loader(const char* name, const char* data, uint32_t size, TVG_UNUSED const string& mimeType, bool copy) +LoadModule* LoaderMgr::loader(const char* name, const char* data, uint32_t size, TVG_UNUSED const char* mimeType, bool copy) { #ifdef THORVG_TTF_LOADER_SUPPORT //TODO: add check for mimetype ? diff --git a/src/renderer/tvgLoader.h b/src/renderer/tvgLoader.h index 542afca9..a4529690 100644 --- a/src/renderer/tvgLoader.h +++ b/src/renderer/tvgLoader.h @@ -29,12 +29,12 @@ struct LoaderMgr { static bool init(); static bool term(); - 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 char* filename, bool* invalid); + 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 string& mimeType, 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 bool retrieve(const string& path); + static bool retrieve(const char* filename); static bool retrieve(LoadModule* loader); }; diff --git a/src/renderer/tvgPicture.cpp b/src/renderer/tvgPicture.cpp index d874b418..7bf17f25 100644 --- a/src/renderer/tvgPicture.cpp +++ b/src/renderer/tvgPicture.cpp @@ -154,15 +154,15 @@ Type Picture::type() const noexcept } -Result Picture::load(const std::string& path) noexcept +Result Picture::load(const char* filename) noexcept { - if (path.empty()) return Result::InvalidArguments; + if (!filename) return Result::InvalidArguments; - return pImpl->load(path); + return pImpl->load(filename); } -Result Picture::load(const char* data, uint32_t size, const string& mimeType, const string& rpath, bool copy) noexcept +Result Picture::load(const char* data, uint32_t size, const char* mimeType, const char* rpath, bool copy) noexcept { if (!data || size <= 0) return Result::InvalidArguments; diff --git a/src/renderer/tvgPicture.h b/src/renderer/tvgPicture.h index c9dcc5ba..63e42662 100644 --- a/src/renderer/tvgPicture.h +++ b/src/renderer/tvgPicture.h @@ -122,12 +122,12 @@ struct Picture::Impl return true; } - Result load(const string& path) + Result load(const char* filename) { if (paint || surface) return Result::InsufficientCondition; bool invalid; //Invalid Path - auto loader = static_cast(LoaderMgr::loader(path, &invalid)); + auto loader = static_cast(LoaderMgr::loader(filename, &invalid)); if (!loader) { if (invalid) return Result::InvalidArguments; return Result::NonSupport; @@ -135,7 +135,7 @@ struct Picture::Impl return load(loader); } - Result load(const char* data, uint32_t size, const string& mimeType, const string& rpath, bool copy) + Result load(const char* data, uint32_t size, const char* mimeType, const char* rpath, bool copy) { if (paint || surface) return Result::InsufficientCondition; auto loader = static_cast(LoaderMgr::loader(data, size, mimeType, rpath, copy)); diff --git a/src/renderer/tvgSaver.cpp b/src/renderer/tvgSaver.cpp index e3dc97c5..6bf9fca1 100644 --- a/src/renderer/tvgSaver.cpp +++ b/src/renderer/tvgSaver.cpp @@ -21,6 +21,7 @@ */ #include "tvgCommon.h" +#include "tvgStr.h" #include "tvgSaveModule.h" #include "tvgPaint.h" @@ -77,10 +78,10 @@ static SaveModule* _find(FileType type) } -static SaveModule* _find(const string& path) +static SaveModule* _find(const char* filename) { - auto ext = path.substr(path.find_last_of(".") + 1); - if (!ext.compare("gif")) return _find(FileType::Gif); + auto ext = strExtension(filename); + if (ext && !strcmp(ext, "gif")) return _find(FileType::Gif); return nullptr; } @@ -100,7 +101,7 @@ Saver::~Saver() } -Result Saver::save(unique_ptr paint, const string& path, uint32_t quality) noexcept +Result Saver::save(unique_ptr paint, const char* filename, uint32_t quality) noexcept { auto p = paint.release(); if (!p) return Result::MemoryCorruption; @@ -111,8 +112,8 @@ Result Saver::save(unique_ptr paint, const string& path, uint32_t quality return Result::InsufficientCondition; } - if (auto saveModule = _find(path)) { - if (saveModule->save(p, pImpl->bg, path, quality)) { + if (auto saveModule = _find(filename)) { + if (saveModule->save(p, pImpl->bg, filename, quality)) { pImpl->saveModule = saveModule; return Result::Success; } else { @@ -135,7 +136,7 @@ Result Saver::background(unique_ptr paint) noexcept } -Result Saver::save(unique_ptr animation, const string& path, uint32_t quality, uint32_t fps) noexcept +Result Saver::save(unique_ptr animation, const char* filename, uint32_t quality, uint32_t fps) noexcept { auto a = animation.release(); if (!a) return Result::MemoryCorruption; @@ -154,8 +155,8 @@ Result Saver::save(unique_ptr animation, const string& path, uint32_t return Result::InsufficientCondition; } - if (auto saveModule = _find(path)) { - if (saveModule->save(a, pImpl->bg, path, quality, fps)) { + if (auto saveModule = _find(filename)) { + if (saveModule->save(a, pImpl->bg, filename, quality, fps)) { pImpl->saveModule = saveModule; return Result::Success; } else { diff --git a/src/renderer/tvgText.cpp b/src/renderer/tvgText.cpp index b324b950..8c45837b 100644 --- a/src/renderer/tvgText.cpp +++ b/src/renderer/tvgText.cpp @@ -58,7 +58,7 @@ Result Text::font(const char* name, float size, const char* style) noexcept } -Result Text::load(const std::string& path) noexcept +Result Text::load(const char* path) noexcept { bool invalid; //invalid path if (!LoaderMgr::loader(path, &invalid)) { @@ -70,7 +70,7 @@ Result Text::load(const std::string& path) noexcept } -Result Text::load(const char* name, const char* data, uint32_t size, const string& mimeType, bool copy) noexcept +Result Text::load(const char* name, const char* data, uint32_t size, const char* mimeType, bool copy) noexcept { if (!name || (size == 0 && data)) return Result::InvalidArguments; @@ -85,9 +85,9 @@ Result Text::load(const char* name, const char* data, uint32_t size, const strin } -Result Text::unload(const std::string& path) noexcept +Result Text::unload(const char* filename) noexcept { - if (LoaderMgr::retrieve(path)) return Result::Success; + if (LoaderMgr::retrieve(filename)) return Result::Success; return Result::InsufficientCondition; } diff --git a/tools/lottie2gif/lottie2gif.cpp b/tools/lottie2gif/lottie2gif.cpp index 1548e517..4479bd95 100644 --- a/tools/lottie2gif/lottie2gif.cpp +++ b/tools/lottie2gif/lottie2gif.cpp @@ -73,7 +73,7 @@ private: auto animation = Animation::gen(); auto picture = animation->picture(); - if (picture->load(in) != Result::Success) return false; + if (picture->load(in.c_str()) != Result::Success) return false; float width, height; picture->size(&width, &height); @@ -89,7 +89,7 @@ private: bg->appendRect(0, 0, width * scale, height * scale); saver->background(std::move(bg)); } - if (saver->save(std::move(animation), out, 100, fps) != Result::Success) return false; + if (saver->save(std::move(animation), out.c_str(), 100, fps) != Result::Success) return false; if (saver->sync() != Result::Success) return false; if (Initializer::term() != Result::Success) return false;