mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
font: add kerning support
This commit is contained in:
parent
ed1632f464
commit
864c970ba3
@ -244,19 +244,18 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
|
||||
return;
|
||||
}
|
||||
|
||||
const lv_font_glyph_dsc_t * g = lv_font_get_glyph_dsc(font_p, letter);
|
||||
if(g == NULL) return;
|
||||
lv_coord_t pos_x = pos_p->x + g->ofs_x;
|
||||
lv_coord_t pos_y = pos_p->y + g->ofs_y;
|
||||
|
||||
uint8_t bpp = lv_font_get_bpp(font_p, letter); /*Bit per pixel (1,2, 4 or 8)*/
|
||||
lv_font_glyph_dsc_t g;
|
||||
bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter);
|
||||
if(g_ret == false) return;
|
||||
|
||||
lv_coord_t pos_x = pos_p->x + g.ofs_x;
|
||||
lv_coord_t pos_y = pos_p->y + g.ofs_y;
|
||||
|
||||
const uint8_t * bpp_opa_table;
|
||||
uint8_t bitmask_init;
|
||||
uint8_t bitmask;
|
||||
|
||||
switch(bpp) {
|
||||
switch(g.bpp) {
|
||||
case 1:
|
||||
bpp_opa_table = bpp1_opa_table;
|
||||
bitmask_init = 0x80;
|
||||
@ -281,7 +280,7 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
|
||||
if(map_p == NULL) return;
|
||||
|
||||
/*If the letter is completely out of mask don't draw it */
|
||||
if(pos_x + g->box_w < mask_p->x1 || pos_x > mask_p->x2 || pos_y + g->box_h < mask_p->y1 ||
|
||||
if(pos_x + g.box_w < mask_p->x1 || pos_x > mask_p->x2 || pos_y + g.box_h < mask_p->y1 ||
|
||||
pos_y > mask_p->y2)
|
||||
return;
|
||||
|
||||
@ -293,16 +292,16 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
|
||||
lv_coord_t col, row;
|
||||
uint8_t col_bit;
|
||||
uint8_t col_byte_cnt;
|
||||
uint8_t width_byte_scr = g->box_w >> 3; /*Width in bytes (on the screen finally) (e.g. w = 11 -> 2 bytes wide)*/
|
||||
if(g->box_w & 0x7) width_byte_scr++;
|
||||
uint8_t width_byte_bpp = (g->box_w * bpp) >> 3; /*Letter width in byte. Real width in the font*/
|
||||
if((g->box_w * bpp) & 0x7) width_byte_bpp++;
|
||||
uint8_t width_byte_scr = g.box_w >> 3; /*Width in bytes (on the screen finally) (e.g. w = 11 -> 2 bytes wide)*/
|
||||
if(g.box_w & 0x7) width_byte_scr++;
|
||||
uint8_t width_byte_bpp = (g.box_w * g.bpp) >> 3; /*Letter width in byte. Real width in the font*/
|
||||
if((g.box_w * g.bpp) & 0x7) width_byte_bpp++;
|
||||
|
||||
/* Calculate the col/row start/end on the map*/
|
||||
lv_coord_t col_start = pos_x >= mask_p->x1 ? 0 : mask_p->x1 - pos_x;
|
||||
lv_coord_t col_end = pos_x + g->box_w <= mask_p->x2 ? g->box_w : mask_p->x2 - pos_x + 1;
|
||||
lv_coord_t col_end = pos_x + g.box_w <= mask_p->x2 ? g.box_w : mask_p->x2 - pos_x + 1;
|
||||
lv_coord_t row_start = pos_y >= mask_p->y1 ? 0 : mask_p->y1 - pos_y;
|
||||
lv_coord_t row_end = pos_y + g->box_h <= mask_p->y2 ? g->box_h : mask_p->y2 - pos_y + 1;
|
||||
lv_coord_t row_end = pos_y + g.box_h <= mask_p->y2 ? g.box_h : mask_p->y2 - pos_y + 1;
|
||||
|
||||
/*Set a pointer on VDB to the first pixel of the letter*/
|
||||
vdb_buf_tmp += ((pos_y - vdb->area.y1) * vdb_width) + pos_x - vdb->area.x1;
|
||||
@ -311,21 +310,21 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
|
||||
vdb_buf_tmp += (row_start * vdb_width) + col_start;
|
||||
|
||||
/*Move on the map too*/
|
||||
map_p += (row_start * width_byte_bpp) + ((col_start * bpp) >> 3);
|
||||
map_p += (row_start * width_byte_bpp) + ((col_start * g.bpp) >> 3);
|
||||
|
||||
uint8_t letter_px;
|
||||
lv_opa_t px_opa;
|
||||
for(row = row_start; row < row_end; row++) {
|
||||
col_byte_cnt = 0;
|
||||
col_bit = (col_start * bpp) % 8;
|
||||
col_bit = (col_start * g.bpp) % 8;
|
||||
bitmask = bitmask_init >> col_bit;
|
||||
for(col = col_start; col < col_end; col++) {
|
||||
letter_px = (*map_p & bitmask) >> (8 - col_bit - bpp);
|
||||
letter_px = (*map_p & bitmask) >> (8 - col_bit - g.bpp);
|
||||
if(letter_px != 0) {
|
||||
if(opa == LV_OPA_COVER) {
|
||||
px_opa = bpp == 8 ? letter_px : bpp_opa_table[letter_px];
|
||||
px_opa = g.bpp == 8 ? letter_px : bpp_opa_table[letter_px];
|
||||
} else {
|
||||
px_opa = bpp == 8 ? (uint16_t)((uint16_t)letter_px * opa) >> 8
|
||||
px_opa = g.bpp == 8 ? (uint16_t)((uint16_t)letter_px * opa) >> 8
|
||||
: (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8;
|
||||
}
|
||||
|
||||
@ -345,9 +344,9 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
|
||||
|
||||
vdb_buf_tmp++;
|
||||
|
||||
if(col_bit < 8 - bpp) {
|
||||
col_bit += bpp;
|
||||
bitmask = bitmask >> bpp;
|
||||
if(col_bit < 8 - g.bpp) {
|
||||
col_bit += g.bpp;
|
||||
bitmask = bitmask >> g.bpp;
|
||||
} else {
|
||||
col_bit = 0;
|
||||
col_byte_cnt++;
|
||||
|
@ -136,8 +136,10 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
cmd_state = CMD_STATE_WAIT;
|
||||
i = line_start;
|
||||
uint32_t letter;
|
||||
uint32_t letter_next;
|
||||
while(i < line_end) {
|
||||
letter = lv_txt_encoded_next(txt, &i);
|
||||
letter_next = lv_txt_encoded_next(&txt[i], NULL);
|
||||
|
||||
/*Handle the re-color command*/
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
@ -181,7 +183,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
|
||||
if(cmd_state == CMD_STATE_IN) color = recolor;
|
||||
|
||||
letter_w = lv_font_get_width_int(font, letter);
|
||||
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
|
||||
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
|
||||
int char_ind = lv_encoded_get_char_id(txt, i);
|
||||
|
@ -81,13 +81,19 @@ static const uint8_t lv_font_dejavu_20_glyph_bitmap[] = {
|
||||
/*4 rows*/
|
||||
};
|
||||
|
||||
|
||||
static const lv_font_kern_t kern_0031[] = {
|
||||
{.next_unicode = 0x0033, .space = 3 << 4},
|
||||
{.next_unicode = 0x0000} /*Trailing*/
|
||||
};
|
||||
|
||||
/*Store the glyph descriptions*/
|
||||
static const lv_font_glyph_dsc_t lv_font_dejavu_20_glyph_dsc[] = {
|
||||
{.adv_w = LV_FONT_SET_ADV_W(6, 0), .box_w = 6, .box_h = 0, .ofs_x = 0, .ofs_y = 0, .bitmap_index = 0}, /*Unicode: U+0020 ( )*/
|
||||
{.adv_w = LV_FONT_SET_ADV_W(8, 0), .box_w = 8, .box_h = 13,.ofs_x = 0, .ofs_y = 3, .bitmap_index = 0}, /*Unicode: U+0031 (1)*/
|
||||
{.adv_w = LV_FONT_SET_ADV_W(9, 0), .box_w = 9, .box_h = 13,.ofs_x = 0, .ofs_y = 3, .bitmap_index = 13}, /*Unicode: U+0033 (3)*/
|
||||
{.adv_w = LV_FONT_SET_ADV_W(12, 0), .box_w = 12,.box_h = 13,.ofs_x = 0, .ofs_y = 3, .bitmap_index = 39}, /*Unicode: U+0041 (A)*/
|
||||
{.adv_w = LV_FONT_SET_ADV_W(8, 0), .box_w = 8, .box_h = 10,.ofs_x = 0, .ofs_y = 6, .bitmap_index = 65}, /*Unicode: U+0061 (a)*/
|
||||
static const lv_font_glyph_dsc_built_in_t lv_font_dejavu_20_glyph_dsc[] = {
|
||||
{.adv_w = LV_FONT_SET_WIDTH(6, 0), .box_w = 6, .box_h = 0, .ofs_x = 0, .ofs_y = 0, .bitmap_index = 0, }, /*Unicode: U+0020 ( )*/
|
||||
{.adv_w = LV_FONT_SET_WIDTH(8, 0), .box_w = 8, .box_h = 13,.ofs_x = 0, .ofs_y = 3, .bitmap_index = 0, .kern_table = kern_0031}, /*Unicode: U+0031 (1)*/
|
||||
{.adv_w = LV_FONT_SET_WIDTH(9, 0), .box_w = 9, .box_h = 13,.ofs_x = 0, .ofs_y = 3, .bitmap_index = 13}, /*Unicode: U+0033 (3)*/
|
||||
{.adv_w = LV_FONT_SET_WIDTH(12, 0), .box_w = 12,.box_h = 13,.ofs_x = 0, .ofs_y = 3, .bitmap_index = 39}, /*Unicode: U+0041 (A)*/
|
||||
{.adv_w = LV_FONT_SET_WIDTH(8, 0), .box_w = 8, .box_h = 10,.ofs_x = 0, .ofs_y = 6, .bitmap_index = 65}, /*Unicode: U+0061 (a)*/
|
||||
};
|
||||
|
||||
static const uint16_t lv_font_dejavu_20_unicode_list[] = {
|
||||
@ -99,10 +105,11 @@ static const uint16_t lv_font_dejavu_20_unicode_list[] = {
|
||||
};
|
||||
|
||||
static lv_font_dsc_built_in_t lv_font_dejavu_20_dsc = {
|
||||
.glyph_cnt = 5, /*Number of glyphs in the font*/
|
||||
.glyph_cnt = 5, /*Number of glyphs in the font*/
|
||||
.glyph_bitmap = lv_font_dejavu_20_glyph_bitmap, /*Bitmap of glyphs*/
|
||||
.glyph_dsc = lv_font_dejavu_20_glyph_dsc, /*Description of glyphs*/
|
||||
.unicode_list = lv_font_dejavu_20_unicode_list, /*Every character in the font from 'unicode_first' to 'unicode_last'*/
|
||||
.unicode_list = lv_font_dejavu_20_unicode_list, /*Every character in the font from 'unicode_first' to 'unicode_last'*/
|
||||
.bpp = 1, /*Bit per pixel*/
|
||||
};
|
||||
|
||||
lv_font_t lv_font_dejavu_20 = {
|
||||
@ -111,7 +118,6 @@ lv_font_t lv_font_dejavu_20 = {
|
||||
.dsc = &lv_font_dejavu_20_dsc,
|
||||
.get_glyph_bitmap = lv_font_get_glyph_bitmap_plain, /*Function pointer to get glyph's bitmap*/
|
||||
.get_glyph_dsc = lv_font_get_glyph_dsc_plain, /*Function pointer to get glyph's width*/
|
||||
.bpp = 1, /*Bit per pixel*/
|
||||
.line_height = 20, /*Font height in pixels*/
|
||||
.next_page = NULL, /*Pointer to a font extension*/
|
||||
};
|
||||
|
@ -102,62 +102,60 @@ const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t lett
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the description of a glyph in a font.
|
||||
* @param font_p pointer to a font
|
||||
* @param letter an UNICODE character code
|
||||
* @return pointer to a glyph descriptor
|
||||
* Get the descriptor of a glyph
|
||||
* @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`
|
||||
*/
|
||||
const lv_font_glyph_dsc_t * lv_font_get_glyph_dsc(const lv_font_t * font_p, uint32_t letter)
|
||||
bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_out, uint32_t letter)
|
||||
{
|
||||
const lv_font_t * font_i = font_p;
|
||||
const lv_font_glyph_dsc_t * dsc;
|
||||
bool ret;
|
||||
while(font_i != NULL) {
|
||||
dsc = font_i->get_glyph_dsc(font_i, letter);
|
||||
if(dsc) {
|
||||
/*Glyph found*/
|
||||
return dsc;
|
||||
}
|
||||
ret = font_i->get_glyph_dsc(font_i, dsc_out, letter);
|
||||
if(ret) return ret;
|
||||
|
||||
font_i = font_i->next_page;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t lv_font_get_width_int(const lv_font_t * font, uint32_t letter)
|
||||
{
|
||||
const lv_font_glyph_dsc_t * dsc = lv_font_get_glyph_dsc(font, letter);
|
||||
return dsc ? LV_FONT_GET_ADV_W_INT(dsc->adv_w) : 0;
|
||||
}
|
||||
|
||||
uint8_t lv_font_get_width_fract(const lv_font_t * font, uint32_t letter)
|
||||
{
|
||||
const lv_font_glyph_dsc_t * dsc = lv_font_get_glyph_dsc(font, letter);
|
||||
return dsc ? LV_FONT_GET_ADV_W_FRACT(dsc->adv_w) : 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bit-per-pixel of font
|
||||
* @param font pointer to font
|
||||
* @param letter a letter from font (font extensions can have different bpp)
|
||||
* @return bpp of the font (or font extension)
|
||||
* Get the width of a glyph with kerning
|
||||
* @param font pointer to a font
|
||||
* @param letter an UNICODE letter
|
||||
* @param letter_next the next letter after `letter`. Used for kerning
|
||||
* @return the width of the glyph
|
||||
*/
|
||||
uint8_t lv_font_get_bpp(const lv_font_t * font, uint32_t letter)
|
||||
uint8_t lv_font_get_glyph_width(const lv_font_t * font, uint32_t letter, uint32_t letter_next)
|
||||
{
|
||||
const lv_font_t * font_i = font;
|
||||
while(font_i != NULL) {
|
||||
if(letter >= font_i->unicode_first && letter <= font_i->unicode_last) {
|
||||
return font_i->bpp;
|
||||
lv_font_glyph_dsc_t dsc;
|
||||
bool ret = lv_font_get_glyph_dsc(font, &dsc, letter);
|
||||
if(ret == false) return 0;
|
||||
|
||||
int32_t w = dsc.adv_w;
|
||||
|
||||
/*Apply kerning is required*/
|
||||
if(dsc.kern_table && letter_next != 0) {
|
||||
uint32_t i;
|
||||
for(i = 0; dsc.kern_table[i].next_unicode != 0; i++) {
|
||||
if((uint32_t)dsc.kern_table[i].next_unicode == letter_next) {
|
||||
w += dsc.kern_table[i].space;
|
||||
break;
|
||||
}
|
||||
}
|
||||
font_i = font_i->next_page;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if(w < 0) w = 0;
|
||||
|
||||
return w <= 0 ? 0 : LV_FONT_GET_WIDTH_INT(w);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic bitmap get function used in 'font->get_bitmap' when the font contains all characters in
|
||||
* the range
|
||||
* 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
|
||||
@ -190,23 +188,23 @@ const uint8_t * lv_font_get_glyph_bitmap_plain(const lv_font_t * font, uint32_t
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic glyph width get function used in 'font->get_width' when the font contains all characters
|
||||
* in the range
|
||||
* @param font pointer to font
|
||||
* @param unicode_letter an unicode letter which width should be get
|
||||
* @return width of the gylph or -1 if not found
|
||||
* 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`
|
||||
*/
|
||||
const lv_font_glyph_dsc_t * lv_font_get_glyph_dsc_plain(const lv_font_t * font, uint32_t unicode_letter)
|
||||
bool lv_font_get_glyph_dsc_plain(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter)
|
||||
{
|
||||
/*Check the range*/
|
||||
if(unicode_letter < font->unicode_first || unicode_letter > font->unicode_last) return NULL;
|
||||
|
||||
lv_font_dsc_built_in_t * font_dsc = (lv_font_dsc_built_in_t *) font->dsc;
|
||||
|
||||
int32_t index = -1;
|
||||
/*No Unicode list -> Continuous font*/
|
||||
if(font_dsc->unicode_list == NULL) {
|
||||
uint32_t index = (unicode_letter - font->unicode_first);
|
||||
return &font_dsc->glyph_dsc[index];
|
||||
index = (unicode_letter - font->unicode_first);
|
||||
}
|
||||
/*Has Unicode list -> Sparse font */
|
||||
else {
|
||||
@ -215,13 +213,22 @@ const lv_font_glyph_dsc_t * lv_font_get_glyph_dsc_plain(const lv_font_t * font,
|
||||
sizeof(font_dsc->unicode_list[0]), lv_font_codeCompare);
|
||||
|
||||
if(pUnicode != NULL) {
|
||||
uint32_t idx = (uint16_t)(pUnicode - font_dsc->unicode_list);
|
||||
return &font_dsc->glyph_dsc[idx];
|
||||
index = (uint16_t)(pUnicode - font_dsc->unicode_list);
|
||||
}
|
||||
}
|
||||
|
||||
/*If not returned earlier then the letter is not found in this font*/
|
||||
return NULL;
|
||||
if(index > 0) {
|
||||
dsc_out->adv_w = font_dsc->glyph_dsc[index].adv_w;
|
||||
dsc_out->box_h = font_dsc->glyph_dsc[index].box_h;
|
||||
dsc_out->box_w = font_dsc->glyph_dsc[index].box_w;
|
||||
dsc_out->ofs_x = font_dsc->glyph_dsc[index].ofs_x;
|
||||
dsc_out->ofs_y = font_dsc->glyph_dsc[index].ofs_y;
|
||||
dsc_out->kern_table = font_dsc->glyph_dsc[index].kern_table;
|
||||
dsc_out->bpp = font_dsc->bpp;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
|
@ -29,29 +29,27 @@ extern "C" {
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*Number of fractional digits in the advanced width (`adv_w`) field of `lv_font_glyph_dsc_t`*/
|
||||
#define LV_FONT_ADV_W_FRACT_DIGIT 4
|
||||
#define LV_FONT_WIDTH_FRACT_DIGIT 4
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
int32_t next_unicode :23;
|
||||
int32_t space :9; /*5 integer, 4 fractional*/
|
||||
}lv_font_kern_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bitmap_index : 20; /* Start index of the bitmap. A font can be max 1 MB. */
|
||||
uint32_t adv_w :12; /*The glyph needs this space. Draw the next glyph after this width. 8 bit integer, 4 bit fractional */
|
||||
uint8_t box_w; /*Width of the glyph's bounding box*/
|
||||
uint8_t box_h; /*Height of the glyph's bounding box*/
|
||||
uint8_t ofs_x; /*x offset of the bounding box*/
|
||||
int8_t ofs_y; /*y offset of the bounding box*/
|
||||
} lv_font_glyph_dsc_t;
|
||||
|
||||
typedef struct {
|
||||
const uint8_t * glyph_bitmap;
|
||||
const lv_font_glyph_dsc_t * glyph_dsc;
|
||||
const uint16_t * unicode_list;
|
||||
uint16_t glyph_cnt; /*Number of glyphs in the font. */
|
||||
}lv_font_dsc_built_in_t;
|
||||
|
||||
uint16_t adv_w; /*The glyph needs this space. Draw the next glyph after this width. 8 bit integer, 4 bit fractional */
|
||||
uint8_t box_w; /*Width of the glyph's bounding box*/
|
||||
uint8_t box_h; /*Height of the glyph's bounding box*/
|
||||
int8_t ofs_x; /*x offset of the bounding box*/
|
||||
int8_t ofs_y; /*y offset of the bounding box*/
|
||||
uint8_t bpp; /*Bit-per-pixel: 1, 2, 4, 8*/
|
||||
const lv_font_kern_t * kern_table;
|
||||
}lv_font_glyph_dsc_t;
|
||||
|
||||
typedef struct _lv_font_struct
|
||||
{
|
||||
@ -59,21 +57,41 @@ typedef struct _lv_font_struct
|
||||
uint32_t unicode_last;
|
||||
|
||||
/*Get a glyph's descriptor from a font*/
|
||||
const lv_font_glyph_dsc_t * (*get_glyph_dsc)(const struct _lv_font_struct *, uint32_t letter);
|
||||
bool (*get_glyph_dsc)(const struct _lv_font_struct *, lv_font_glyph_dsc_t *, uint32_t letter);
|
||||
|
||||
/*Get a glyph's bitmap from a font*/
|
||||
const uint8_t * (*get_glyph_bitmap)(const struct _lv_font_struct *, uint32_t);
|
||||
|
||||
/*Pointer to the font in a font pack (must have the same line height)*/
|
||||
struct _lv_font_struct * next_page;
|
||||
uint8_t size; /*The original size*/
|
||||
uint8_t size; /*The original size (height)*/
|
||||
uint8_t line_height; /*The real line height where any text fits*/
|
||||
uint8_t base_line; /*Base line measured from the top of the line*/
|
||||
uint8_t bpp; /*Bit per pixel: 1, 2, 4 or 8*/
|
||||
|
||||
uint8_t base_line; /*Base line measured from the top of the line_height*/
|
||||
void * dsc; /*Store implementation specific data here*/
|
||||
} lv_font_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bitmap_index : 20; /* Start index of the bitmap. A font can be max 1 MB. */
|
||||
uint32_t adv_w :12; /*The glyph needs this space. Draw the next glyph after this width. 8 bit integer, 4 bit fractional */
|
||||
|
||||
uint8_t box_w; /*Width of the glyph's bounding box*/
|
||||
uint8_t box_h; /*Height of the glyph's bounding box*/
|
||||
int8_t ofs_x; /*x offset of the bounding box*/
|
||||
int8_t ofs_y; /*y offset of the bounding box*/
|
||||
|
||||
const lv_font_kern_t * kern_table;
|
||||
}lv_font_glyph_dsc_built_in_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
const uint8_t * glyph_bitmap;
|
||||
const lv_font_glyph_dsc_built_in_t * glyph_dsc;
|
||||
const uint16_t * unicode_list;
|
||||
uint16_t glyph_cnt; /*Number of glyphs in the font. */
|
||||
uint8_t bpp; /*Bit per pixel: 1, 2, 4 or 8*/
|
||||
}lv_font_dsc_built_in_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
@ -97,15 +115,6 @@ void lv_font_add(lv_font_t * child, lv_font_t * parent);
|
||||
*/
|
||||
void lv_font_remove(lv_font_t * child, lv_font_t * parent);
|
||||
|
||||
/**
|
||||
* Tells if font which contains `letter` is monospace or not
|
||||
* @param font_p point to font
|
||||
* @param letter an UNICODE character code
|
||||
* @return true: the letter is monospace; false not monospace
|
||||
*/
|
||||
bool lv_font_is_monospace(const lv_font_t * font_p, uint32_t letter);
|
||||
|
||||
|
||||
/**
|
||||
* Return with the bitmap of a font.
|
||||
* @param font_p pointer to a font
|
||||
@ -115,21 +124,23 @@ bool lv_font_is_monospace(const lv_font_t * font_p, uint32_t letter);
|
||||
const uint8_t * lv_font_get_glyph_bitmap(const lv_font_t * font_p, uint32_t letter);
|
||||
|
||||
/**
|
||||
* Get the description of a glyph in a font.
|
||||
* @param font_p pointer to a font
|
||||
* @param letter an UNICODE character code
|
||||
* @return pointer to a glyph descriptor
|
||||
* Get the descriptor of a glyph
|
||||
* @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`
|
||||
*/
|
||||
const lv_font_glyph_dsc_t * lv_font_get_glyph_dsc(const lv_font_t * font_p, uint32_t letter);
|
||||
bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_out, uint32_t letter);
|
||||
|
||||
uint8_t lv_font_get_width_int(const lv_font_t * font, uint32_t letter);
|
||||
/**
|
||||
* Get the width of a letter in a font. If `monospace` is set then return with it.
|
||||
* @param font_p pointer to a font
|
||||
* @param letter an UNICODE character code
|
||||
* @return the width of a letter
|
||||
* Get the width of a glyph with kerning
|
||||
* @param font pointer to a font
|
||||
* @param letter an UNICODE letter
|
||||
* @param letter_next the next letter after `letter`. Used for kerning
|
||||
* @return the width of the glyph
|
||||
*/
|
||||
uint8_t lv_font_get_width_int(const lv_font_t * font_p, uint32_t letter);
|
||||
uint8_t lv_font_get_glyph_width(const lv_font_t * font, uint32_t letter, uint32_t letter_next);
|
||||
|
||||
/**
|
||||
* Get the line height of a font. All characters fit into this height
|
||||
@ -138,35 +149,26 @@ uint8_t lv_font_get_width_int(const lv_font_t * font_p, uint32_t letter);
|
||||
*/
|
||||
static inline uint8_t lv_font_get_line_height(const lv_font_t * font_p)
|
||||
{
|
||||
return font_p->line_height;//(uint8_t)((int16_t)font_p->ascent - font_p->descent);
|
||||
return font_p->line_height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bit-per-pixel of font
|
||||
* @param font pointer to font
|
||||
* @param letter a letter from font (font extensions can have different bpp)
|
||||
* @return bpp of the font (or font extension)
|
||||
*/
|
||||
uint8_t lv_font_get_bpp(const lv_font_t * font, uint32_t letter);
|
||||
|
||||
|
||||
/**
|
||||
* Generic bitmap get function used in 'font->get_bitmap' when the font contains all characters in
|
||||
* the range
|
||||
* 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
|
||||
*/
|
||||
const uint8_t * lv_font_get_glyph_bitmap_plain(const lv_font_t * font, uint32_t unicode_letter);
|
||||
const uint8_t * lv_font_get_glyph_bitmap_plain(const lv_font_t * font, uint32_t letter);
|
||||
|
||||
/**
|
||||
* Generic glyph width get function used in 'font->get_width' when the font contains all characters
|
||||
* in the range
|
||||
* @param font pointer to font
|
||||
* @param unicode_letter an unicode letter which width should be get
|
||||
* @return width of the gylph or -1 if not found
|
||||
* 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`
|
||||
*/
|
||||
const lv_font_glyph_dsc_t * lv_font_get_glyph_dsc_plain(const lv_font_t * font, uint32_t unicode_letter);
|
||||
bool lv_font_get_glyph_dsc_plain(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@ -174,9 +176,9 @@ const lv_font_glyph_dsc_t * lv_font_get_glyph_dsc_plain(const lv_font_t * font,
|
||||
|
||||
#define LV_FONT_DECLARE(font_name) extern lv_font_t font_name;
|
||||
|
||||
#define LV_FONT_SET_ADV_W(_integer, _fract) ((_integer << LV_FONT_ADV_W_FRACT_DIGIT) + _fract)
|
||||
#define LV_FONT_GET_ADV_W_INT(_adv_w) (_adv_w >> LV_FONT_ADV_W_FRACT_DIGIT)
|
||||
#define LV_FONT_GET_ADV_W_FRACT(_adv_w) (_adv_w & ((1 << LV_FONT_ADV_W_FRACT_DIGIT) -1))
|
||||
#define LV_FONT_SET_WIDTH(_integer, _fract) ((_integer << LV_FONT_WIDTH_FRACT_DIGIT) + _fract)
|
||||
#define LV_FONT_GET_WIDTH_INT(_w) (_w >> LV_FONT_WIDTH_FRACT_DIGIT)
|
||||
#define LV_FONT_GET_WIDTH_FRACT(_w) (_w & ((1 << LV_FONT_WIDTH_FRACT_DIGIT) -1))
|
||||
|
||||
|
||||
/**********************
|
||||
|
@ -173,11 +173,13 @@ uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord
|
||||
uint32_t n_char_since_last_break = 0; /* Used count word length of long words */
|
||||
uint32_t last_break = NO_BREAK_FOUND;
|
||||
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
||||
uint32_t letter = 0;
|
||||
uint32_t letter;
|
||||
uint32_t letter_next;
|
||||
|
||||
while(txt[i] != '\0') {
|
||||
lv_coord_t letter_width;
|
||||
letter = lv_txt_encoded_next(txt, &i);
|
||||
letter_next = lv_txt_encoded_next(&txt[i], NULL);
|
||||
|
||||
/*Handle the recolor command*/
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
@ -196,7 +198,7 @@ uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord
|
||||
|
||||
} else { /*Check the actual length*/
|
||||
n_char_since_last_break++;
|
||||
letter_width = lv_font_get_width_int(font, letter);
|
||||
letter_width = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
cur_w += letter_width;
|
||||
|
||||
/* Get the length of the current work and determine best place
|
||||
@ -210,12 +212,12 @@ uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord
|
||||
i = last_break;
|
||||
} else {
|
||||
uint32_t i_tmp = i;
|
||||
cur_w -=
|
||||
w_at_last_break +
|
||||
letter_space; /*ignore the first letter_space after the break char */
|
||||
/*ignore the first letter_space after the break char */
|
||||
cur_w -= w_at_last_break + letter_space;
|
||||
bool other = true;
|
||||
while(txt[i_tmp] != '\0') {
|
||||
letter = lv_txt_encoded_next(txt, &i_tmp);
|
||||
letter_next = lv_txt_encoded_next(&txt[i_tmp], NULL);
|
||||
|
||||
/*Handle the recolor command*/
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
@ -242,7 +244,7 @@ uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord
|
||||
break;
|
||||
}
|
||||
n_char_since_last_break++;
|
||||
lv_coord_t letter_width2 = lv_font_get_width_int(font, letter);
|
||||
lv_coord_t letter_width2 = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
cur_w += letter_width2;
|
||||
if(cur_w > max_width) {
|
||||
/* Current letter already exceeds, return previous */
|
||||
@ -323,17 +325,19 @@ lv_coord_t lv_txt_get_width(const char * txt, uint16_t length, const lv_font_t *
|
||||
lv_coord_t width = 0;
|
||||
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
||||
uint32_t letter;
|
||||
uint32_t letter_next;
|
||||
|
||||
if(length != 0) {
|
||||
while(i < length) {
|
||||
letter = lv_txt_encoded_next(txt, &i);
|
||||
letter_next = lv_txt_encoded_next(&txt[i], NULL);
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
if(lv_txt_is_cmd(&cmd_state, letter) != false) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
lv_coord_t char_width = lv_font_get_width_int(font, letter);
|
||||
lv_coord_t char_width = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
if(char_width > 0) {
|
||||
width += char_width;
|
||||
width += letter_space;
|
||||
|
@ -564,12 +564,20 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
||||
}
|
||||
|
||||
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
||||
|
||||
uint32_t i = line_start;
|
||||
uint32_t i_current = i;
|
||||
uint32_t letter;
|
||||
uint32_t letter_next;
|
||||
|
||||
while(i <= new_line_start - 1) {
|
||||
letter =
|
||||
lv_txt_encoded_next(txt, &i); /*Be careful 'i' already points to the next character*/
|
||||
/* Get the current letter.
|
||||
* Be careful 'i' already points to the next character*/
|
||||
letter = lv_txt_encoded_next(txt, &i);
|
||||
|
||||
/*Get the next letter too for kerning*/
|
||||
letter_next = lv_txt_encoded_next(&txt[i], NULL);
|
||||
|
||||
/*Handle the recolor command*/
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
if(lv_txt_is_cmd(&cmd_state, txt[i]) != false) {
|
||||
@ -577,7 +585,7 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
||||
}
|
||||
}
|
||||
|
||||
x += lv_font_get_width_int(font, letter);
|
||||
x += lv_font_get_glyph_width(font, letter, letter_next);
|
||||
if(pos->x < x) {
|
||||
i = i_current;
|
||||
break;
|
||||
@ -670,12 +678,20 @@ bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos)
|
||||
}
|
||||
|
||||
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
||||
|
||||
uint32_t i = line_start;
|
||||
uint32_t i_current = i;
|
||||
uint32_t letter = 0;
|
||||
uint32_t letter;
|
||||
uint32_t letter_next;
|
||||
|
||||
while(i <= new_line_start - 1) {
|
||||
letter =
|
||||
lv_txt_encoded_next(txt, &i); /*Be careful 'i' already points to the next character*/
|
||||
/* Get the current letter
|
||||
* Be careful 'i' already points to the next character */
|
||||
letter = lv_txt_encoded_next(txt, &i);
|
||||
|
||||
/*Get the next letter for kerning*/
|
||||
letter_next = lv_txt_encoded_next(&txt[i], NULL);
|
||||
|
||||
/*Handle the recolor command*/
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
if(lv_txt_is_cmd(&cmd_state, txt[i]) != false) {
|
||||
@ -683,7 +699,7 @@ bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos)
|
||||
}
|
||||
}
|
||||
last_x = x;
|
||||
x += lv_font_get_width_int(font, letter);
|
||||
x += lv_font_get_glyph_width(font, letter, letter_next);
|
||||
if(pos->x < x) {
|
||||
i = i_current;
|
||||
break;
|
||||
@ -692,7 +708,7 @@ bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos)
|
||||
i_current = i;
|
||||
}
|
||||
|
||||
int max_diff = lv_font_get_width_int(font, letter) + style->text.letter_space + 1;
|
||||
int32_t max_diff = lv_font_get_glyph_width(font, letter, letter_next) + style->text.letter_space + 1;
|
||||
return (pos->x >= (last_x - style->text.letter_space) && pos->x <= (last_x + max_diff));
|
||||
}
|
||||
|
||||
@ -833,10 +849,11 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_
|
||||
style->text.line_space, LV_COORD_MAX, flag);
|
||||
|
||||
lv_point_t ofs;
|
||||
|
||||
/*Draw the text again next to the original to make an circular effect */
|
||||
if(size.x > lv_obj_get_width(label)) {
|
||||
ofs.x = ext->offset.x + size.x +
|
||||
lv_font_get_width_int(style->text.font, ' ') * LV_LABEL_WAIT_CHAR_COUNT;
|
||||
lv_font_get_glyph_width(style->text.font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
|
||||
ofs.y = ext->offset.y;
|
||||
|
||||
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs,
|
||||
@ -950,8 +967,7 @@ static void lv_label_refr_text(lv_obj_t * label)
|
||||
anim.start = 0;
|
||||
anim.ready_cb = NULL;
|
||||
anim.path_cb = lv_anim_path_linear;
|
||||
anim.playback_pause =
|
||||
(((lv_font_get_width_int(style->text.font, ' ') + style->text.letter_space) * 1000) /
|
||||
anim.playback_pause = (((lv_font_get_glyph_width(style->text.font, ' ', ' ') + style->text.letter_space) * 1000) /
|
||||
ext->anim_speed) * LV_LABEL_WAIT_CHAR_COUNT;
|
||||
anim.repeat_pause = anim.playback_pause;
|
||||
anim.act_time = -anim.playback_pause;
|
||||
@ -990,8 +1006,7 @@ static void lv_label_refr_text(lv_obj_t * label)
|
||||
anim.repeat = 1;
|
||||
anim.playback = 0;
|
||||
anim.start = 0;
|
||||
anim.act_time =
|
||||
-(((lv_font_get_width_int(style->text.font, ' ') + style->text.letter_space) * 1000) /
|
||||
anim.act_time = -(((lv_font_get_glyph_width(style->text.font, ' ', ' ') + style->text.letter_space) * 1000) /
|
||||
ext->anim_speed) * LV_LABEL_WAIT_CHAR_COUNT;
|
||||
anim.ready_cb = NULL;
|
||||
anim.path_cb = lv_anim_path_linear;
|
||||
@ -1000,7 +1015,7 @@ static void lv_label_refr_text(lv_obj_t * label)
|
||||
|
||||
bool hor_anim = false;
|
||||
if(size.x > lv_obj_get_width(label)) {
|
||||
anim.end = -size.x - lv_font_get_width_int(font, ' ') * LV_LABEL_WAIT_CHAR_COUNT;
|
||||
anim.end = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
|
||||
anim.exec_cb = (lv_anim_exec_cb_t)lv_label_set_offset_x;
|
||||
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
|
||||
lv_anim_create(&anim);
|
||||
@ -1031,7 +1046,7 @@ static void lv_label_refr_text(lv_obj_t * label)
|
||||
} else {
|
||||
lv_point_t p;
|
||||
p.x = lv_obj_get_width(label) -
|
||||
(lv_font_get_width_int(style->text.font, '.') + style->text.letter_space) *
|
||||
(lv_font_get_glyph_width(style->text.font, '.', '.') + style->text.letter_space) *
|
||||
LV_LABEL_DOT_NUM; /*Shrink with dots*/
|
||||
p.y = lv_obj_get_height(label);
|
||||
p.y -= p.y % (lv_font_get_line_height(style->text.font) +
|
||||
|
@ -456,7 +456,7 @@ void lv_ta_set_text(lv_obj_t * ta, const char * txt)
|
||||
/*Don't let 'width == 0' because the cursor will not be visible*/
|
||||
if(lv_obj_get_width(ext->label) == 0) {
|
||||
const lv_style_t * style = lv_obj_get_style(ext->label);
|
||||
lv_obj_set_width(ext->label, lv_font_get_width_int(style->text.font, ' '));
|
||||
lv_obj_set_width(ext->label, lv_font_get_glyph_width(style->text.font, ' ', '\0'));
|
||||
}
|
||||
|
||||
if(ext->pwd_mode != 0) {
|
||||
@ -1522,12 +1522,14 @@ static void refr_cursor_area(lv_obj_t * ta)
|
||||
uint32_t letter = lv_txt_encoded_next(&txt[byte_pos], NULL);
|
||||
|
||||
lv_coord_t letter_h = lv_font_get_line_height(label_style->text.font);
|
||||
|
||||
/*Set letter_w (set not 0 on non printable but valid chars)*/
|
||||
lv_coord_t letter_w;
|
||||
if(letter == '\0' || letter == '\n' || letter == '\r') {
|
||||
letter_w = lv_font_get_width_int(label_style->text.font, ' ');
|
||||
letter_w = lv_font_get_glyph_width(label_style->text.font, ' ', '\0');
|
||||
} else {
|
||||
letter_w = lv_font_get_width_int(label_style->text.font, letter);
|
||||
/*`letter_next` parameter is '\0' to ignore kerning*/
|
||||
letter_w = lv_font_get_glyph_width(label_style->text.font, letter, '\0');
|
||||
}
|
||||
|
||||
lv_point_t letter_pos;
|
||||
@ -1545,9 +1547,9 @@ static void refr_cursor_area(lv_obj_t * ta)
|
||||
}
|
||||
|
||||
if(letter == '\0' || letter == '\n' || letter == '\r') {
|
||||
letter_w = lv_font_get_width_int(label_style->text.font, ' ');
|
||||
letter_w = lv_font_get_glyph_width(label_style->text.font, ' ', '\0');
|
||||
} else {
|
||||
letter_w = lv_font_get_width_int(label_style->text.font, letter);
|
||||
letter_w = lv_font_get_glyph_width(label_style->text.font, letter, '\0');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1031,7 +1031,7 @@ static void tabview_realign(lv_obj_t * tabview)
|
||||
break;
|
||||
case LV_TABVIEW_BTNS_POS_LEFT:
|
||||
case LV_TABVIEW_BTNS_POS_RIGHT:
|
||||
btns_size = lv_font_get_width_int(style_btn_rel->text.font, 0x0041) + // 'A'
|
||||
btns_size = lv_font_get_glyph_width(style_btn_rel->text.font, 'A', '\0') +
|
||||
style_btn_rel->body.padding.left +
|
||||
style_btn_rel->body.padding.right +
|
||||
style_btn_bg->body.padding.left + style_btn_bg->body.padding.right;
|
||||
|
Loading…
x
Reference in New Issue
Block a user