ttf_loader: support loading from memory

New text API for loading fonts from memory
is introduced. This is necessary to enable
embedded fonts support.
This commit is contained in:
Mira Grudzinska 2024-06-05 01:13:59 +02:00 committed by Hermet Park
parent f8626d13d1
commit d8a720fb7e
6 changed files with 95 additions and 3 deletions

View file

@ -1571,6 +1571,34 @@ public:
*/
static Result load(const std::string& path) noexcept;
/**
* @brief Loads a scalable font data (ttf) from a memory block of a given size.
*
* ThorVG efficiently caches the loaded font data using the specified @p name as a key.
* This means that loading the same fonts again will not result in duplicate operations.
* Instead, ThorVG will reuse the previously loaded font data.
*
* @param[in] name The name under which the font will be stored and accessible (e.x. in a @p font() API).
* @param[in] data A pointer to a memory location where the content of the font data is stored.
* @param[in] size The size in bytes of the memory occupied by the @p data.
* @param[in] mimeType Mimetype or extension of font data. In case an empty string is provided the loader will be determined automatically.
* @param[in] copy If @c true the data are copied into the engine local buffer, otherwise they are not (default).
*
* @retval Result::Success When succeed.
* @retval Result::InvalidArguments If no name is provided or if @p size is zero while @p data points to a valid memory location.
* @retval Result::NonSupport When trying to load a file with an unsupported extension.
* @retval Result::Unknown If an error occurs at a later stage.
*
* @warning: It's the user responsibility to release the @p data memory.
*
* @note To unload the font data loaded using this API, pass the proper @p name and @c nullptr as @p data.
* @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.
* @note Experimental API
*
* @see Text::font(const char* name, float size, const char* style)
*/
static Result load(const char* name, const char* data, uint32_t size, const std::string& mimeType = "ttf", bool copy = false) noexcept;
/**
* @brief Unloads the specified scalable font data (TTF) that was previously loaded.
*

View file

@ -193,7 +193,13 @@ static uint32_t* _codepoints(const char* text, size_t n)
void TtfLoader::clear()
{
_unmap(this);
if (nomap) {
if (freeData) free(reader.data);
reader.data = nullptr;
reader.size = 0;
freeData = false;
nomap = false;
} else _unmap(this);
shape = nullptr;
}
@ -236,6 +242,22 @@ bool TtfLoader::open(const string& path)
}
bool TtfLoader::open(const char* data, uint32_t size, TVG_UNUSED const string& rpath, bool copy)
{
reader.size = size;
nomap = true;
if (copy) {
reader.data = (uint8_t*)malloc(size);
if (!reader.data) return false;
memcpy((char*)reader.data, data, reader.size);
freeData = true;
} else reader.data = (uint8_t*)data;
return reader.header();
}
bool TtfLoader::request(Shape* shape, char* text, bool italic)
{
this->shape = shape;

View file

@ -37,12 +37,15 @@ struct TtfLoader : public FontLoader
char* text = nullptr;
Shape* shape = nullptr;
bool italic = false;
bool nomap = false;
bool freeData = false;
TtfLoader();
~TtfLoader();
using FontLoader::open;
bool open(const string& path) override;
bool open(const char *data, uint32_t size, const string& rpath, bool copy) override;
bool resize(Paint* paint, float w, float h) override;
bool request(Shape* shape, char* text, bool italic = false) override;
bool read() override;

View file

@ -433,3 +433,26 @@ LoadModule* LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool
delete(loader);
return nullptr;
}
//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, const string& mimeType, bool copy)
{
//TODO: add check for mimetype ?
if (auto loader = _findFromCache(name)) return loader;
if (auto loader = _findByType(mimeType)) {
if (loader->open(data, size, "", copy)) {
loader->hashpath = strdup(name);
loader->pathcache = true;
ScopedLock lock(key);
_activeLoaders.back(loader);
return loader;
} else {
TVGLOG("LOADER", "The font data \"%s\" could not be loaded.", name);
delete(loader);
}
}
return nullptr;
}

View file

@ -32,6 +32,7 @@ struct LoaderMgr
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 LoadModule* loader(const char* name, const char* data, uint32_t size, const string& mimeType, bool copy);
static LoadModule* loader(const char* key);
static bool retrieve(const string& path);
static bool retrieve(LoadModule* loader);

View file

@ -71,6 +71,21 @@ 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
{
if (!name || (size == 0 && data)) return Result::InvalidArguments;
//unload font
if (!data) {
if (LoaderMgr::retrieve(name)) return Result::Success;
return Result::InvalidArguments;
}
if (!LoaderMgr::loader(name, data, size, mimeType, copy)) return Result::NonSupport;
return Result::Success;
}
Result Text::unload(const std::string& path) noexcept
{
if (LoaderMgr::retrieve(path)) return Result::Success;