2019-05-20 06:40:00 +02:00
|
|
|
/**
|
|
|
|
* @file lv_font.c
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*********************
|
|
|
|
* INCLUDES
|
|
|
|
*********************/
|
|
|
|
|
2019-06-06 05:55:17 +02:00
|
|
|
#include "lv_font.h"
|
2019-05-29 06:40:19 +02:00
|
|
|
#include "lv_font_fmt_txt.h"
|
2019-06-06 05:55:17 +02:00
|
|
|
#include "../lv_misc/lv_log.h"
|
|
|
|
#include "../lv_misc/lv_utils.h"
|
2019-05-20 06:40:00 +02:00
|
|
|
|
|
|
|
/*********************
|
|
|
|
* DEFINES
|
|
|
|
*********************/
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
* TYPEDEFS
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
* STATIC PROTOTYPES
|
|
|
|
**********************/
|
2019-06-01 21:46:05 +02:00
|
|
|
static uint32_t get_glyph_dsc_id(const lv_font_t * font, uint32_t letter);
|
2019-06-02 11:56:57 +02:00
|
|
|
static int8_t get_kern_value(const lv_font_t * font, uint32_t gid_left, uint32_t gid_right);
|
2019-06-06 05:55:17 +02:00
|
|
|
//static int32_t lv_font_codeCompare(const void * pRef, const void * pElement);
|
2019-05-20 06:40:00 +02:00
|
|
|
|
|
|
|
/**********************
|
|
|
|
* STATIC VARIABLES
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
* GLOBAL PROTOTYPES
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
* MACROS
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
* GLOBAL FUNCTIONS
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Used as `get_glyph_bitmap` callback in LittelvGL's native font format if the font is uncompressed.
|
|
|
|
* @param font pointer to font
|
|
|
|
* @param unicode_letter an unicode letter which bitmap should be get
|
|
|
|
* @return pointer to the bitmap or NULL if not found
|
|
|
|
*/
|
2019-05-26 19:31:01 +02:00
|
|
|
const uint8_t * lv_font_get_bitmap_fmt_txt(const lv_font_t * font, uint32_t unicode_letter)
|
2019-05-20 06:40:00 +02:00
|
|
|
{
|
2019-05-29 06:40:19 +02:00
|
|
|
lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *) font->dsc;
|
2019-06-01 21:46:05 +02:00
|
|
|
uint32_t gid = get_glyph_dsc_id(font, unicode_letter);
|
|
|
|
if(!gid) return false;
|
|
|
|
|
|
|
|
const lv_font_fmt_txt_glyph_dsc_t * gdsc = &fdsc->glyph_dsc[gid];
|
2019-05-20 06:40:00 +02:00
|
|
|
|
2019-05-29 06:40:19 +02:00
|
|
|
if(gdsc) return &fdsc->glyph_bitmap[gdsc->bitmap_index];
|
2019-05-20 06:40:00 +02:00
|
|
|
|
|
|
|
/*If not returned earlier then the letter is not found in this font*/
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Used as `get_glyph_dsc` callback in LittelvGL's native font format if the font is uncompressed.
|
|
|
|
* @param font_p pointer to font
|
|
|
|
* @param dsc_out store the result descriptor here
|
|
|
|
* @param letter an UNICODE letter code
|
|
|
|
* @return true: descriptor is successfully loaded into `dsc_out`.
|
|
|
|
* false: the letter was not found, no data is loaded to `dsc_out`
|
|
|
|
*/
|
2019-05-29 06:40:19 +02:00
|
|
|
bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next)
|
2019-05-20 06:40:00 +02:00
|
|
|
{
|
2019-05-29 06:40:19 +02:00
|
|
|
lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *) font->dsc;
|
2019-06-01 21:46:05 +02:00
|
|
|
uint32_t gid = get_glyph_dsc_id(font, unicode_letter);
|
|
|
|
if(!gid) return false;
|
|
|
|
|
2019-06-02 11:56:57 +02:00
|
|
|
int8_t kvalue = 0;
|
2019-06-01 21:46:05 +02:00
|
|
|
if(fdsc->kern_dsc) {
|
|
|
|
uint32_t gid_next = get_glyph_dsc_id(font, unicode_letter_next);
|
|
|
|
if(gid_next) {
|
|
|
|
kvalue = get_kern_value(font, gid, gid_next);
|
2019-05-20 06:40:00 +02:00
|
|
|
}
|
2019-06-01 21:46:05 +02:00
|
|
|
}
|
2019-05-20 06:40:00 +02:00
|
|
|
|
2019-06-01 21:46:05 +02:00
|
|
|
/*Put together a glyph dsc*/
|
|
|
|
const lv_font_fmt_txt_glyph_dsc_t * gdsc = &fdsc->glyph_dsc[gid];
|
2019-05-29 06:40:19 +02:00
|
|
|
|
2019-06-05 15:16:43 +02:00
|
|
|
uint32_t adv_w = gdsc->adv_w + ((int32_t)((int32_t)kvalue * fdsc->kern_scale) >> 4);
|
|
|
|
adv_w = (adv_w + (1 << 3)) >> 4;
|
2019-05-29 06:40:19 +02:00
|
|
|
|
2019-06-05 15:16:43 +02:00
|
|
|
dsc_out->adv_w = adv_w;
|
2019-06-01 21:46:05 +02:00
|
|
|
dsc_out->box_h = gdsc->box_h;
|
|
|
|
dsc_out->box_w = gdsc->box_w;
|
|
|
|
dsc_out->ofs_x = gdsc->ofs_x;
|
|
|
|
dsc_out->ofs_y = gdsc->ofs_y;
|
|
|
|
dsc_out->bpp = fdsc->bpp;
|
2019-05-29 06:40:19 +02:00
|
|
|
|
2019-06-01 21:46:05 +02:00
|
|
|
return true;
|
2019-05-20 06:40:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
* STATIC FUNCTIONS
|
|
|
|
**********************/
|
|
|
|
|
2019-06-01 21:46:05 +02:00
|
|
|
static uint32_t get_glyph_dsc_id(const lv_font_t * font, uint32_t letter)
|
2019-05-29 06:40:19 +02:00
|
|
|
{
|
2019-06-01 21:46:05 +02:00
|
|
|
if(letter == '\0') return 0;
|
|
|
|
|
2019-05-29 06:40:19 +02:00
|
|
|
lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *) font->dsc;
|
|
|
|
|
|
|
|
uint16_t i;
|
|
|
|
for(i = 0; i < fdsc->cmap_num; i++) {
|
|
|
|
|
|
|
|
/*Relative code point*/
|
|
|
|
uint32_t rcp = letter - fdsc->cmaps[i].range_start;
|
2019-06-01 21:46:05 +02:00
|
|
|
if(rcp > fdsc->cmaps[i].range_length) continue;
|
2019-05-29 06:40:19 +02:00
|
|
|
uint32_t glyph_id = 0;
|
|
|
|
if(fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY) {
|
|
|
|
glyph_id = fdsc->cmaps[i].glyph_id_start + rcp;
|
|
|
|
}
|
2019-06-01 21:46:05 +02:00
|
|
|
else if(fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_FORMAT0_FULL) {
|
2019-06-02 11:56:57 +02:00
|
|
|
const uint8_t * gid_ofs_8 = fdsc->cmaps[i].glyph_id_ofs_list;
|
|
|
|
glyph_id = fdsc->cmaps[i].glyph_id_start + gid_ofs_8[rcp];
|
2019-06-01 21:46:05 +02:00
|
|
|
}
|
2019-06-02 11:56:57 +02:00
|
|
|
else if(fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_SPARSE_TINY) {
|
|
|
|
uint32_t u;
|
2019-06-03 00:55:59 +02:00
|
|
|
for(u = 0; u < fdsc->cmaps[i].list_length; u++) {
|
2019-06-02 11:56:57 +02:00
|
|
|
if(fdsc->cmaps[i].unicode_list[u] == rcp) {
|
|
|
|
glyph_id = fdsc->cmaps[i].glyph_id_start + u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(fdsc->cmaps[i].type == LV_FONT_FMT_TXT_CMAP_SPARSE_TINY) {
|
2019-06-01 21:46:05 +02:00
|
|
|
const uint8_t * gid_ofs_16 = fdsc->cmaps[i].glyph_id_ofs_list;
|
2019-06-02 11:56:57 +02:00
|
|
|
uint32_t u;
|
|
|
|
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];
|
|
|
|
}
|
2019-06-01 21:46:05 +02:00
|
|
|
}
|
2019-05-29 06:40:19 +02:00
|
|
|
|
2019-06-01 21:46:05 +02:00
|
|
|
return glyph_id;
|
2019-05-29 06:40:19 +02:00
|
|
|
}
|
|
|
|
|
2019-06-01 21:46:05 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-06-02 11:56:57 +02:00
|
|
|
static int8_t get_kern_value(const lv_font_t * font, uint32_t gid_left, uint32_t gid_right)
|
2019-06-01 21:46:05 +02:00
|
|
|
{
|
|
|
|
lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *) font->dsc;
|
2019-05-29 06:40:19 +02:00
|
|
|
|
2019-06-02 11:56:57 +02:00
|
|
|
int8_t value = 0;
|
|
|
|
uint32_t k;
|
|
|
|
if(fdsc->kern_classes == 0) {
|
|
|
|
/*Kern pairs*/
|
|
|
|
const lv_font_fmt_txt_kern_pair_t * kdsc = fdsc->kern_dsc;
|
2019-06-05 12:28:31 +02:00
|
|
|
if(kdsc->glyph_ids_size == 0) {
|
2019-06-02 11:56:57 +02:00
|
|
|
const uint8_t * g_ids = kdsc->glyph_ids;
|
|
|
|
for(k = 0; k < (uint32_t)kdsc->pair_cnt * 2; k += 2) {
|
|
|
|
if(g_ids[k] == gid_left &&
|
|
|
|
g_ids[k+1] == gid_right) {
|
|
|
|
value = kdsc->values[k >> 1];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-06-05 12:28:31 +02:00
|
|
|
} else if(kdsc->glyph_ids_size == 1) {
|
2019-06-02 11:56:57 +02:00
|
|
|
const uint16_t * g_ids = kdsc->glyph_ids;
|
|
|
|
for(k = 0; k < (uint32_t)kdsc->pair_cnt * 2; k += 2) {
|
|
|
|
if(g_ids[k] == gid_left &&
|
|
|
|
g_ids[k+1] == gid_right) {
|
|
|
|
value = kdsc->values[k >> 1];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-06-05 12:28:31 +02:00
|
|
|
} else {
|
|
|
|
/*Invalid value*/
|
2019-06-02 11:56:57 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/*Kern classes*/
|
|
|
|
const lv_font_fmt_txt_kern_classes_t * kdsc = fdsc->kern_dsc;
|
|
|
|
uint8_t left_class = kdsc->left_class_mapping[gid_left];
|
|
|
|
uint8_t right_class = kdsc->left_class_mapping[gid_right];
|
|
|
|
|
|
|
|
/* If class = 0, kerning not exist for that glyph
|
|
|
|
* else got the value form `class_pair_values` 2D array*/
|
|
|
|
if(left_class > 0 && right_class > 0) {
|
|
|
|
value = kdsc->class_pair_values[(left_class-1)* kdsc->right_class_cnt + (right_class-1)];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return value;
|
2019-05-29 06:40:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-20 06:40:00 +02:00
|
|
|
/** Code Comparator.
|
|
|
|
*
|
|
|
|
* Compares the value of both input arguments.
|
|
|
|
*
|
|
|
|
* @param[in] pRef Pointer to the reference.
|
|
|
|
* @param[in] pElement Pointer to the element to compare.
|
|
|
|
*
|
|
|
|
* @return Result of comparison.
|
|
|
|
* @retval < 0 Reference is greater than element.
|
|
|
|
* @retval = 0 Reference is equal to element.
|
|
|
|
* @retval > 0 Reference is less than element.
|
|
|
|
*
|
|
|
|
*/
|
2019-06-06 05:55:17 +02:00
|
|
|
//static int32_t lv_font_codeCompare(const void * pRef, const void * pElement)
|
|
|
|
//{
|
|
|
|
// return (*(uint16_t *)pRef) - (*(uint16_t *)pElement);
|
|
|
|
//}
|