1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-21 06:53:01 +08:00

font: use binary search

This commit is contained in:
Gabor Kiss-Vamosi 2019-06-12 23:01:16 +02:00
parent a2c9c72186
commit ed69452c45

View File

@ -25,7 +25,9 @@
**********************/ **********************/
static uint32_t get_glyph_dsc_id(const lv_font_t * font, uint32_t letter); static uint32_t get_glyph_dsc_id(const lv_font_t * font, uint32_t letter);
static int8_t get_kern_value(const lv_font_t * font, uint32_t gid_left, uint32_t gid_right); static int8_t get_kern_value(const lv_font_t * font, uint32_t gid_left, uint32_t gid_right);
//static int32_t lv_font_codeCompare(const void * pRef, const void * pElement); static int32_t unicode_list_compare(const void * ref, const void * element);
static int32_t kern_pair_8_compare(const void * ref, const void * element);
static int32_t kern_pair_16_compare(const void * ref, const void * element);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@ -126,21 +128,22 @@ static uint32_t get_glyph_dsc_id(const lv_font_t * font, uint32_t letter)
glyph_id = fdsc->cmaps[i].glyph_id_start + gid_ofs_8[rcp]; glyph_id = fdsc->cmaps[i].glyph_id_start + gid_ofs_8[rcp];
} }
else if(fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_SPARSE_TINY) { else if(fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_SPARSE_TINY) {
uint32_t u; uint8_t * p = lv_utils_bsearch(&rcp, fdsc->cmaps[i].unicode_list, fdsc->cmaps[i].list_length, sizeof(fdsc->cmaps[i].unicode_list[0]), unicode_list_compare);
for(u = 0; u < fdsc->cmaps[i].list_length; u++) {
if(fdsc->cmaps[i].unicode_list[u] == rcp) { if(p) {
glyph_id = fdsc->cmaps[i].glyph_id_start + u; uint32_t ofs = (uintptr_t)p - (uintptr_t) fdsc->cmaps[i].unicode_list;
ofs = ofs >> 1; /*The list stores `uint16_t` so the get the index divide by 2*/
glyph_id = fdsc->cmaps[i].glyph_id_start + ofs;
} }
} }
} else if(fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_SPARSE_FULL) {
else if(fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_SPARSE_TINY) { uint8_t * p = lv_utils_bsearch(&rcp, fdsc->cmaps[i].unicode_list, fdsc->cmaps[i].list_length, sizeof(fdsc->cmaps[i].unicode_list[0]), unicode_list_compare);
if(p) {
uint32_t ofs = (uintptr_t)p - (uintptr_t) fdsc->cmaps[i].unicode_list;
ofs = ofs >> 1; /*The list stores `uint16_t` so the get the index divide by 2*/
const uint8_t * gid_ofs_16 = fdsc->cmaps[i].glyph_id_ofs_list; const uint8_t * gid_ofs_16 = fdsc->cmaps[i].glyph_id_ofs_list;
uint32_t u; glyph_id = fdsc->cmaps[i].glyph_id_start + gid_ofs_16[ofs];
for(u = 0; u < 50 /*fdsc->cmaps[i].list_length*/; u++) {
if(fdsc->cmaps[i].unicode_list[u] == rcp) {
glyph_id = fdsc->cmaps[i].glyph_id_start + u;
}
glyph_id = fdsc->cmaps[i].glyph_id_start + gid_ofs_16[u];
} }
} }
@ -156,28 +159,37 @@ static int8_t get_kern_value(const lv_font_t * font, uint32_t gid_left, uint32_t
lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *) font->dsc; lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *) font->dsc;
int8_t value = 0; int8_t value = 0;
uint32_t k;
if(fdsc->kern_classes == 0) { if(fdsc->kern_classes == 0) {
/*Kern pairs*/ /*Kern pairs*/
const lv_font_fmt_txt_kern_pair_t * kdsc = fdsc->kern_dsc; const lv_font_fmt_txt_kern_pair_t * kdsc = fdsc->kern_dsc;
if(kdsc->glyph_ids_size == 0) { if(kdsc->glyph_ids_size == 0) {
/* Use binary search to find the kern value.
* The pairs are ordered left_id first, then right_id secondly. */
const uint8_t * g_ids = kdsc->glyph_ids; const uint8_t * g_ids = kdsc->glyph_ids;
for(k = 0; k < (uint32_t)kdsc->pair_cnt * 2; k += 2) { uint16_t g_id_both = (gid_right << 8) + gid_left; /*Create one number from the ids*/
if(g_ids[k] == gid_left && uint8_t * kid_p = lv_utils_bsearch(&g_id_both, g_ids, kdsc->pair_cnt, 2, kern_pair_8_compare);
g_ids[k+1] == gid_right) {
value = kdsc->values[k >> 1]; /*If the `g_id_both` were found get its index from the pointer*/
break; if(kid_p) {
} uintptr_t ofs = (uintptr_t)kid_p - (uintptr_t)g_ids;
ofs = ofs >> 1; /*ofs is for pair, divide by 2 to refer as a single value*/
value = kdsc->values[ofs];
} }
} else if(kdsc->glyph_ids_size == 1) { } else if(kdsc->glyph_ids_size == 1) {
/* Use binary search to find the kern value.
* The pairs are ordered left_id first, then right_id secondly. */
const uint16_t * g_ids = kdsc->glyph_ids; const uint16_t * g_ids = kdsc->glyph_ids;
for(k = 0; k < (uint32_t)kdsc->pair_cnt * 2; k += 2) { uint32_t g_id_both = (uint32_t)((uint32_t)gid_right << 8) + gid_left; /*Create one number from the ids*/
if(g_ids[k] == gid_left && uint8_t * kid_p = lv_utils_bsearch(&g_id_both, g_ids, kdsc->pair_cnt, 4, kern_pair_16_compare);
g_ids[k+1] == gid_right) {
value = kdsc->values[k >> 1]; /*If the `g_id_both` were found get its index from the pointer*/
break; if(kid_p) {
} uintptr_t ofs = (uintptr_t)kid_p - (uintptr_t)g_ids;
ofs = ofs >> 4; /*ofs is 4 byte pairs, divide by 4 to refer as a single value*/
value = kdsc->values[ofs];
} }
} else { } else {
/*Invalid value*/ /*Invalid value*/
} }
@ -197,6 +209,26 @@ static int8_t get_kern_value(const lv_font_t * font, uint32_t gid_left, uint32_t
return value; return value;
} }
static int32_t kern_pair_8_compare(const void * ref, const void * element)
{
const uint8_t * ref8_p = ref;
const uint8_t * element8_p = element;
/*If the MSB is different it will matter. If not return the diff. of the LSB*/
if(ref8_p[0] != element8_p[0]) return (int32_t)ref8_p[0] - element8_p[0];
else return (int32_t) ref8_p[1] - element8_p[1];
}
static int32_t kern_pair_16_compare(const void * ref, const void * element)
{
const uint16_t * ref16_p = ref;
const uint16_t * element16_p = element;
/*If the MSB is different it will matter. If not return the diff. of the LSB*/
if(ref16_p[0] != element16_p[0]) return (int32_t)ref16_p[0] - element16_p[0];
else return (int32_t) ref16_p[1] - element16_p[1];
}
/** Code Comparator. /** Code Comparator.
* *
@ -211,7 +243,7 @@ static int8_t get_kern_value(const lv_font_t * font, uint32_t gid_left, uint32_t
* @retval > 0 Reference is less than element. * @retval > 0 Reference is less than element.
* *
*/ */
//static int32_t lv_font_codeCompare(const void * pRef, const void * pElement) static int32_t unicode_list_compare(const void * ref, const void * element)
//{ {
// return (*(uint16_t *)pRef) - (*(uint16_t *)pElement); return (*(uint16_t *)ref) - (*(uint16_t *)element);
//} }