Merge branch 'feat-subpixel' into dev-6.1

This commit is contained in:
Gabor Kiss-Vamosi
2019-10-18 14:58:04 +02:00
7 changed files with 3112 additions and 2040 deletions

View File

@@ -361,6 +361,12 @@ typedef void * lv_font_user_data_t;
# define lv_vsnprintf vsnprintf # define lv_vsnprintf vsnprintf
#endif /*LV_SPRINTF_CUSTOM*/ #endif /*LV_SPRINTF_CUSTOM*/
/* Set the pixel order of the display.
* Important only if "subpx fonts" are used.
* With "normal" font it doesn't matter.
*/
#define LV_SUBPX_BGR 0
/*=================== /*===================
* LV_OBJ SETTINGS * LV_OBJ SETTINGS
*==================*/ *==================*/

View File

@@ -504,6 +504,14 @@
#endif #endif
#endif /*LV_SPRINTF_CUSTOM*/ #endif /*LV_SPRINTF_CUSTOM*/
/* Set the pixel order of the display.
* Important only if "subpx fonts" are used.
* With "normal" font it doesn't matter.
*/
#ifndef LV_SUBPX_BGR
#define LV_SUBPX_BGR 0
#endif
/*=================== /*===================
* LV_OBJ SETTINGS * LV_OBJ SETTINGS
*==================*/ *==================*/

View File

