mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-14 06:42:58 +08:00
feat(font) add fallback support and mem. font load option to FreeType (#2796)
* adding font type check * using theme specified font supports freetype drawing * adding font type check * using theme specified font supports freetype drawing * freetype fallback font support * improved fallback font * updated fallback font modifier * docs(events) LV_EVENT_APPLY was removed (#2791) * reverted to default font logic * removed unused function * improved font fallback * font fallback for default lv_draw_letter as well * added back masked drawing support * fallback support for freetype uncached * updated description * fixed constructor initialization for ISO C * reverted unneeded changes * using loop instead of recursion to resolve glyph info * simplified glyph dec resolving * removed unused enum value * improved lv_font_fmt_ft_dsc_t field naming * supports pointer as freetype font source * Updated docs for font fallback Co-authored-by: Vincent Hamp <higaski@users.noreply.github.com> Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
parent
57cde348fa
commit
3ea4d66411
@ -251,3 +251,19 @@ const uint8_t * my_get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_
|
||||
return bitmap; /*Or NULL if not found*/
|
||||
}
|
||||
```
|
||||
|
||||
## Use font fallback
|
||||
|
||||
You can specify `fallback` in `lv_font_t` to provide fallback to the font. When the font
|
||||
fails to find glyph to a letter, it will try to let font from `fallback` to handle.
|
||||
|
||||
`fallback` can be chained, so it will try to solve until there is no `fallback` set.
|
||||
|
||||
```c
|
||||
/* Roboto font doesn't have support for CJK glyphs */
|
||||
lv_font_t *roboto = my_font_load_function();
|
||||
/* Droid Sans Fallback has more glyphs but its typeface doesn't look good as Roboto */
|
||||
lv_font_t *droid_sans_fallback = my_font_load_function();
|
||||
/* So now we can display Roboto for supported characters while having wider characters set support */
|
||||
roboto->fallback = droid_sans_fallback;
|
||||
```
|
@ -449,6 +449,9 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_letter(const lv_point_t * pos_p, const lv_are
|
||||
return;
|
||||
}
|
||||
|
||||
if (g.resolved_font) {
|
||||
font_p = g.resolved_font;
|
||||
}
|
||||
const uint8_t * map_p = lv_font_get_glyph_bitmap(font_p, letter);
|
||||
if(map_p == NULL) {
|
||||
LV_LOG_WARN("lv_draw_letter: character's bitmap not found");
|
||||
|
@ -23,6 +23,8 @@
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct {
|
||||
const void * mem;
|
||||
long size;
|
||||
char * name;
|
||||
} lv_face_info_t;
|
||||
|
||||
@ -49,8 +51,6 @@ static FT_Error font_face_requester(FTC_FaceID face_id,
|
||||
FT_Library library_is, FT_Pointer req_data, FT_Face * aface);
|
||||
static bool lv_ft_font_init_cache(lv_ft_info_t * info);
|
||||
static void lv_ft_font_destroy_cache(lv_font_t * font);
|
||||
static bool lv_ft_font_init_cache(lv_ft_info_t * info);
|
||||
static void lv_ft_font_destroy_cache(lv_font_t * font);
|
||||
#else
|
||||
static FT_Face face_find_in_list(lv_ft_info_t * info);
|
||||
static void face_add_to_list(FT_Face face);
|
||||
@ -59,7 +59,6 @@ static void face_generic_finalizer(void * object);
|
||||
static bool lv_ft_font_init_nocache(lv_ft_info_t * info);
|
||||
static void lv_ft_font_destroy_nocache(lv_font_t * font);
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
@ -163,7 +162,12 @@ static FT_Error font_face_requester(FTC_FaceID face_id,
|
||||
LV_UNUSED(req_data);
|
||||
|
||||
lv_face_info_t * info = (lv_face_info_t *)face_id;
|
||||
FT_Error error = FT_New_Face(library, info->name, 0, aface);
|
||||
FT_Error error;
|
||||
if (info->mem) {
|
||||
error = FT_New_Memory_Face(library, info->mem, info->size, 0, aface);
|
||||
} else {
|
||||
error = FT_New_Face(library, info->name, 0, aface);
|
||||
}
|
||||
if(error) {
|
||||
LV_LOG_ERROR("FT_New_Face error:%d\n", error);
|
||||
return error;
|
||||
@ -209,6 +213,7 @@ static bool get_glyph_dsc_cb_cache(const lv_font_t * font,
|
||||
dsc_out->ofs_x = sbit->left; /*X offset of the bitmap in [pf]*/
|
||||
dsc_out->ofs_y = sbit->top - sbit->height; /*Y offset of the bitmap measured from the as line*/
|
||||
dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
|
||||
dsc_out->is_placeholder = glyph_index == 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -230,12 +235,14 @@ static bool lv_ft_font_init_cache(lv_ft_info_t * info)
|
||||
lv_mem_free(dsc);
|
||||
return false;
|
||||
}
|
||||
|
||||
lv_memset_00(dsc->font, sizeof(lv_font_t));
|
||||
lv_face_info_t * face_info = NULL;
|
||||
face_info = lv_mem_alloc(sizeof(lv_face_info_t) + strlen(info->name) + 1);
|
||||
if(face_info == NULL) {
|
||||
goto Fail;
|
||||
}
|
||||
face_info->mem = info->mem;
|
||||
face_info->size = info->mem_size;
|
||||
face_info->name = ((char *)face_info) + sizeof(lv_face_info_t);
|
||||
strcpy(face_info->name, info->name);
|
||||
|
||||
@ -294,7 +301,6 @@ void lv_ft_font_destroy_cache(lv_font_t * font)
|
||||
lv_mem_free(dsc);
|
||||
}
|
||||
}
|
||||
|
||||
#else/* LV_FREETYPE_CACHE_SIZE */
|
||||
|
||||
static FT_Face face_find_in_list(lv_ft_info_t * info)
|
||||
@ -366,6 +372,7 @@ static bool get_glyph_dsc_cb_nocache(const lv_font_t * font,
|
||||
if(face->size != dsc->size) {
|
||||
FT_Activate_Size(dsc->size);
|
||||
}
|
||||
dsc_out->is_placeholder = glyph_index == 0;
|
||||
|
||||
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
|
||||
if(error) {
|
||||
@ -406,6 +413,7 @@ static bool lv_ft_font_init_nocache(lv_ft_info_t * info)
|
||||
lv_mem_free(dsc);
|
||||
return false;
|
||||
}
|
||||
lv_memset_00(dsc->font, sizeof(lv_font_t));
|
||||
|
||||
lv_face_info_t * face_info = NULL;
|
||||
FT_Face face = face_find_in_list(info);
|
||||
@ -414,7 +422,12 @@ static bool lv_ft_font_init_nocache(lv_ft_info_t * info)
|
||||
if(face_info == NULL) {
|
||||
goto Fail;
|
||||
}
|
||||
FT_Error error = FT_New_Face(library, info->name, 0, &face);
|
||||
FT_Error error;
|
||||
if (info->mem) {
|
||||
error = FT_New_Memory_Face(library, info->mem, (FT_Long) info->mem_size, 0, &face);
|
||||
} else {
|
||||
error = FT_New_Face(library, info->name, 0, &face);
|
||||
}
|
||||
if(error) {
|
||||
lv_mem_free(face_info);
|
||||
LV_LOG_WARN("create face error(%d)", error);
|
||||
@ -422,6 +435,8 @@ static bool lv_ft_font_init_nocache(lv_ft_info_t * info)
|
||||
}
|
||||
|
||||
/* link face and face info */
|
||||
face_info->mem = info->mem;
|
||||
face_info->size = (long) info->mem_size;
|
||||
face_info->name = ((char *)face_info) + sizeof(lv_face_info_t);
|
||||
strcpy(face_info->name, info->name);
|
||||
face->generic.data = face_info;
|
||||
|
@ -30,6 +30,8 @@ typedef enum {
|
||||
|
||||
typedef struct {
|
||||
const char * name; /* The name of the font file */
|
||||
const void * mem; /* The pointer of the font file */
|
||||
size_t mem_size; /* The size of the memory */
|
||||
lv_font_t * font; /* point to lvgl font */
|
||||
uint16_t weight; /* font size */
|
||||
uint16_t style; /* font style */
|
||||
|
@ -65,7 +65,19 @@ bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_o
|
||||
uint32_t letter_next)
|
||||
{
|
||||
LV_ASSERT_NULL(font_p);
|
||||
return font_p->get_glyph_dsc(font_p, dsc_out, letter, letter_next);
|
||||
LV_ASSERT_NULL(dsc_out);
|
||||
dsc_out->resolved_font = NULL;
|
||||
const lv_font_t * f = font_p;
|
||||
bool found = false;
|
||||
while(f) {
|
||||
found = f->get_glyph_dsc(f, dsc_out, letter, letter_next);
|
||||
if (found && !dsc_out->is_placeholder) {
|
||||
dsc_out->resolved_font = f;
|
||||
break;
|
||||
}
|
||||
f = f->fallback;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,14 +33,17 @@ extern "C" {
|
||||
* General types
|
||||
*-----------------*/
|
||||
|
||||
struct _lv_font_t;
|
||||
/** Describes the properties of a glyph.*/
|
||||
typedef struct {
|
||||
const struct _lv_font_t *resolved_font; /**< Pointer to a font where the gylph was actually found after handling fallbacks*/
|
||||
uint16_t adv_w; /**< The glyph needs this space. Draw the next glyph after this width.*/
|
||||
uint16_t box_w; /**< Width of the glyph's bounding box*/
|
||||
uint16_t box_h; /**< Height of the glyph's bounding box*/
|
||||
int16_t ofs_x; /**< x offset of the bounding box*/
|
||||
int16_t ofs_y; /**< y offset of the bounding box*/
|
||||
uint8_t bpp; /**< Bit-per-pixel: 1, 2, 4, 8*/
|
||||
uint8_t bpp:4; /**< Bit-per-pixel: 1, 2, 4, 8*/
|
||||
uint8_t is_placeholder:1; /** Glyph is missing. But placeholder will still be displayed */
|
||||
} lv_font_glyph_dsc_t;
|
||||
|
||||
/** The bitmaps might be upscaled by 3 to achieve subpixel rendering.*/
|
||||
@ -70,6 +73,7 @@ typedef struct _lv_font_t {
|
||||
int8_t underline_thickness; /**< Thickness of the underline*/
|
||||
|
||||
const void * dsc; /**< Store implementation specific or run_time data or caching here*/
|
||||
const struct _lv_font_t * fallback; /**< Fallback font for missing glyph. Resolved recursively */
|
||||
#if LV_USE_USER_DATA
|
||||
void * user_data; /**< Custom user data for font.*/
|
||||
#endif
|
||||
|
@ -182,6 +182,7 @@ bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t * font, lv_font_glyph_dsc_t *
|
||||
dsc_out->ofs_x = gdsc->ofs_x;
|
||||
dsc_out->ofs_y = gdsc->ofs_y;
|
||||
dsc_out->bpp = (uint8_t)fdsc->bpp;
|
||||
dsc_out->is_placeholder = false;
|
||||
|
||||
if(is_tab) dsc_out->box_w = dsc_out->box_w * 2;
|
||||
|
||||
|
@ -30,15 +30,11 @@
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct lv_sdl_font_atlas_t {
|
||||
SDL_Rect * pos;
|
||||
} lv_sdl_font_atlas_t;
|
||||
|
||||
typedef struct {
|
||||
lv_gpu_cache_key_magic_t magic;
|
||||
const lv_font_t * font_p;
|
||||
uint32_t cmap_index;
|
||||
} lv_font_key_t;
|
||||
uint32_t letter;
|
||||
} lv_font_glyph_key_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
@ -47,17 +43,8 @@ typedef struct {
|
||||
static void draw_letter_masked(SDL_Renderer * renderer, SDL_Texture * atlas, SDL_Rect * src, SDL_Rect * dst,
|
||||
SDL_Rect * clip, lv_color_t color, lv_opa_t opa);
|
||||
|
||||
static void font_atlas_free(lv_sdl_font_atlas_t * atlas);
|
||||
static lv_font_glyph_key_t font_key_glyph_create(const lv_font_t * font_p, uint32_t letter);
|
||||
|
||||
static SDL_Texture * font_atlas_bake(SDL_Renderer * renderer, const lv_font_t * font_p, uint32_t cmap_idx,
|
||||
lv_sdl_font_atlas_t * atlas);
|
||||
|
||||
static int32_t unicode_list_compare(const void * ref, const void * element);
|
||||
|
||||
static bool font_cmap_find_index(const lv_font_fmt_txt_dsc_t * dsc, uint32_t letter, uint32_t * cmap_index,
|
||||
uint32_t * char_index);
|
||||
|
||||
static lv_font_key_t font_key_create(const lv_font_t * font_p, uint32_t cmap_index);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@ -109,33 +96,38 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * clip_area,
|
||||
pos_y > clip_area->y2) {
|
||||
return;
|
||||
}
|
||||
lv_area_t dst = {pos_x, pos_y, pos_x + g.box_w - 1, pos_y + g.box_h - 1};
|
||||
uint32_t atlas_index;
|
||||
uint32_t cmap_index;
|
||||
if(!font_cmap_find_index(font_p->dsc, letter, &cmap_index, &atlas_index)) {
|
||||
return;
|
||||
}
|
||||
lv_font_key_t key = font_key_create(font_p, cmap_index);
|
||||
lv_sdl_font_atlas_t * atlas = NULL;
|
||||
bool found = false;
|
||||
SDL_Texture * texture = lv_gpu_draw_cache_get_with_userdata(&key, sizeof(key), &found, (void **) &atlas);
|
||||
|
||||
lv_disp_t * disp = _lv_refr_get_disp_refreshing();
|
||||
SDL_Renderer * renderer = (SDL_Renderer *) disp->driver->user_data;
|
||||
|
||||
if(!found) {
|
||||
atlas = SDL_malloc(sizeof(lv_sdl_font_atlas_t));
|
||||
texture = font_atlas_bake(renderer, font_p, cmap_index, atlas);
|
||||
lv_gpu_draw_cache_put_advanced(&key, sizeof(key), texture, atlas, (lv_lru_free_t *) font_atlas_free, 0);
|
||||
lv_font_glyph_key_t glyph_key = font_key_glyph_create(font_p, letter);
|
||||
bool glyph_found = false;
|
||||
SDL_Texture *texture = lv_gpu_draw_cache_get(&glyph_key, sizeof(glyph_key), &glyph_found);
|
||||
if (!glyph_found) {
|
||||
if (g.resolved_font) {
|
||||
font_p = g.resolved_font;
|
||||
}
|
||||
const uint8_t *bmp = lv_font_get_glyph_bitmap(font_p, letter);
|
||||
uint8_t *buf = lv_mem_alloc(g.box_w * g.box_h);
|
||||
lv_sdl_to_8bpp(buf, bmp, g.box_w, g.box_h, g.box_w, g.bpp);
|
||||
SDL_Surface * mask = lv_sdl_create_mask_surface(buf, g.box_w, g.box_h, g.box_w);
|
||||
texture = SDL_CreateTextureFromSurface(renderer, mask);
|
||||
SDL_FreeSurface(mask);
|
||||
lv_mem_free(buf);
|
||||
lv_gpu_draw_cache_put(&glyph_key, sizeof(glyph_key), texture);
|
||||
}
|
||||
if(texture == NULL) return;
|
||||
SDL_Rect dstrect = {.x = pos_x, .y = pos_y, .w = g.box_w, .h = g.box_h};
|
||||
if (!texture) {
|
||||
return;
|
||||
}
|
||||
lv_area_t dst = {pos_x, pos_y, pos_x + g.box_w - 1, pos_y + g.box_h - 1};
|
||||
SDL_Rect dstrect;
|
||||
lv_area_to_sdl_rect(&dst, &dstrect);
|
||||
|
||||
SDL_Rect clip_area_rect;
|
||||
lv_area_to_sdl_rect(clip_area, &clip_area_rect);
|
||||
|
||||
if(lv_draw_mask_is_any(&dst)) {
|
||||
draw_letter_masked(renderer, texture, &atlas->pos[atlas_index], &dstrect, &clip_area_rect, color, opa);
|
||||
draw_letter_masked(renderer, texture, NULL, &dstrect, &clip_area_rect, color, opa);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -143,10 +135,9 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * clip_area,
|
||||
SDL_SetTextureAlphaMod(texture, opa);
|
||||
SDL_SetTextureColorMod(texture, color.ch.red, color.ch.green, color.ch.blue);
|
||||
SDL_RenderSetClipRect(renderer, &clip_area_rect);
|
||||
SDL_RenderCopy(renderer, texture, &atlas->pos[atlas_index], &dstrect);
|
||||
SDL_RenderCopy(renderer, texture, NULL, &dstrect);
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@ -192,140 +183,14 @@ static void draw_letter_masked(SDL_Renderer * renderer, SDL_Texture * atlas, SDL
|
||||
SDL_DestroyTexture(mask);
|
||||
}
|
||||
|
||||
SDL_Texture * font_atlas_bake(SDL_Renderer * renderer, const lv_font_t * font_p, uint32_t cmap_idx,
|
||||
lv_sdl_font_atlas_t * atlas)
|
||||
static lv_font_glyph_key_t font_key_glyph_create(const lv_font_t * font_p, uint32_t letter)
|
||||
{
|
||||
/* Clear atlas struct */
|
||||
SDL_memset(atlas, 0, sizeof(lv_sdl_font_atlas_t));
|
||||
const lv_font_fmt_txt_dsc_t * dsc = (lv_font_fmt_txt_dsc_t *) font_p->dsc;
|
||||
if(dsc->bitmap_format != LV_FONT_FMT_TXT_PLAIN) {
|
||||
/* we don't support compressed font at this moment */
|
||||
return NULL;
|
||||
}
|
||||
const lv_font_fmt_txt_cmap_t * cmap = &dsc->cmaps[cmap_idx];
|
||||
int glyph_count = cmap->type == LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY ? cmap->range_length : cmap->list_length;
|
||||
int atlas_size = 0;
|
||||
while(atlas_size * atlas_size < glyph_count) {
|
||||
atlas_size++;
|
||||
}
|
||||
int atlas_w = font_p->line_height * atlas_size;
|
||||
int atlas_h = font_p->line_height * (glyph_count / atlas_size + 1);
|
||||
if(atlas_w > 2048 || atlas_h > 2048) {
|
||||
/*This atlas texture will be too large to load*/
|
||||
return NULL;
|
||||
}
|
||||
lv_opa_t * s1 = lv_mem_buf_get(atlas_w * atlas_h * sizeof(lv_opa_t));
|
||||
atlas->pos = SDL_malloc(sizeof(SDL_Rect) * glyph_count);
|
||||
int atlas_y = 0;
|
||||
int atlas_x = 0;
|
||||
for(int i = 0; i < glyph_count; i++) {
|
||||
int glyph_idx = cmap->glyph_id_start + i;
|
||||
switch(cmap->type) {
|
||||
case LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL: {
|
||||
const uint8_t * gid_ofs_8 = cmap->glyph_id_ofs_list;
|
||||
glyph_idx = gid_ofs_8[i];
|
||||
break;
|
||||
}
|
||||
case LV_FONT_FMT_TXT_CMAP_SPARSE_FULL: {
|
||||
const uint16_t * gid_ofs_16 = cmap->glyph_id_ofs_list;
|
||||
glyph_idx = gid_ofs_16[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
const lv_font_fmt_txt_glyph_dsc_t * gd = &dsc->glyph_dsc[glyph_idx];
|
||||
if(atlas_x + gd->box_w >= atlas_w) {
|
||||
atlas_x = 0;
|
||||
atlas_y += font_p->line_height;
|
||||
}
|
||||
SDL_Rect * rect = &atlas->pos[i];
|
||||
rect->x = atlas_x;
|
||||
rect->y = atlas_y;
|
||||
rect->w = gd->box_w;
|
||||
rect->h = gd->box_h;
|
||||
if(gd->box_w <= 0 || gd->box_h <= 0) {
|
||||
continue;
|
||||
}
|
||||
lv_sdl_to_8bpp(&s1[rect->y * atlas_w + rect->x], &dsc->glyph_bitmap[gd->bitmap_index], rect->w,
|
||||
rect->h, atlas_w, dsc->bpp);
|
||||
atlas_x += gd->box_w;
|
||||
}
|
||||
SDL_Surface * mask = lv_sdl_create_mask_surface(s1, atlas_w, atlas_h, atlas_w);
|
||||
SDL_Texture * result = SDL_CreateTextureFromSurface(renderer, mask);
|
||||
SDL_FreeSurface(mask);
|
||||
lv_mem_buf_release(s1);
|
||||
|
||||
if(!result) {
|
||||
if(atlas->pos) {
|
||||
SDL_free(atlas->pos);
|
||||
}
|
||||
SDL_memset(atlas, 0, sizeof(lv_sdl_font_atlas_t));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void font_atlas_free(lv_sdl_font_atlas_t * atlas)
|
||||
{
|
||||
if(atlas->pos) {
|
||||
SDL_free(atlas->pos);
|
||||
}
|
||||
SDL_free(atlas);
|
||||
}
|
||||
|
||||
static bool font_cmap_find_index(const lv_font_fmt_txt_dsc_t * dsc, uint32_t letter, uint32_t * cmap_index,
|
||||
uint32_t * char_index)
|
||||
{
|
||||
for(int i = 0; i < dsc->cmap_num; i++) {
|
||||
const lv_font_fmt_txt_cmap_t * cmap = &dsc->cmaps[i];
|
||||
/*Relative code point*/
|
||||
uint32_t rcp = letter - cmap->range_start;
|
||||
if(rcp > cmap->range_length) continue;
|
||||
if(cmap->type == LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY) {
|
||||
*cmap_index = i;
|
||||
*char_index = rcp;
|
||||
return true;
|
||||
}
|
||||
else if(cmap->type == LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL) {
|
||||
*cmap_index = i;
|
||||
*char_index = rcp;
|
||||
return true;
|
||||
}
|
||||
else if(cmap->type == LV_FONT_FMT_TXT_CMAP_SPARSE_TINY) {
|
||||
uint16_t key = rcp;
|
||||
uint16_t * p = _lv_utils_bsearch(&key, cmap->unicode_list, cmap->list_length,
|
||||
sizeof(cmap->unicode_list[0]), unicode_list_compare);
|
||||
if(!p) continue;
|
||||
|
||||
*cmap_index = i;
|
||||
*char_index = p - cmap->unicode_list;
|
||||
return true;
|
||||
}
|
||||
else if(cmap->type == LV_FONT_FMT_TXT_CMAP_SPARSE_FULL) {
|
||||
uint16_t key = rcp;
|
||||
uint16_t * p = _lv_utils_bsearch(&key, cmap->unicode_list, cmap->list_length,
|
||||
sizeof(cmap->unicode_list[0]), unicode_list_compare);
|
||||
if(!p) continue;
|
||||
|
||||
*cmap_index = i;
|
||||
*char_index = p - cmap->unicode_list;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t unicode_list_compare(const void * ref, const void * element)
|
||||
{
|
||||
return ((int32_t)(*(uint16_t *) ref)) - ((int32_t)(*(uint16_t *) element));
|
||||
}
|
||||
|
||||
static lv_font_key_t font_key_create(const lv_font_t * font_p, uint32_t cmap_index)
|
||||
{
|
||||
lv_font_key_t key;
|
||||
lv_font_glyph_key_t key;
|
||||
/* VERY IMPORTANT! Padding between members is uninitialized, so we have to wipe them manually */
|
||||
SDL_memset(&key, 0, sizeof(key));
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_FONT;
|
||||
key.magic = LV_GPU_CACHE_KEY_MAGIC_FONT_GLYPH;
|
||||
key.font_p = font_p;
|
||||
key.cmap_index = cmap_index;
|
||||
key.letter = letter;
|
||||
return key;
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ typedef enum {
|
||||
LV_GPU_CACHE_KEY_MAGIC_RECT_BG = 0x31,
|
||||
LV_GPU_CACHE_KEY_MAGIC_RECT_SHADOW = 0x32,
|
||||
LV_GPU_CACHE_KEY_MAGIC_RECT_BORDER = 0x33,
|
||||
LV_GPU_CACHE_KEY_MAGIC_FONT = 0x41,
|
||||
LV_GPU_CACHE_KEY_MAGIC_FONT_GLYPH = 0x41,
|
||||
LV_GPU_CACHE_KEY_TEMP = 0xFF,
|
||||
} lv_gpu_cache_key_magic_t;
|
||||
|
||||
|
@ -163,7 +163,7 @@ void lv_sdl_to_8bpp(uint8_t * dest, const uint8_t * src, int width, int height,
|
||||
while(cur < src_len) {
|
||||
curbit = 8 - bpp;
|
||||
uint8_t src_byte = src[cur * bpp / 8];
|
||||
while(curbit >= 0) {
|
||||
while(curbit >= 0 && cur < src_len) {
|
||||
uint8_t src_bits = opa_mask & (src_byte >> curbit);
|
||||
dest[(cur / width * stride) + (cur % width)] = opa_table[src_bits];
|
||||
curbit -= bpp;
|
||||
|
Loading…
x
Reference in New Issue
Block a user