mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-14 06:42:58 +08:00
feat(tiny_ttf): use draw_buf and the cache (#4639)
Co-authored-by: Fabian Blatz <fabianblatz@gmail.com> Co-authored-by: Mike Fikes <mike@fikesfarm.com> Co-authored-by: Zoltan Janosy <janosy.zoltan@gmail.com> Co-authored-by: Zoltan Janosy <zjanosy@fishman.com> Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
parent
8c63327f66
commit
cc628426b8
@ -2,13 +2,6 @@
|
||||
#if LV_USE_TINY_TTF
|
||||
#include <stdio.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 STBRP_STATIC
|
||||
#define STBTT_STATIC
|
||||
@ -16,209 +9,12 @@
|
||||
#define STBTT_HEAP_FACTOR_SIZE_32 50
|
||||
#define STBTT_HEAP_FACTOR_SIZE_128 20
|
||||
#define STBTT_HEAP_FACTOR_SIZE_DEFAULT 10
|
||||
#define STBTT_malloc(x,u) ((void)(u),lv_malloc(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;
|
||||
#define STBTT_malloc(x, u) ((void)(u), lv_malloc(x))
|
||||
#define STBTT_free(x, u) ((void)(u), lv_free(x))
|
||||
#define TTF_MALLOC(x) (lv_malloc(x))
|
||||
#define TTF_FREE(x) (lv_free(x))
|
||||
|
||||
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);
|
||||
cache->buckets[i].entries = NULL;
|
||||
cache->buckets[i].capacity = 0;
|
||||
}
|
||||
}
|
||||
cache->total_size = 0;
|
||||
}
|
||||
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*/
|
||||
typedef struct ttf_cb_stream {
|
||||
lv_fs_file_t * file;
|
||||
@ -256,9 +52,10 @@ static void ttf_cb_stream_seek(ttf_cb_stream_t * stream, size_t position)
|
||||
}
|
||||
}
|
||||
|
||||
#define STBTT_STREAM_TYPE ttf_cb_stream_t*
|
||||
#define STBTT_STREAM_SEEK(s,x) ttf_cb_stream_seek(s,x);
|
||||
#define STBTT_STREAM_READ(s,x,y) ttf_cb_stream_read(s,x,y);
|
||||
/* for stream support */
|
||||
#define STBTT_STREAM_TYPE ttf_cb_stream_t *
|
||||
#define STBTT_STREAM_SEEK(s, x) ttf_cb_stream_seek(s, x);
|
||||
#define STBTT_STREAM_READ(s, x, y) ttf_cb_stream_read(s, x, y);
|
||||
#endif
|
||||
|
||||
#include "stb_rect_pack.h"
|
||||
@ -266,18 +63,21 @@ static void ttf_cb_stream_seek(ttf_cb_stream_t * stream, size_t position)
|
||||
|
||||
typedef struct ttf_font_desc {
|
||||
lv_fs_file_t file;
|
||||
#if LV_TINY_TTF_FILE_SUPPORT !=0
|
||||
#if LV_TINY_TTF_FILE_SUPPORT != 0
|
||||
ttf_cb_stream_t stream;
|
||||
#else
|
||||
const uint8_t * stream;
|
||||
#endif
|
||||
stbtt_fontinfo info;
|
||||
ttf_cache_handle_t cache;
|
||||
float scale;
|
||||
int ascent;
|
||||
int descent;
|
||||
} ttf_font_desc_t;
|
||||
|
||||
typedef struct ttf_cache_entry {
|
||||
uint8_t * buffer;
|
||||
} ttf_cache_entry_t;
|
||||
|
||||
static bool ttf_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter,
|
||||
uint32_t unicode_letter_next)
|
||||
{
|
||||
@ -286,15 +86,19 @@ static bool ttf_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * d
|
||||
unicode_letter == 0x200c) { /*ZERO WIDTH NON-JOINER*/
|
||||
dsc_out->box_w = 0;
|
||||
dsc_out->adv_w = 0;
|
||||
dsc_out->box_h = 0; /*height of the bitmap in [px]*/
|
||||
dsc_out->ofs_x = 0; /*X offset of the bitmap in [pf]*/
|
||||
dsc_out->ofs_y = 0; /*Y offset of the bitmap in [pf]*/
|
||||
dsc_out->box_h = 0; /*height of the bitmap in [px]*/
|
||||
dsc_out->ofs_x = 0; /*X offset of the bitmap in [pf]*/
|
||||
dsc_out->ofs_y = 0; /*Y offset of the bitmap in [pf]*/
|
||||
dsc_out->bpp = 0;
|
||||
dsc_out->is_placeholder = false;
|
||||
return true;
|
||||
}
|
||||
ttf_font_desc_t * dsc = (ttf_font_desc_t *)font->dsc;
|
||||
int g1 = stbtt_FindGlyphIndex(&dsc->info, (int)unicode_letter);
|
||||
if(g1 == 0) {
|
||||
/* Glyph not found */
|
||||
return false;
|
||||
}
|
||||
int x1, y1, x2, y2;
|
||||
|
||||
stbtt_GetGlyphBitmapBox(&dsc->info, g1, dsc->scale, dsc->scale, &x1, &y1, &x2, &y2);
|
||||
@ -310,13 +114,13 @@ static bool ttf_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * d
|
||||
|
||||
dsc_out->adv_w = (uint16_t)floor((((float)advw + (float)k) * dsc->scale) +
|
||||
0.5f); /*Horizontal space required by the glyph in [px]*/
|
||||
dsc_out->box_w = (x2 - x1 + 1); /*width of the bitmap in [px]*/
|
||||
dsc_out->box_h = (y2 - y1 + 1); /*height of the bitmap in [px]*/
|
||||
dsc_out->ofs_x = x1; /*X offset of the bitmap in [pf]*/
|
||||
dsc_out->ofs_y = -y2; /*Y offset of the bitmap measured from the as line*/
|
||||
dsc_out->bpp = 8; /*Bits per pixel: 1/2/4/8*/
|
||||
dsc_out->box_w = (x2 - x1 + 1); /*width of the bitmap in [px]*/
|
||||
dsc_out->box_h = (y2 - y1 + 1); /*height of the bitmap in [px]*/
|
||||
dsc_out->ofs_x = x1; /*X offset of the bitmap in [pf]*/
|
||||
dsc_out->ofs_y = -y2; /*Y offset of the bitmap measured from the as line*/
|
||||
dsc_out->bpp = 8; /*Bits per pixel: 1/2/4/8*/
|
||||
dsc_out->is_placeholder = false;
|
||||
return true; /*true: glyph found; false: glyph was not found*/
|
||||
return true; /*true: glyph found; false: glyph was not found*/
|
||||
}
|
||||
|
||||
static const uint8_t * ttf_get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter, uint8_t * bitmap_buf)
|
||||
@ -324,52 +128,67 @@ static const uint8_t * ttf_get_glyph_bitmap_cb(const lv_font_t * font, uint32_t
|
||||
LV_UNUSED(bitmap_buf);
|
||||
ttf_font_desc_t * dsc = (ttf_font_desc_t *)font->dsc;
|
||||
const stbtt_fontinfo * info = (const stbtt_fontinfo *)&dsc->info;
|
||||
uint8_t * buffer = (uint8_t *)ttf_cache_get(dsc->cache, unicode_letter);
|
||||
if(buffer == NULL) {
|
||||
int g1 = stbtt_FindGlyphIndex(info, (int)unicode_letter);
|
||||
int x1, y1, x2, y2;
|
||||
stbtt_GetGlyphBitmapBox(info, g1, dsc->scale, dsc->scale, &x1, &y1, &x2, &y2);
|
||||
int w, h;
|
||||
w = x2 - x1 + 1;
|
||||
h = y2 - y1 + 1;
|
||||
int buffer_size = w * h;
|
||||
buffer = ttf_cache_add(dsc->cache, unicode_letter, buffer_size);
|
||||
if(buffer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(buffer, 0, buffer_size);
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(w, LV_COLOR_FORMAT_A8);
|
||||
stbtt_MakeGlyphBitmap(info, buffer, w, h, stride, dsc->scale, dsc->scale, g1);
|
||||
int g1 = stbtt_FindGlyphIndex(info, (int)unicode_letter);
|
||||
if(g1 == 0) {
|
||||
/* Glyph not found */
|
||||
return NULL;
|
||||
}
|
||||
int x1, y1, x2, y2;
|
||||
stbtt_GetGlyphBitmapBox(info, g1, dsc->scale, dsc->scale, &x1, &y1, &x2, &y2);
|
||||
int w, h;
|
||||
w = x2 - x1 + 1;
|
||||
h = y2 - y1 + 1;
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(w, LV_COLOR_FORMAT_A8);
|
||||
lv_cache_lock();
|
||||
uint32_t cp = unicode_letter;
|
||||
lv_cache_entry_t * cache = lv_cache_find(font + cp, LV_CACHE_SRC_TYPE_PTR, 0, 0);
|
||||
if(cache) {
|
||||
uint8_t * buffer = (uint8_t *)lv_cache_get_data(cache);
|
||||
lv_cache_unlock();
|
||||
return buffer;
|
||||
}
|
||||
size_t szb = h * stride;
|
||||
lv_cache_entry_t * entry = lv_cache_add(szb);
|
||||
if(entry == NULL) {
|
||||
lv_cache_unlock();
|
||||
LV_LOG_ERROR("tiny_ttf: cache not allocated\n");
|
||||
return NULL;
|
||||
}
|
||||
/* This smells. We add the codepoint to the base pointer to get a key. */
|
||||
entry->src = font + cp;
|
||||
entry->src_type = LV_CACHE_SRC_TYPE_PTR;
|
||||
uint8_t * buffer = lv_draw_buf_malloc(szb, LV_COLOR_FORMAT_A8);
|
||||
if(NULL == buffer) {
|
||||
LV_LOG_ERROR("tiny_ttf: out of memory\n");
|
||||
lv_cache_invalidate(entry);
|
||||
lv_cache_unlock();
|
||||
return NULL;
|
||||
}
|
||||
entry->data = buffer;
|
||||
entry->free_data = 1;
|
||||
memset(buffer, 0, szb);
|
||||
stbtt_MakeGlyphBitmap(info, buffer, w, h, stride, dsc->scale, dsc->scale, g1);
|
||||
lv_cache_unlock();
|
||||
return 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);
|
||||
LV_UNUSED(cache_size);
|
||||
if((path == NULL && data == NULL) || 0 >= line_height) {
|
||||
LV_LOG_ERROR("tiny_ttf: invalid argument\n");
|
||||
return NULL;
|
||||
}
|
||||
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) {
|
||||
LV_LOG_ERROR("tiny_ttf: out of memory\n");
|
||||
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(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);
|
||||
return NULL;
|
||||
@ -383,7 +202,6 @@ static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size
|
||||
dsc->stream.position = 0;
|
||||
}
|
||||
if(0 == stbtt_InitFont(&dsc->info, &dsc->stream, stbtt_GetFontOffsetForIndex(&dsc->stream, 0))) {
|
||||
ttf_cache_destroy(dsc->cache);
|
||||
TTF_FREE(dsc);
|
||||
|
||||
LV_LOG_ERROR("tiny_ttf: init failed\n");
|
||||
@ -393,7 +211,6 @@ static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size
|
||||
#else
|
||||
dsc->stream = (const uint8_t *)data;
|
||||
if(0 == stbtt_InitFont(&dsc->info, dsc->stream, stbtt_GetFontOffsetForIndex(dsc->stream, 0))) {
|
||||
ttf_cache_destroy(dsc->cache);
|
||||
TTF_FREE(dsc);
|
||||
LV_LOG_ERROR("tiny_ttf: init failed\n");
|
||||
return NULL;
|
||||
@ -404,7 +221,6 @@ static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size
|
||||
float scale = stbtt_ScaleForPixelHeight(&dsc->info, line_height);
|
||||
lv_font_t * out_font = (lv_font_t *)TTF_MALLOC(sizeof(lv_font_t));
|
||||
if(out_font == NULL) {
|
||||
ttf_cache_destroy(dsc->cache);
|
||||
TTF_FREE(dsc);
|
||||
LV_LOG_ERROR("tiny_ttf: out of memory\n");
|
||||
return NULL;
|
||||
@ -423,7 +239,7 @@ static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size
|
||||
out_font->get_glyph_bitmap = ttf_get_glyph_bitmap_cb;
|
||||
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);
|
||||
@ -449,7 +265,6 @@ void lv_tiny_ttf_set_size(lv_font_t * font, lv_coord_t line_height)
|
||||
dsc->scale = stbtt_ScaleForPixelHeight(&dsc->info, line_height);
|
||||
font->base_line = line_height - (lv_coord_t)(dsc->ascent * dsc->scale);
|
||||
font->underline_position = (uint8_t)line_height - dsc->descent;
|
||||
ttf_cache_clear(dsc->cache);
|
||||
}
|
||||
}
|
||||
void lv_tiny_ttf_destroy(lv_font_t * font)
|
||||
@ -457,8 +272,7 @@ void lv_tiny_ttf_destroy(lv_font_t * font)
|
||||
if(font != NULL) {
|
||||
if(font->dsc != NULL) {
|
||||
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) {
|
||||
lv_fs_close(&ttf->file);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user