@@ -252,6 +252,7 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0'); bool g_ret = lv_font_get_glyph_dsc(font_p, &g, letter, '\0');
if(g_ret == false) return; if(g_ret == false) return;
lv_coord_t pos_x = pos_p->x + g.ofs_x; lv_coord_t pos_x = pos_p->x + g.ofs_x;
lv_coord_t pos_y = pos_p->y + (font_p->line_height - font_p->base_line) - g.box_h - g.ofs_y; lv_coord_t pos_y = pos_p->y + (font_p->line_height - font_p->base_line) - g.box_h - g.ofs_y;
@@ -300,17 +301,32 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
if(g.box_w & 0x7) width_byte_scr++; if(g.box_w & 0x7) width_byte_scr++;
uint16_t width_bit = g.box_w * g.bpp; /*Letter width in bits*/ uint16_t width_bit = g.box_w * g.bpp; /*Letter width in bits*/
bool subpx = font_p->subpx == LV_FONT_SUBPX_NONE ? false : true;
/* Calculate the col/row start/end on the map*/ /* 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_start;
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;
lv_coord_t row_start = pos_y >= mask_p->y1 ? 0 : mask_p->y1 - pos_y; lv_coord_t row_start;
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;
if(subpx == false) {
col_start = pos_x >= mask_p->x1 ? 0 : mask_p->x1 - pos_x;
col_end = pos_x + g.box_w <= mask_p->x2 ? g.box_w : mask_p->x2 - pos_x + 1;
row_start = pos_y >= mask_p->y1 ? 0 : mask_p->y1 - pos_y;
row_end = pos_y + g.box_h <= mask_p->y2 ? g.box_h : mask_p->y2 - pos_y + 1;
} else {
col_start = pos_x >= mask_p->x1 ? 0 : (mask_p->x1 - pos_x) * 3;
col_end = pos_x + g.box_w / 3 <= mask_p->x2 ? g.box_w : (mask_p->x2 - pos_x + 1) * 3;
row_start = pos_y >= mask_p->y1 ? 0 : mask_p->y1 - pos_y;
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*/ /*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; vdb_buf_tmp += ((pos_y - vdb->area.y1) * vdb_width) + pos_x - vdb->area.x1;
/*If the letter is partially out of mask the move there on VDB*/ /*If the letter is partially out of mask the move there on VDB*/
vdb_buf_tmp += (row_start * vdb_width) + col_start; if(subpx) vdb_buf_tmp += (row_start * vdb_width) + col_start / 3;
else vdb_buf_tmp += (row_start * vdb_width) + col_start;
/*Move on the map too*/ /*Move on the map too*/
uint32_t bit_ofs = (row_start * width_bit) + (col_start * g.bpp); uint32_t bit_ofs = (row_start * width_bit) + (col_start * g.bpp);
@@ -326,10 +342,17 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
scr_transp = disp->driver.screen_transp; scr_transp = disp->driver.screen_transp;
#endif #endif
uint8_t font_rgb[3];
uint8_t txt_rgb[3] = {color.ch.red, color.ch.green, color.ch.blue};
for(row = row_start; row < row_end; row++) { for(row = row_start; row < row_end; row++) {
bitmask = bitmask_init >> col_bit; bitmask = bitmask_init >> col_bit;
uint8_t sub_px_cnt = 0;
for(col = col_start; col < col_end; col++) { for(col = col_start; col < col_end; col++) {
letter_px = (*map_p & bitmask) >> (8 - col_bit - g.bpp); letter_px = (*map_p & bitmask) >> (8 - col_bit - g.bpp);
/*subpx == 0*/
if(subpx == false) {
if(letter_px != 0) { if(letter_px != 0) {
if(opa == LV_OPA_COVER) { if(opa == LV_OPA_COVER) {
px_opa = g.bpp == 8 ? letter_px : bpp_opa_table[letter_px]; px_opa = g.bpp == 8 ? letter_px : bpp_opa_table[letter_px];
@@ -342,9 +365,9 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
disp->driver.set_px_cb(&disp->driver, (uint8_t *)vdb->buf_act, vdb_width, disp->driver.set_px_cb(&disp->driver, (uint8_t *)vdb->buf_act, vdb_width,
(col + pos_x) - vdb->area.x1, (row + pos_y) - vdb->area.y1, color, px_opa); (col + pos_x) - vdb->area.x1, (row + pos_y) - vdb->area.y1, color, px_opa);
} else if(vdb_buf_tmp->full != color.full) { } else if(vdb_buf_tmp->full != color.full) {
if(px_opa > LV_OPA_MAX) if(px_opa > LV_OPA_MAX) {
*vdb_buf_tmp = color; *vdb_buf_tmp = color;
else if(px_opa > LV_OPA_MIN) { } else if(px_opa > LV_OPA_MIN) {
if(scr_transp == false) { if(scr_transp == false) {
*vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, px_opa); *vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, px_opa);
} else { } else {
@@ -355,8 +378,49 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
} }
} }
} }
vdb_buf_tmp++; vdb_buf_tmp++;
}
/*Handle subpx drawing*/
else {
if(letter_px != 0) {
if(opa == LV_OPA_COVER) {
px_opa = g.bpp == 8 ? letter_px : bpp_opa_table[letter_px];
} else {
px_opa = g.bpp == 8 ? (uint16_t)((uint16_t)letter_px * opa) >> 8
: (uint16_t)((uint16_t)bpp_opa_table[letter_px] * opa) >> 8;
}
font_rgb[sub_px_cnt] = px_opa;
} else {
font_rgb[sub_px_cnt] = 0;
}
sub_px_cnt ++;
if(sub_px_cnt == 3) {
lv_color_t res_color;
uint8_t bg_rgb[3] = {vdb_buf_tmp->ch.red, vdb_buf_tmp->ch.green, vdb_buf_tmp->ch.blue};
#if LV_SUBPX_BGR
res_color.ch.blue = (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8;
res_color.ch.green = (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8;
res_color.ch.red = (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8;
#else
res_color.ch.red = (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8;
res_color.ch.green = (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8;
res_color.ch.blue = (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8;
#endif
if(scr_transp == false) {
vdb_buf_tmp->full = res_color.full;
#if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP
} else {
*vdb_buf_tmp = color_mix_2_alpha(*vdb_buf_tmp, (*vdb_buf_tmp).ch.alpha, color, px_opa);
#endif
}
sub_px_cnt = 0;
vdb_buf_tmp++;
}
}
if(col_bit < 8 - g.bpp) { if(col_bit < 8 - g.bpp) {
col_bit += g.bpp; col_bit += g.bpp;
@@ -367,11 +431,15 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv
map_p++; map_p++;
} }
} }
col_bit += ((g.box_w - col_end) + col_start) * g.bpp; col_bit += ((g.box_w - col_end) + col_start) * g.bpp;
map_p += (col_bit >> 3); map_p += (col_bit >> 3);
col_bit = col_bit & 0x7; col_bit = col_bit & 0x7;
vdb_buf_tmp += vdb_width - (col_end - col_start); /*Next row in VDB*/
/*Next row in VDB*/
if(subpx) vdb_buf_tmp += vdb_width - (col_end - col_start) / 3;
else vdb_buf_tmp += vdb_width - (col_end - col_start);
} }
} }

View File

@@ -53,7 +53,18 @@ typedef struct
uint8_t bpp; /**< Bit-per-pixel: 1, 2, 4, 8*/ uint8_t bpp; /**< Bit-per-pixel: 1, 2, 4, 8*/
}lv_font_glyph_dsc_t; }lv_font_glyph_dsc_t;
/*Describe the properties of a font*/
/** The bitmaps might be upscaled by 3 to achieve subpixel rendering. */
enum {
LV_FONT_SUBPX_NONE,
LV_FONT_SUBPX_HOR,
LV_FONT_SUBPX_VER,
LV_FONT_SUBPX_BOTH,
};
typedef uint8_t lv_font_subpx_t;
/** Describe the properties of a font*/
typedef struct _lv_font_struct typedef struct _lv_font_struct
{ {
/** Get a glyph's descriptor from a font*/ /** Get a glyph's descriptor from a font*/
@@ -65,10 +76,13 @@ typedef struct _lv_font_struct
/*Pointer to the font in a font pack (must have the same line height)*/ /*Pointer to the font in a font pack (must have the same line height)*/
uint8_t line_height; /**< The real line height where any text fits*/ 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_height*/ uint8_t base_line; /**< Base line measured from the top of the line_height*/
uint8_t subpx :2; /**< An element of `lv_font_subpx_t`*/
void * dsc; /**< Store implementation specific data here*/ void * dsc; /**< Store implementation specific data here*/
#if LV_USE_USER_DATA #if LV_USE_USER_DATA
lv_font_user_data_t user_data; /**< Custom user data for font. */ lv_font_user_data_t user_data; /**< Custom user data for font. */
#endif #endif
} lv_font_t; } lv_font_t;
/********************** /**********************

View File

@@ -140,7 +140,9 @@ bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t * font, lv_font_glyph_dsc_t *
/*Put together a glyph dsc*/ /*Put together a glyph dsc*/
const lv_font_fmt_txt_glyph_dsc_t * gdsc = &fdsc->glyph_dsc[gid]; const lv_font_fmt_txt_glyph_dsc_t * gdsc = &fdsc->glyph_dsc[gid];
uint32_t adv_w = gdsc->adv_w + ((int32_t)((int32_t)kvalue * fdsc->kern_scale) >> 4); int32_t kv = ((int32_t)((int32_t)kvalue * fdsc->kern_scale) >> 4);
uint32_t adv_w = gdsc->adv_w + kv;
adv_w = (adv_w + (1 << 3)) >> 4; adv_w = (adv_w + (1 << 3)) >> 4;
dsc_out->adv_w = adv_w; dsc_out->adv_w = adv_w;

View File

@@ -191,6 +191,7 @@ typedef struct {
* from `lv_font_fmt_txt_bitmap_format_t` * from `lv_font_fmt_txt_bitmap_format_t`
*/ */
uint16_t bitmap_format :2; uint16_t bitmap_format :2;
uint16_t subpx :1;
/*Cache the last letter and is glyph id*/ /*Cache the last letter and is glyph id*/
uint32_t last_letter; uint32_t last_letter;

File diff suppressed because it is too large Load Diff