diff --git a/lv_conf_template.h b/lv_conf_template.h index a2a19a2b8..aab872fc4 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -361,6 +361,12 @@ typedef void * lv_font_user_data_t; # define lv_vsnprintf vsnprintf #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 *==================*/ diff --git a/src/lv_conf_checker.h b/src/lv_conf_checker.h index 655732447..a855707b4 100644 --- a/src/lv_conf_checker.h +++ b/src/lv_conf_checker.h @@ -504,6 +504,14 @@ #endif #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 *==================*/ diff --git a/src/lv_draw/lv_draw_arc.c b/src/lv_draw/lv_draw_arc.c index ca3c7ddbc..ed4192dfe 100644 --- a/src/lv_draw/lv_draw_arc.c +++ b/src/lv_draw/lv_draw_arc.c @@ -56,6 +56,11 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons lv_coord_t thickness = style->line.width; if(thickness > radius) thickness = radius; +#if LV_ANTIALIAS + thickness--; + radius--; +#endif + lv_coord_t r_out = radius; lv_coord_t r_in = r_out - thickness; int16_t deg_base; @@ -72,17 +77,26 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons else deg_test = deg_test_inv; + int middle_r_out = r_out; +#if !LV_ANTIALIAS + thickness--; + middle_r_out = r_out - 1; +#endif if(deg_test(270, start_angle, end_angle)) - hor_line(center_x - r_out + 1, center_y, mask, thickness - 1, color, opa); /*Left Middle*/ + hor_line(center_x - middle_r_out, center_y, mask, thickness, color, opa); /*Left Middle*/ if(deg_test(90, start_angle, end_angle)) - hor_line(center_x + r_in, center_y, mask, thickness - 1, color, opa); /*Right Middle*/ + hor_line(center_x + r_in, center_y, mask, thickness, color, opa); /*Right Middle*/ if(deg_test(180, start_angle, end_angle)) - ver_line(center_x, center_y - r_out + 1, mask, thickness - 1, color, opa); /*Top Middle*/ + ver_line(center_x, center_y - middle_r_out, mask, thickness, color, opa); /*Top Middle*/ if(deg_test(0, start_angle, end_angle)) - ver_line(center_x, center_y + r_in, mask, thickness - 1, color, opa); /*Bottom middle*/ + ver_line(center_x, center_y + r_in, mask, thickness, color, opa); /*Bottom middle*/ uint32_t r_out_sqr = r_out * r_out; uint32_t r_in_sqr = r_in * r_in; +#if LV_ANTIALIAS + uint32_t r_out_aa_sqr = (r_out + 1) * (r_out + 1); + uint32_t r_in_aa_sqr = (r_in - 1) * (r_in - 1); +#endif int16_t xi; int16_t yi; for(yi = -r_out; yi < 0; yi++) { @@ -94,13 +108,56 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons x_end[1] = LV_COORD_MIN; x_end[2] = LV_COORD_MIN; x_end[3] = LV_COORD_MIN; + int xe = 0; for(xi = -r_out; xi < 0; xi++) { uint32_t r_act_sqr = xi * xi + yi * yi; +#if LV_ANTIALIAS + if(r_act_sqr > r_out_aa_sqr) { + continue; + } +#else if(r_act_sqr > r_out_sqr) continue; +#endif deg_base = lv_atan2(xi, yi) - 180; +#if LV_ANTIALIAS + int opa = -1; + if(r_act_sqr > r_out_sqr) { + opa = LV_OPA_100 * (r_out + 1) - lv_sqrt(LV_OPA_100 * LV_OPA_100 * r_act_sqr); + if(opa < LV_OPA_0) + opa = LV_OPA_0; + else if(opa > LV_OPA_100) + opa = LV_OPA_100; + } else if(r_act_sqr < r_in_sqr) { + if(xe == 0) xe = xi; + opa = lv_sqrt(LV_OPA_100 * LV_OPA_100 * r_act_sqr) - LV_OPA_100 * (r_in - 1); + if(opa < LV_OPA_0) + opa = LV_OPA_0; + else if(opa > LV_OPA_100) + opa = LV_OPA_100; + if(r_act_sqr < r_in_aa_sqr) + break; /*No need to continue the iteration in x once we found the inner edge of the + arc*/ + } + if(opa != -1) { + if(deg_test(180 + deg_base, start_angle, end_angle)) { + lv_draw_px(center_x + xi, center_y + yi, mask, color, opa); + } + if(deg_test(360 - deg_base, start_angle, end_angle)) { + lv_draw_px(center_x + xi, center_y - yi, mask, color, opa); + } + if(deg_test(180 - deg_base, start_angle, end_angle)) { + lv_draw_px(center_x - xi, center_y + yi, mask, color, opa); + } + if(deg_test(deg_base, start_angle, end_angle)) { + lv_draw_px(center_x - xi, center_y - yi, mask, color, opa); + } + continue; + } +#endif + deg = 180 + deg_base; if(deg_test(deg, start_angle, end_angle)) { if(x_start[0] == LV_COORD_MIN) x_start[0] = xi; @@ -129,35 +186,32 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons x_end[3] = xi - 1; } - if(r_act_sqr < r_in_sqr) + if(r_act_sqr < r_in_sqr) { + xe = xi; break; /*No need to continue the iteration in x once we found the inner edge of the arc*/ + } } if(x_start[0] != LV_COORD_MIN) { - if(x_end[0] == LV_COORD_MIN) x_end[0] = xi - 1; + if(x_end[0] == LV_COORD_MIN) x_end[0] = xe - 1; hor_line(center_x + x_start[0], center_y + yi, mask, x_end[0] - x_start[0], color, opa); } if(x_start[1] != LV_COORD_MIN) { - if(x_end[1] == LV_COORD_MIN) x_end[1] = xi - 1; + if(x_end[1] == LV_COORD_MIN) x_end[1] = xe - 1; hor_line(center_x + x_start[1], center_y - yi, mask, x_end[1] - x_start[1], color, opa); } if(x_start[2] != LV_COORD_MIN) { - if(x_end[2] == LV_COORD_MIN) x_end[2] = xi - 1; + if(x_end[2] == LV_COORD_MIN) x_end[2] = xe - 1; hor_line(center_x - x_end[2], center_y + yi, mask, LV_MATH_ABS(x_end[2] - x_start[2]), color, opa); } if(x_start[3] != LV_COORD_MIN) { - if(x_end[3] == LV_COORD_MIN) x_end[3] = xi - 1; + if(x_end[3] == LV_COORD_MIN) x_end[3] = xe - 1; hor_line(center_x - x_end[3], center_y - yi, mask, LV_MATH_ABS(x_end[3] - x_start[3]), color, opa); } - -#if LV_ANTIALIAS - /*TODO*/ - -#endif } } diff --git a/src/lv_draw/lv_draw_basic.c b/src/lv_draw/lv_draw_basic.c index bbe61e512..d1df9058a 100644 --- a/src/lv_draw/lv_draw_basic.c +++ b/src/lv_draw/lv_draw_basic.c @@ -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'); if(g_ret == false) return; + 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; @@ -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++; 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*/ - 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 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 col_start; + lv_coord_t col_end; + lv_coord_t row_start; + 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*/ 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*/ - 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*/ uint32_t bit_ofs = (row_start * width_bit) + (col_start * g.bpp); @@ -326,37 +342,107 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv scr_transp = disp->driver.screen_transp; #endif + uint8_t font_rgb[3]; +#if LV_COLOR_16_SWAP == 0 + uint8_t txt_rgb[3] = {color.ch.red, color.ch.green, color.ch.blue}; +#else + uint8_t txt_rgb[3] = {color.ch.red, (color.ch.green_h << 3) + color.ch.green_l, color.ch.blue}; +#endif + for(row = row_start; row < row_end; row++) { bitmask = bitmask_init >> col_bit; + uint8_t sub_px_cnt = 0; for(col = col_start; col < col_end; col++) { letter_px = (*map_p & bitmask) >> (8 - col_bit - g.bpp); - 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; - } - if(disp->driver.set_px_cb) { - 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); - } else if(vdb_buf_tmp->full != color.full) { - if(px_opa > LV_OPA_MAX) - *vdb_buf_tmp = color; - else if(px_opa > LV_OPA_MIN) { - if(scr_transp == false) { - *vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, px_opa); - } else { + /*subpx == 0*/ + if(subpx == false) { + 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; + } + + if(disp->driver.set_px_cb) { + 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); + } else if(vdb_buf_tmp->full != color.full) { + if(px_opa > LV_OPA_MAX) { + *vdb_buf_tmp = color; + } else if(px_opa > LV_OPA_MIN) { + if(scr_transp == false) { + *vdb_buf_tmp = lv_color_mix(color, *vdb_buf_tmp, px_opa); + } else { #if LV_COLOR_DEPTH == 32 && LV_COLOR_SCREEN_TRANSP - *vdb_buf_tmp = color_mix_2_alpha(*vdb_buf_tmp, (*vdb_buf_tmp).ch.alpha, color, px_opa); + *vdb_buf_tmp = color_mix_2_alpha(*vdb_buf_tmp, (*vdb_buf_tmp).ch.alpha, color, px_opa); #endif + } } } } + 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; + + if(font_rgb[0] == 0 && font_rgb[1] == 0 && font_rgb[2] == 0) { + res_color = *vdb_buf_tmp; + } else { + +#if LV_COLOR_16_SWAP == 0 + uint8_t bg_rgb[3] = {vdb_buf_tmp->ch.red, vdb_buf_tmp->ch.green, vdb_buf_tmp->ch.blue}; +#else + uint8_t bg_rgb[3] = {vdb_buf_tmp->ch.red, + (vdb_buf_tmp->ch.green_h << 3) + vdb_buf_tmp->ch.green_l, + vdb_buf_tmp->ch.blue}; +#endif + +#if LV_SUBPX_BGR + res_color.ch.blue = (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[2] * (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[0] * (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; +#if LV_COLOR_16_SWAP == 0 + res_color.ch.green = (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8; +#else + uint8_t green = (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8; + res_color.ch.green_h = green >> 3; + res_color.ch.green_l = green & 0x7; +#endif + 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++; + } } - vdb_buf_tmp++; if(col_bit < 8 - g.bpp) { col_bit += g.bpp; @@ -367,11 +453,15 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv map_p++; } } + col_bit += ((g.box_w - col_end) + col_start) * g.bpp; map_p += (col_bit >> 3); 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); } } diff --git a/src/lv_font/lv_font.h b/src/lv_font/lv_font.h index e639a54a3..e6433b892 100644 --- a/src/lv_font/lv_font.h +++ b/src/lv_font/lv_font.h @@ -53,7 +53,18 @@ typedef struct uint8_t bpp; /**< Bit-per-pixel: 1, 2, 4, 8*/ }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 { /** 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)*/ 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 subpx :2; /**< An element of `lv_font_subpx_t`*/ void * dsc; /**< Store implementation specific data here*/ #if LV_USE_USER_DATA lv_font_user_data_t user_data; /**< Custom user data for font. */ #endif + + } lv_font_t; /********************** diff --git a/src/lv_font/lv_font_fmt_txt.c b/src/lv_font/lv_font_fmt_txt.c index 1b9f07373..6f350ed75 100644 --- a/src/lv_font/lv_font_fmt_txt.c +++ b/src/lv_font/lv_font_fmt_txt.c @@ -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*/ 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; dsc_out->adv_w = adv_w; diff --git a/src/lv_font/lv_font_fmt_txt.h b/src/lv_font/lv_font_fmt_txt.h index b7efcb3d5..18257c25b 100644 --- a/src/lv_font/lv_font_fmt_txt.h +++ b/src/lv_font/lv_font_fmt_txt.h @@ -191,6 +191,7 @@ typedef struct { * from `lv_font_fmt_txt_bitmap_format_t` */ uint16_t bitmap_format :2; + uint16_t subpx :1; /*Cache the last letter and is glyph id*/ uint32_t last_letter; diff --git a/src/lv_misc/lv_color.h b/src/lv_misc/lv_color.h index a73ab8c88..4f994e2ef 100644 --- a/src/lv_misc/lv_color.h +++ b/src/lv_misc/lv_color.h @@ -303,21 +303,44 @@ static inline uint32_t lv_color_to32(lv_color_t color) ret.ch.alpha = 0xFF; return ret.full; #elif LV_COLOR_DEPTH == 16 + /** + * The floating point math for conversion is: + * valueto = valuefrom * ( (2^bitsto - 1) / (float)(2^bitsfrom - 1) ) + * The faster integer math for conversion is: + * valueto = ( valuefrom * multiplier + adder ) >> divisor + * multiplier = FLOOR( ( (2^bitsto - 1) << divisor ) / (float)(2^bitsfrom - 1) ) + * + * Find the first divisor where ( adder >> divisor ) <= 0 + * + * 5-bit to 8-bit: ( 31 * multiplier + adder ) >> divisor = 255 + * divisor multiplier adder min (0) max (31) + * 0 8 7 7 255 + * 1 16 14 7 255 + * 2 32 28 7 255 + * 3 65 25 3 255 + * 4 131 19 1 255 + * 5 263 7 0 255 + * + * 6-bit to 8-bit: 255 = ( 63 * multiplier + adder ) >> divisor + * divisor multiplier adder min (0) max (63) + * 0 4 3 3 255 + * 1 8 6 3 255 + * 2 16 12 3 255 + * 3 32 24 3 255 + * 4 64 48 3 255 + * 5 129 33 1 255 + * 6 259 3 0 255 + */ + lv_color32_t ret; + ret.ch.red = ( color.ch.red * 263 + 7 ) >> 5; #if LV_COLOR_16_SWAP == 0 - lv_color32_t ret; - ret.ch.red = color.ch.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/ - ret.ch.green = color.ch.green * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/ - ret.ch.blue = color.ch.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/ - ret.ch.alpha = 0xFF; - return ret.full; + ret.ch.green = ( color.ch.green * 259 + 3 ) >> 6; #else - lv_color32_t ret; - ret.ch.red = color.ch.red * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/ - ret.ch.green = ((color.ch.green_h << 3) + color.ch.green_l) * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/ - ret.ch.blue = color.ch.blue * 8; /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/ + ret.ch.green = (((color.ch.green_h << 3) + color.ch.green_l) * 259 + 3 ) >> 6; +#endif + ret.ch.blue = ( color.ch.blue * 263 + 7 ) >> 5; ret.ch.alpha = 0xFF; return ret.full; -#endif #elif LV_COLOR_DEPTH == 32 return color.full; #endif diff --git a/src/lv_misc/lv_math.c b/src/lv_misc/lv_math.c index d1bd51228..f015456e4 100644 --- a/src/lv_misc/lv_math.c +++ b/src/lv_misc/lv_math.c @@ -176,26 +176,26 @@ uint16_t lv_atan2(int x, int y) } /** - * Calculate the sqrt of an integer. - * @param x - * @return the sqrt of x + * Calculate the integer square root of a number. + * @param num + * @return square root of 'num' */ -uint16_t lv_sqrt(uint32_t x) +uint32_t lv_sqrt(uint32_t num) { - uint16_t res=0; - uint16_t add= 0x8000; - int i; - for(i=0;i<16;i++) - { - uint16_t temp=res | add; - uint32_t g2=temp*temp; - if (x>=g2) - { - res=temp; + // http://www.codecodex.com/wiki/Calculate_an_integer_square_root#C + uint32_t root = 0; + uint32_t place = 0x40000000; + + while(place > num) place >>= 2; + while(place) { + if(num >= root + place) { + num -= root + place; + root += (place << 1); } - add>>=1; + root >>= 1; + place >>= 2; } - return res; + return root; } /********************** diff --git a/src/lv_misc/lv_math.h b/src/lv_misc/lv_math.h index 2b1cd6888..dc2c547d5 100644 --- a/src/lv_misc/lv_math.h +++ b/src/lv_misc/lv_math.h @@ -63,11 +63,11 @@ int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3); uint16_t lv_atan2(int x, int y); /** - * Calculate the sqrt of an integer. - * @param x - * @return the sqrt of x + * Calculate the integer square root of a number. + * @param num + * @return square root of 'num' */ -uint16_t lv_sqrt(uint32_t x); +uint32_t lv_sqrt(uint32_t num); /********************** * MACROS diff --git a/src/lv_objx/lv_btnm.c b/src/lv_objx/lv_btnm.c index 179213a60..8421d1197 100644 --- a/src/lv_objx/lv_btnm.c +++ b/src/lv_objx/lv_btnm.c @@ -855,6 +855,12 @@ static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param) #if LV_USE_GROUP lv_indev_t * indev = lv_indev_get_act(); lv_indev_type_t indev_type = lv_indev_get_type(indev); + + /*If not focused by an input device assume the last input device*/ + if(indev_type == LV_INDEV_TYPE_NONE) { + indev_type = lv_indev_get_type(lv_indev_get_next(NULL)); + } + if(indev_type == LV_INDEV_TYPE_POINTER) { /*Select the clicked button*/ lv_point_t p1; diff --git a/src/lv_objx/lv_cpicker.c b/src/lv_objx/lv_cpicker.c index 459d37213..d2bc62523 100644 --- a/src/lv_objx/lv_cpicker.c +++ b/src/lv_objx/lv_cpicker.c @@ -950,6 +950,8 @@ static void next_color_mode(lv_obj_t * cpicker) static void refr_indic_pos(lv_obj_t * cpicker) { + invalidate_indic(cpicker); + lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); lv_coord_t w = lv_obj_get_width(cpicker); lv_coord_t h = lv_obj_get_height(cpicker); diff --git a/src/lv_objx/lv_tabview.c b/src/lv_objx/lv_tabview.c index 3bd684d0a..19924b19b 100644 --- a/src/lv_objx/lv_tabview.c +++ b/src/lv_objx/lv_tabview.c @@ -750,9 +750,12 @@ static lv_res_t lv_tabview_signal(lv_obj_t * tabview, lv_signal_t sign, void * p } if(sign == LV_SIGNAL_FOCUS) { - - lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act()); + /*If not focused by an input device assume the last input device*/ + if(indev_type == LV_INDEV_TYPE_NONE) { + indev_type = lv_indev_get_type(lv_indev_get_next(NULL)); + } + /*With ENCODER select the first button only in edit mode*/ if(indev_type == LV_INDEV_TYPE_ENCODER) { #if LV_USE_GROUP