mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
feat(tiny_ttf): add glyph caching (#3703)
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
parent
d214b00386
commit
ccb66ca701
@ -12,6 +12,7 @@
|
|||||||
png
|
png
|
||||||
gif
|
gif
|
||||||
freetype
|
freetype
|
||||||
|
tiny_ttf
|
||||||
qrcode
|
qrcode
|
||||||
rlottie
|
rlottie
|
||||||
ffmpeg
|
ffmpeg
|
||||||
|
@ -12,6 +12,7 @@ However, if `LV_TINY_TTF_FILE_SUPPORT` is enabled, `lv_tiny_ttf_create_file(path
|
|||||||
|
|
||||||
After a font is created, you can change the size by using `lv_tiny_ttf_set_size(font, line_height)`.
|
After a font is created, you can change the size by using `lv_tiny_ttf_set_size(font, line_height)`.
|
||||||
|
|
||||||
|
By default, a font will use up to 4KB of cache to speed up rendering glyphs. This maximum can be changed by using `lv_tiny_ttf_create_data_ex(data, data_size, line_height, cache_size)` or `lv_tiny_ttf_create_file_ex(path, line_height, cache_size)` (when available). The cache size is indicated in bytes.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
```eval_rst
|
```eval_rst
|
||||||
|
@ -1,17 +1,220 @@
|
|||||||
#include "../../../lvgl.h"
|
#include "lv_tiny_ttf.h"
|
||||||
#include "../../misc/lv_gc.h"
|
|
||||||
#if LV_USE_TINY_TTF
|
#if LV_USE_TINY_TTF
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "lv_tiny_ttf.h"
|
|
||||||
|
#ifndef LV_TINY_TTF_DEFAULT_CACHE_SIZE
|
||||||
|
#define LV_TINY_TTF_DEFAULT_CACHE_SIZE 4096
|
||||||
|
#endif
|
||||||
|
#ifndef LV_TINY_TTF_CACHE_BUCKETS
|
||||||
|
#define LV_TINY_TTF_CACHE_BUCKETS 16
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STB_RECT_PACK_IMPLEMENTATION
|
#define STB_RECT_PACK_IMPLEMENTATION
|
||||||
|
#define STBRP_STATIC
|
||||||
|
#define STBTT_STATIC
|
||||||
#define STB_TRUETYPE_IMPLEMENTATION
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
#define STBTT_HEAP_FACTOR_SIZE_32 50
|
#define STBTT_HEAP_FACTOR_SIZE_32 50
|
||||||
#define STBTT_HEAP_FACTOR_SIZE_128 20
|
#define STBTT_HEAP_FACTOR_SIZE_128 20
|
||||||
#define STBTT_HEAP_FACTOR_SIZE_DEFAULT 10
|
#define STBTT_HEAP_FACTOR_SIZE_DEFAULT 10
|
||||||
#define STBTT_malloc(x,u) ((void)(u),lv_malloc(x))
|
#define STBTT_malloc(x,u) ((void)(u),lv_malloc(x))
|
||||||
#define STBTT_free(x,u) ((void)(u),lv_free(x))
|
#define STBTT_free(x,u) ((void)(u),lv_free(x))
|
||||||
|
#define TTF_CACHE_MALLOC(x) (lv_malloc(x))
|
||||||
|
#define TTF_CACHE_REALLOC(x,y) (lv_realloc(x,y))
|
||||||
|
#define TTF_CACHE_FREE(x) (lv_free(x))
|
||||||
|
#define TTF_MALLOC(x) (lv_malloc(x))
|
||||||
|
#define TTF_FREE(x) (lv_free(x))
|
||||||
|
typedef void * ttf_cache_handle_t;
|
||||||
|
typedef struct ttf_cache_entry {
|
||||||
|
int key;
|
||||||
|
unsigned long long age;
|
||||||
|
int size;
|
||||||
|
void * data;
|
||||||
|
} ttf_cache_entry_t;
|
||||||
|
typedef struct ttf_cache_bucket {
|
||||||
|
int capacity;
|
||||||
|
ttf_cache_entry_t * entries;
|
||||||
|
} ttf_cache_bucket_t;
|
||||||
|
|
||||||
|
typedef struct ttf_cache {
|
||||||
|
int max_size;
|
||||||
|
int bucket_size;
|
||||||
|
int total_size;
|
||||||
|
unsigned long long age;
|
||||||
|
ttf_cache_bucket_t * buckets;
|
||||||
|
} ttf_cache_t;
|
||||||
|
|
||||||
|
static unsigned long long ttf_cache_get_oldest_age(ttf_cache_handle_t * handle)
|
||||||
|
{
|
||||||
|
ttf_cache_t * cache = (ttf_cache_t *)handle;
|
||||||
|
unsigned long long result = (unsigned long long) - 1;
|
||||||
|
for(int i = 0; i < cache->bucket_size; ++i) {
|
||||||
|
ttf_cache_bucket_t * bucket = &cache->buckets[i];
|
||||||
|
if(bucket->entries != NULL) {
|
||||||
|
for(int j = 0; j < bucket->capacity; ++j) {
|
||||||
|
ttf_cache_entry_t * entry = &bucket->entries[j];
|
||||||
|
if(entry->age != 0 && entry->age < result) {
|
||||||
|
result = entry->age;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(result == (unsigned long long) - 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
static ttf_cache_handle_t ttf_cache_create(int max_size, int buckets)
|
||||||
|
{
|
||||||
|
ttf_cache_t * result = (ttf_cache_t *)TTF_CACHE_MALLOC(sizeof(ttf_cache_t));
|
||||||
|
if(result == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
result->age = 1;
|
||||||
|
result->max_size = max_size;
|
||||||
|
result->total_size = 0;
|
||||||
|
result->bucket_size = buckets;
|
||||||
|
result->buckets = (ttf_cache_bucket_t *)TTF_CACHE_MALLOC(buckets * sizeof(ttf_cache_bucket_t));
|
||||||
|
if(result->buckets == NULL) {
|
||||||
|
TTF_CACHE_FREE(result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for(int i = 0; i < buckets; ++i) {
|
||||||
|
result->buckets[i].capacity = 0;
|
||||||
|
result->buckets[i].entries = NULL;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
static void * ttf_cache_get(ttf_cache_handle_t handle, int key)
|
||||||
|
{
|
||||||
|
if(handle == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ttf_cache_t * cache = (ttf_cache_t *)handle;
|
||||||
|
int ci = key % cache->bucket_size;
|
||||||
|
ttf_cache_bucket_t * bucket = &cache->buckets[ci];
|
||||||
|
for(int i = 0; i < bucket->capacity; ++i) {
|
||||||
|
ttf_cache_entry_t * entry = &bucket->entries[i];
|
||||||
|
if(entry->age != 0 && entry->key == key) {
|
||||||
|
entry->age = ++cache->age;
|
||||||
|
return entry->data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
static void * ttf_cache_add(ttf_cache_handle_t handle, int key, int size)
|
||||||
|
{
|
||||||
|
if(handle == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ttf_cache_t * cache = (ttf_cache_t *)handle;
|
||||||
|
int ci = key % cache->bucket_size;
|
||||||
|
ttf_cache_bucket_t * bucket = &cache->buckets[ci];
|
||||||
|
for(int i = 0; i < bucket->capacity; ++i) {
|
||||||
|
ttf_cache_entry_t * entry = &bucket->entries[i];
|
||||||
|
if(entry->age != 0 && entry->key == key) {
|
||||||
|
TTF_CACHE_FREE(entry->data);
|
||||||
|
cache->total_size -= entry->size;
|
||||||
|
entry->age = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(cache->total_size > 0 && (cache->max_size < cache->total_size + size)) {
|
||||||
|
// expire entries
|
||||||
|
unsigned long long oldest = ttf_cache_get_oldest_age(handle);
|
||||||
|
if(oldest == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for(int i = 0; i < cache->bucket_size; ++i) {
|
||||||
|
ttf_cache_bucket_t * bucket2 = &cache->buckets[i];
|
||||||
|
for(int j = 0; j < bucket2->capacity; ++j) {
|
||||||
|
ttf_cache_entry_t * entry = &bucket2->entries[j];
|
||||||
|
if(entry->age == oldest) {
|
||||||
|
if(entry->data != NULL) {
|
||||||
|
TTF_CACHE_FREE(entry->data);
|
||||||
|
entry->data = NULL;
|
||||||
|
entry->age = 0;
|
||||||
|
cache->total_size -= entry->size;
|
||||||
|
entry->size = 0;
|
||||||
|
i = cache->bucket_size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(bucket->entries == NULL) {
|
||||||
|
bucket->capacity = 4;
|
||||||
|
bucket->entries = (ttf_cache_entry_t *)TTF_CACHE_MALLOC(sizeof(ttf_cache_entry_t) * bucket->capacity);
|
||||||
|
if(bucket->entries == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for(int i = 0; i < bucket->capacity; ++i) {
|
||||||
|
bucket->entries[i].age = 0;
|
||||||
|
bucket->entries[i].data = NULL;
|
||||||
|
bucket->entries[i].size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int i = 0; i < bucket->capacity; ++i) {
|
||||||
|
ttf_cache_entry_t * entry = &bucket->entries[i];
|
||||||
|
if(entry->age == 0) {
|
||||||
|
entry->data = TTF_CACHE_MALLOC(size);
|
||||||
|
if(entry->data == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
entry->size = size;
|
||||||
|
entry->age = cache->age;
|
||||||
|
entry->key = key;
|
||||||
|
cache->total_size += size;
|
||||||
|
return entry->data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int newcap = bucket->capacity * 2;
|
||||||
|
ttf_cache_entry_t * te = (ttf_cache_entry_t *)TTF_CACHE_REALLOC(bucket->entries, sizeof(ttf_cache_entry_t) * newcap);
|
||||||
|
if(te == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bucket->entries = te;
|
||||||
|
for(int i = bucket->capacity; i < newcap; ++i) {
|
||||||
|
bucket->entries[i].age = 0;
|
||||||
|
bucket->entries[i].data = NULL;
|
||||||
|
bucket->entries[i].size = 0;
|
||||||
|
}
|
||||||
|
void * result = TTF_CACHE_MALLOC(size);
|
||||||
|
bucket->entries[bucket->capacity].data = result;
|
||||||
|
if(result == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bucket->entries[bucket->capacity].size = size;
|
||||||
|
bucket->entries[bucket->capacity].age = cache->age;
|
||||||
|
bucket->entries[bucket->capacity].key = key;
|
||||||
|
bucket->capacity = newcap;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ttf_cache_clear(ttf_cache_handle_t handle)
|
||||||
|
{
|
||||||
|
if(handle == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ttf_cache_t * cache = (ttf_cache_t *)handle;
|
||||||
|
for(int i = 0; i < cache->bucket_size; ++i) {
|
||||||
|
ttf_cache_bucket_t * bucket = &cache->buckets[i];
|
||||||
|
if(bucket->entries != NULL) {
|
||||||
|
for(int j = 0; j < bucket->capacity; ++j) {
|
||||||
|
ttf_cache_entry_t * entry = &bucket->entries[j];
|
||||||
|
if(entry->age != 0 && entry->data != NULL) {
|
||||||
|
TTF_CACHE_FREE(entry->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TTF_CACHE_FREE(cache->buckets[i].entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void ttf_cache_destroy(ttf_cache_handle_t handle)
|
||||||
|
{
|
||||||
|
ttf_cache_clear(handle);
|
||||||
|
TTF_CACHE_FREE((ttf_cache_t *)handle);
|
||||||
|
}
|
||||||
#if LV_TINY_TTF_FILE_SUPPORT !=0
|
#if LV_TINY_TTF_FILE_SUPPORT !=0
|
||||||
// a hydra stream that can be in memory or from a file
|
// a hydra stream that can be in memory or from a file
|
||||||
typedef struct ttf_cb_stream {
|
typedef struct ttf_cb_stream {
|
||||||
@ -63,9 +266,10 @@ typedef struct ttf_font_desc {
|
|||||||
#if LV_TINY_TTF_FILE_SUPPORT !=0
|
#if LV_TINY_TTF_FILE_SUPPORT !=0
|
||||||
ttf_cb_stream_t stream;
|
ttf_cb_stream_t stream;
|
||||||
#else
|
#else
|
||||||
const unsigned char * stream;
|
const uint8_t * stream;
|
||||||
#endif
|
#endif
|
||||||
stbtt_fontinfo info;
|
stbtt_fontinfo info;
|
||||||
|
ttf_cache_handle_t cache;
|
||||||
float scale;
|
float scale;
|
||||||
int ascent;
|
int ascent;
|
||||||
int descent;
|
int descent;
|
||||||
@ -115,53 +319,52 @@ static const uint8_t * ttf_get_glyph_bitmap_cb(const lv_font_t * font, uint32_t
|
|||||||
{
|
{
|
||||||
ttf_font_desc_t * dsc = (ttf_font_desc_t *)font->dsc;
|
ttf_font_desc_t * dsc = (ttf_font_desc_t *)font->dsc;
|
||||||
const stbtt_fontinfo * info = (const stbtt_fontinfo *)&dsc->info;
|
const stbtt_fontinfo * info = (const stbtt_fontinfo *)&dsc->info;
|
||||||
static size_t buffer_size = 0;
|
uint8_t * buffer = (uint8_t *)ttf_cache_get(dsc->cache, unicode_letter);
|
||||||
int g1 = stbtt_FindGlyphIndex(info, (int)unicode_letter);
|
if(buffer == NULL) {
|
||||||
int x1, y1, x2, y2;
|
int g1 = stbtt_FindGlyphIndex(info, (int)unicode_letter);
|
||||||
stbtt_GetGlyphBitmapBox(info, g1, dsc->scale, dsc->scale, &x1, &y1, &x2, &y2);
|
int x1, y1, x2, y2;
|
||||||
int w, h;
|
stbtt_GetGlyphBitmapBox(info, g1, dsc->scale, dsc->scale, &x1, &y1, &x2, &y2);
|
||||||
w = x2 - x1 + 1;
|
int w, h;
|
||||||
h = y2 - y1 + 1;
|
w = x2 - x1 + 1;
|
||||||
if(LV_GC_ROOT(_ttf_glyph_bitmap_buffer) == NULL) {
|
h = y2 - y1 + 1;
|
||||||
buffer_size = (size_t)(w * h);
|
int buffer_size = w * h;
|
||||||
LV_GC_ROOT(_ttf_glyph_bitmap_buffer) = (uint8_t *)lv_malloc(buffer_size);
|
buffer = ttf_cache_add(dsc->cache, unicode_letter, buffer_size);
|
||||||
if(LV_GC_ROOT(_ttf_glyph_bitmap_buffer) == NULL) {
|
if(buffer == NULL) {
|
||||||
buffer_size = 0;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(LV_GC_ROOT(_ttf_glyph_bitmap_buffer), 0, buffer_size);
|
memset(buffer, 0, buffer_size);
|
||||||
|
stbtt_MakeGlyphBitmap(info, buffer, w, h, w, dsc->scale, dsc->scale, g1);
|
||||||
}
|
}
|
||||||
else {
|
return buffer; /*Or NULL if not found*/
|
||||||
size_t s = w * h;
|
|
||||||
if(s > buffer_size) {
|
|
||||||
buffer_size = s;
|
|
||||||
LV_GC_ROOT(_ttf_glyph_bitmap_buffer) = (uint8_t *)lv_realloc(LV_GC_ROOT(_ttf_glyph_bitmap_buffer), buffer_size);
|
|
||||||
if(LV_GC_ROOT(_ttf_glyph_bitmap_buffer) == NULL) {
|
|
||||||
buffer_size = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memset(LV_GC_ROOT(_ttf_glyph_bitmap_buffer), 0, buffer_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stbtt_MakeGlyphBitmap(info, LV_GC_ROOT(_ttf_glyph_bitmap_buffer), w, h, w, dsc->scale, dsc->scale, g1);
|
|
||||||
return LV_GC_ROOT(_ttf_glyph_bitmap_buffer); /*Or NULL if not found*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size_t data_size, lv_coord_t line_height)
|
static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size_t data_size, lv_coord_t line_height,
|
||||||
|
size_t cache_size)
|
||||||
{
|
{
|
||||||
|
LV_UNUSED(data_size);
|
||||||
if((path == NULL && data == NULL) || 0 >= line_height) {
|
if((path == NULL && data == NULL) || 0 >= line_height) {
|
||||||
LV_LOG_ERROR("tiny_ttf: invalid argument\n");
|
LV_LOG_ERROR("tiny_ttf: invalid argument\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ttf_font_desc_t * dsc = (ttf_font_desc_t *)lv_malloc(sizeof(ttf_font_desc_t));
|
if(cache_size < 1) {
|
||||||
|
cache_size = LV_TINY_TTF_DEFAULT_CACHE_SIZE;
|
||||||
|
}
|
||||||
|
ttf_font_desc_t * dsc = (ttf_font_desc_t *)TTF_MALLOC(sizeof(ttf_font_desc_t));
|
||||||
if(dsc == NULL) {
|
if(dsc == NULL) {
|
||||||
LV_LOG_ERROR("tiny_ttf: out of memory\n");
|
LV_LOG_ERROR("tiny_ttf: out of memory\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
dsc->cache = ttf_cache_create(cache_size, LV_TINY_TTF_CACHE_BUCKETS);
|
||||||
|
if(dsc->cache == NULL) {
|
||||||
|
LV_LOG_ERROR("tiny_ttf: out of memory\n");
|
||||||
|
TTF_FREE(dsc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
#if LV_TINY_TTF_FILE_SUPPORT !=0
|
#if LV_TINY_TTF_FILE_SUPPORT !=0
|
||||||
if(path != NULL) {
|
if(path != NULL) {
|
||||||
if(LV_FS_RES_OK != lv_fs_open(&dsc->file, path, LV_FS_MODE_RD)) {
|
if(LV_FS_RES_OK != lv_fs_open(&dsc->file, path, LV_FS_MODE_RD)) {
|
||||||
|
ttf_cache_destroy(dsc->cache);
|
||||||
|
TTF_FREE(dsc);
|
||||||
LV_LOG_ERROR("tiny_ttf: unable to open %s\n", path);
|
LV_LOG_ERROR("tiny_ttf: unable to open %s\n", path);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -174,25 +377,29 @@ static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size
|
|||||||
dsc->stream.position = 0;
|
dsc->stream.position = 0;
|
||||||
}
|
}
|
||||||
if(0 == stbtt_InitFont(&dsc->info, &dsc->stream, stbtt_GetFontOffsetForIndex(&dsc->stream, 0))) {
|
if(0 == stbtt_InitFont(&dsc->info, &dsc->stream, stbtt_GetFontOffsetForIndex(&dsc->stream, 0))) {
|
||||||
lv_free(dsc);
|
ttf_cache_destroy(dsc->cache);
|
||||||
|
TTF_FREE(dsc);
|
||||||
|
|
||||||
LV_LOG_ERROR("tiny_ttf: init failed\n");
|
LV_LOG_ERROR("tiny_ttf: init failed\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
LV_UNUSED(data_size);
|
|
||||||
dsc->stream = (const uint8_t *)data;
|
dsc->stream = (const uint8_t *)data;
|
||||||
if(0 == stbtt_InitFont(&dsc->info, dsc->stream, stbtt_GetFontOffsetForIndex(dsc->stream, 0))) {
|
if(0 == stbtt_InitFont(&dsc->info, dsc->stream, stbtt_GetFontOffsetForIndex(dsc->stream, 0))) {
|
||||||
lv_free(dsc);
|
ttf_cache_destroy(dsc->cache);
|
||||||
|
TTF_FREE(dsc);
|
||||||
LV_LOG_ERROR("tiny_ttf: init failed\n");
|
LV_LOG_ERROR("tiny_ttf: init failed\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float scale = stbtt_ScaleForPixelHeight(&dsc->info, line_height);
|
float scale = stbtt_ScaleForPixelHeight(&dsc->info, line_height);
|
||||||
lv_font_t * out_font = (lv_font_t *)lv_malloc(sizeof(lv_font_t));
|
lv_font_t * out_font = (lv_font_t *)TTF_MALLOC(sizeof(lv_font_t));
|
||||||
if(out_font == NULL) {
|
if(out_font == NULL) {
|
||||||
lv_free(dsc);
|
ttf_cache_destroy(dsc->cache);
|
||||||
|
TTF_FREE(dsc);
|
||||||
LV_LOG_ERROR("tiny_ttf: out of memory\n");
|
LV_LOG_ERROR("tiny_ttf: out of memory\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -211,14 +418,22 @@ static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size
|
|||||||
return out_font;
|
return out_font;
|
||||||
}
|
}
|
||||||
#if LV_TINY_TTF_FILE_SUPPORT !=0
|
#if LV_TINY_TTF_FILE_SUPPORT !=0
|
||||||
|
lv_font_t * lv_tiny_ttf_create_file_ex(const char * path, lv_coord_t line_height, size_t cache_size)
|
||||||
|
{
|
||||||
|
return lv_tiny_ttf_create(path, NULL, 0, line_height, cache_size);
|
||||||
|
}
|
||||||
lv_font_t * lv_tiny_ttf_create_file(const char * path, lv_coord_t line_height)
|
lv_font_t * lv_tiny_ttf_create_file(const char * path, lv_coord_t line_height)
|
||||||
{
|
{
|
||||||
return lv_tiny_ttf_create(path, NULL, 0, line_height);
|
return lv_tiny_ttf_create(path, NULL, 0, line_height, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
lv_font_t * lv_tiny_ttf_create_data_ex(const void * data, size_t data_size, lv_coord_t line_height, size_t cache_size)
|
||||||
|
{
|
||||||
|
return lv_tiny_ttf_create(NULL, data, data_size, line_height, cache_size);
|
||||||
|
}
|
||||||
lv_font_t * lv_tiny_ttf_create_data(const void * data, size_t data_size, lv_coord_t line_height)
|
lv_font_t * lv_tiny_ttf_create_data(const void * data, size_t data_size, lv_coord_t line_height)
|
||||||
{
|
{
|
||||||
return lv_tiny_ttf_create(NULL, data, data_size, line_height);
|
return lv_tiny_ttf_create(NULL, data, data_size, line_height, 0);
|
||||||
}
|
}
|
||||||
void lv_tiny_ttf_set_size(lv_font_t * font, lv_coord_t line_height)
|
void lv_tiny_ttf_set_size(lv_font_t * font, lv_coord_t line_height)
|
||||||
{
|
{
|
||||||
@ -228,6 +443,7 @@ void lv_tiny_ttf_set_size(lv_font_t * font, lv_coord_t line_height)
|
|||||||
dsc->scale = stbtt_ScaleForPixelHeight(&dsc->info, line_height);
|
dsc->scale = stbtt_ScaleForPixelHeight(&dsc->info, line_height);
|
||||||
font->base_line = line_height - (lv_coord_t)(dsc->ascent * dsc->scale);
|
font->base_line = line_height - (lv_coord_t)(dsc->ascent * dsc->scale);
|
||||||
font->underline_position = (uint8_t)line_height - dsc->descent;
|
font->underline_position = (uint8_t)line_height - dsc->descent;
|
||||||
|
ttf_cache_clear(dsc->cache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void lv_tiny_ttf_destroy(lv_font_t * font)
|
void lv_tiny_ttf_destroy(lv_font_t * font)
|
||||||
@ -235,14 +451,15 @@ void lv_tiny_ttf_destroy(lv_font_t * font)
|
|||||||
if(font != NULL) {
|
if(font != NULL) {
|
||||||
if(font->dsc != NULL) {
|
if(font->dsc != NULL) {
|
||||||
ttf_font_desc_t * ttf = (ttf_font_desc_t *)font->dsc;
|
ttf_font_desc_t * ttf = (ttf_font_desc_t *)font->dsc;
|
||||||
|
ttf_cache_destroy(ttf->cache);
|
||||||
#if LV_TINY_TTF_FILE_SUPPORT !=0
|
#if LV_TINY_TTF_FILE_SUPPORT !=0
|
||||||
if(ttf->stream.file != NULL) {
|
if(ttf->stream.file != NULL) {
|
||||||
lv_fs_close(&ttf->file);
|
lv_fs_close(&ttf->file);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
lv_free(ttf);
|
TTF_FREE(ttf);
|
||||||
}
|
}
|
||||||
lv_free(font);
|
TTF_FREE(font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,11 +31,17 @@ extern "C" {
|
|||||||
#if LV_TINY_TTF_FILE_SUPPORT !=0
|
#if LV_TINY_TTF_FILE_SUPPORT !=0
|
||||||
// create a font from the specified file or path with the specified line height.
|
// create a font from the specified file or path with the specified line height.
|
||||||
lv_font_t * lv_tiny_ttf_create_file(const char * path, lv_coord_t line_height);
|
lv_font_t * lv_tiny_ttf_create_file(const char * path, lv_coord_t line_height);
|
||||||
#endif // LV_TINY_TTF_FILE_SUPPORT !=0
|
|
||||||
|
// create a font from the specified file or path with the specified line height with the specified cache size.
|
||||||
|
lv_font_t * lv_tiny_ttf_create_file_ex(const char * path, lv_coord_t line_height, size_t cache_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
// create a font from the specified data pointer with the specified line height.
|
// create a font from the specified data pointer with the specified line height.
|
||||||
lv_font_t * lv_tiny_ttf_create_data(const void * data, size_t data_size, lv_coord_t line_height);
|
lv_font_t * lv_tiny_ttf_create_data(const void * data, size_t data_size, lv_coord_t line_height);
|
||||||
|
|
||||||
|
// create a font from the specified data pointer with the specified line height and the specified cache size.
|
||||||
|
lv_font_t * lv_tiny_ttf_create_data_ex(const void * data, size_t data_size, lv_coord_t line_height, size_t cache_size);
|
||||||
|
|
||||||
// set the size of the font to a new line_height
|
// set the size of the font to a new line_height
|
||||||
void lv_tiny_ttf_set_size(lv_font_t * font, lv_coord_t line_height);
|
void lv_tiny_ttf_set_size(lv_font_t * font, lv_coord_t line_height);
|
||||||
|
|
||||||
|
@ -87,6 +87,12 @@ typedef int stbrp_coord;
|
|||||||
#define STBRP__MAXVAL 0x7fffffff
|
#define STBRP__MAXVAL 0x7fffffff
|
||||||
// Mostly for internal use, but this is the maximum supported coordinate value.
|
// Mostly for internal use, but this is the maximum supported coordinate value.
|
||||||
|
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
STBRP_DEF int stbrp_pack_rects(stbrp_context * context, stbrp_rect * rects, int num_rects);
|
STBRP_DEF int stbrp_pack_rects(stbrp_context * context, stbrp_rect * rects, int num_rects);
|
||||||
// Assign packed locations to rectangles. The rectangles are of type
|
// Assign packed locations to rectangles. The rectangles are of type
|
||||||
// 'stbrp_rect' defined below, stored in the array 'rects', and there
|
// 'stbrp_rect' defined below, stored in the array 'rects', and there
|
||||||
@ -579,6 +585,10 @@ STBRP_DEF int stbrp_pack_rects(stbrp_context * context, stbrp_rect * rects, int
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
This software is available under 2 licenses -- choose whichever you prefer.
|
This software is available under 2 licenses -- choose whichever you prefer.
|
||||||
|
@ -553,6 +553,11 @@ typedef struct {
|
|||||||
int size;
|
int size;
|
||||||
} stbtt__buf;
|
} stbtt__buf;
|
||||||
|
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// TEXTURE BAKING API
|
// TEXTURE BAKING API
|
||||||
@ -5443,6 +5448,7 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char * s1, int len1, cons
|
|||||||
|
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // STB_TRUETYPE_IMPLEMENTATION
|
#endif // STB_TRUETYPE_IMPLEMENTATION
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 23 KiB |
Loading…
x
Reference in New Issue
Block a user