mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-23 15:56:59 +08:00
feat(arclabel): support lv_arclabel_get_text_angle to get real rendered text size in degree (#9546)
This commit is contained in:
@@ -51,6 +51,8 @@ static void lv_arclabel_event(const lv_obj_class_t * class_p, lv_event_t * e);
|
||||
static lv_value_precise_t calc_arc_text_total_angle(const char * text, const lv_font_t * font, uint32_t radius,
|
||||
const lv_value_precise_t angle_size, int32_t letter_space, bool recolor,
|
||||
const lv_arclabel_overflow_t overflow, bool end_overlap, bool * need_ellipsis, uint32_t * letter_count);
|
||||
static lv_value_precise_t arclabel_calc_arc_text_total_angle(lv_obj_t * obj, int32_t * arc_radius, bool * need_ellipsis,
|
||||
uint32_t * letter_count);
|
||||
static const char * recolor_cmd_get_next(const char * text_in, uint32_t len_in,
|
||||
const char ** text_out, uint32_t * len_out,
|
||||
lv_color_t * color_out);
|
||||
@@ -356,6 +358,13 @@ bool lv_arclabel_get_end_overlap(lv_obj_t * obj)
|
||||
return ((lv_arclabel_t *) obj)->end_overlap;
|
||||
}
|
||||
|
||||
lv_value_precise_t lv_arclabel_get_text_angle(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
return arclabel_calc_arc_text_total_angle(obj, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
@@ -418,42 +427,14 @@ static void arclabel_draw_main(lv_event_t * e)
|
||||
const lv_opa_t opa = LV_OPA_MIX2(layer->opa, lv_obj_get_style_text_opa(obj, LV_PART_MAIN));
|
||||
const int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN);
|
||||
|
||||
const int32_t line_height = font->line_height;
|
||||
const int32_t base_line = font->base_line;
|
||||
int32_t arc_r_delta = 0;
|
||||
int32_t arc_r = arclabel->radius;
|
||||
|
||||
if(arc_r == LV_SIZE_CONTENT) arc_r = LV_PCT(100);
|
||||
if(LV_COORD_IS_PCT(arc_r)) {
|
||||
const int32_t width = lv_area_get_width(&coords);
|
||||
const int32_t height = lv_area_get_height(&coords);
|
||||
arc_r = lv_pct_to_px(arc_r, LV_MIN(width, height)) / 2;
|
||||
}
|
||||
|
||||
switch(arclabel->text_align_v) {
|
||||
case LV_ARCLABEL_TEXT_ALIGN_LEADING:
|
||||
arc_r_delta = line_height - base_line;
|
||||
break;
|
||||
case LV_ARCLABEL_TEXT_ALIGN_CENTER:
|
||||
arc_r_delta = line_height / 2 - base_line;
|
||||
break;
|
||||
case LV_ARCLABEL_TEXT_ALIGN_TRAILING:
|
||||
arc_r_delta = -base_line;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
arc_r += arclabel->dir == LV_ARCLABEL_DIR_CLOCKWISE ? -arc_r_delta : arc_r_delta;
|
||||
|
||||
int32_t arc_r = 0;
|
||||
bool need_ellipsis = false;
|
||||
uint32_t processed_total_word_count = 0;
|
||||
const lv_value_precise_t total_visible_angle = arclabel_calc_arc_text_total_angle(obj, &arc_r, &need_ellipsis,
|
||||
&processed_total_word_count);
|
||||
|
||||
const int32_t offset = arclabel->offset;
|
||||
const lv_value_precise_t angle_offset = rad_to_deg(offset, arc_r);
|
||||
uint32_t processed_total_word_count = 0;
|
||||
|
||||
lv_value_precise_t total_visible_angle = calc_arc_text_total_angle(text_start, font, arc_r,
|
||||
arclabel->angle_size, letter_space, arclabel->recolor,
|
||||
arclabel->overflow, arclabel->end_overlap, &need_ellipsis, &processed_total_word_count);
|
||||
|
||||
lv_value_precise_t angle_start = 0;
|
||||
switch(arclabel->text_align_h) {
|
||||
@@ -568,6 +549,54 @@ static void arclabel_draw_main(lv_event_t * e)
|
||||
}
|
||||
}
|
||||
|
||||
static lv_value_precise_t arclabel_calc_arc_text_total_angle(lv_obj_t * obj, int32_t * arc_radius, bool * need_ellipsis,
|
||||
uint32_t * letter_count)
|
||||
{
|
||||
lv_arclabel_t * arclabel = (lv_arclabel_t *)obj;
|
||||
|
||||
const char * text = arclabel->text;
|
||||
const char * text_start = text;
|
||||
|
||||
lv_area_t coords;
|
||||
lv_obj_get_content_coords(obj, &coords);
|
||||
|
||||
const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN);
|
||||
const int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN);
|
||||
|
||||
const int32_t line_height = font->line_height;
|
||||
const int32_t base_line = font->base_line;
|
||||
int32_t arc_r_delta = 0;
|
||||
int32_t arc_r = arclabel->radius;
|
||||
|
||||
if(arc_r == LV_SIZE_CONTENT) arc_r = LV_PCT(100);
|
||||
if(LV_COORD_IS_PCT(arc_r)) {
|
||||
const int32_t width = lv_area_get_width(&coords);
|
||||
const int32_t height = lv_area_get_height(&coords);
|
||||
arc_r = lv_pct_to_px(arc_r, LV_MIN(width, height)) / 2;
|
||||
}
|
||||
|
||||
switch(arclabel->text_align_v) {
|
||||
case LV_ARCLABEL_TEXT_ALIGN_LEADING:
|
||||
arc_r_delta = line_height - base_line;
|
||||
break;
|
||||
case LV_ARCLABEL_TEXT_ALIGN_CENTER:
|
||||
arc_r_delta = line_height / 2 - base_line;
|
||||
break;
|
||||
case LV_ARCLABEL_TEXT_ALIGN_TRAILING:
|
||||
arc_r_delta = -base_line;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
arc_r += arclabel->dir == LV_ARCLABEL_DIR_CLOCKWISE ? -arc_r_delta : arc_r_delta;
|
||||
if(arc_radius != NULL) *arc_radius = arc_r;
|
||||
lv_value_precise_t total_visible_angle = calc_arc_text_total_angle(text_start, font, arc_r,
|
||||
arclabel->angle_size, letter_space, arclabel->recolor,
|
||||
arclabel->overflow, arclabel->end_overlap, need_ellipsis, letter_count);
|
||||
return total_visible_angle;
|
||||
}
|
||||
|
||||
static lv_value_precise_t calc_arc_text_total_angle(const char * text, const lv_font_t * font, const uint32_t radius,
|
||||
const lv_value_precise_t angle_size, const int32_t letter_space, const bool recolor,
|
||||
const lv_arclabel_overflow_t overflow, bool end_overlap, bool * need_ellipsis, uint32_t * letter_count)
|
||||
@@ -580,6 +609,7 @@ static lv_value_precise_t calc_arc_text_total_angle(const char * text, const lv_
|
||||
lv_value_precise_t total_arc_length = 0;
|
||||
lv_value_precise_t pre_total_arc_length = 0;
|
||||
uint32_t pre_processed_letter_count = 0;
|
||||
lv_value_precise_t ellipsis_arc_length = 0;
|
||||
bool full = false;
|
||||
uint32_t letter = 0;
|
||||
uint32_t letter_next = 0;
|
||||
@@ -587,7 +617,7 @@ static lv_value_precise_t calc_arc_text_total_angle(const char * text, const lv_
|
||||
lv_value_precise_t available_arc_length = angle_size_in_arc_length;
|
||||
if(overflow == LV_ARCLABEL_OVERFLOW_ELLIPSIS) {
|
||||
lv_value_precise_t dot_width = lv_font_get_glyph_width(font, '.', '.');
|
||||
lv_value_precise_t ellipsis_arc_length = 3 * dot_width + 2 * letter_space;
|
||||
ellipsis_arc_length = 3 * dot_width + 2 * letter_space;
|
||||
if(available_arc_length > ellipsis_arc_length) available_arc_length -= ellipsis_arc_length;
|
||||
else available_arc_length = 0;
|
||||
}
|
||||
@@ -628,7 +658,9 @@ static lv_value_precise_t calc_arc_text_total_angle(const char * text, const lv_
|
||||
}
|
||||
|
||||
if(full && (overflow == LV_ARCLABEL_OVERFLOW_ELLIPSIS || overflow == LV_ARCLABEL_OVERFLOW_CLIP)) {
|
||||
total_arc_length = pre_total_arc_length;
|
||||
total_arc_length = pre_total_arc_length + (overflow == LV_ARCLABEL_OVERFLOW_ELLIPSIS
|
||||
? ellipsis_arc_length
|
||||
: 0);
|
||||
processed_letter_count = pre_processed_letter_count;
|
||||
}
|
||||
|
||||
|
||||
@@ -273,6 +273,17 @@ lv_arclabel_overflow_t lv_arclabel_get_overflow(lv_obj_t * obj);
|
||||
*/
|
||||
bool lv_arclabel_get_end_overlap(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* Get the text angle for an arc label object.
|
||||
* @note The text angle is calculated at runtime. You can get the updated value
|
||||
* after the arclabel's size has been updated.
|
||||
* Returns the real rendered text angle in degrees except in
|
||||
* `LV_ARCLABEL_OVERFLOW_VISIBLE` mode.
|
||||
* @param obj pointer to an arc label object
|
||||
* @return the text angle (if `LV_USE_FLOAT` is enabled it can be fractional too.)
|
||||
*/
|
||||
lv_value_precise_t lv_arclabel_get_text_angle(lv_obj_t * obj);
|
||||
|
||||
/*=====================
|
||||
* Other functions
|
||||
*====================*/
|
||||
|
||||
@@ -165,10 +165,13 @@ void test_arclabel_overflow(void)
|
||||
lv_arclabel_set_dir(arclabel, LV_ARCLABEL_DIR_CLOCKWISE);
|
||||
lv_arclabel_set_overflow(arclabel, overflows[i]);
|
||||
lv_obj_center(arclabel);
|
||||
}
|
||||
|
||||
lv_obj_refr_size(arclabel);
|
||||
TEST_ASSERT_GREATER_THAN_FLOAT(178, lv_arclabel_get_text_angle(arclabel));
|
||||
}
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/arclabel_overflow" EXT_NAME);
|
||||
}
|
||||
|
||||
void test_arclabel_opacity(void)
|
||||
{
|
||||
if(!font) {
|
||||
@@ -220,4 +223,5 @@ void test_arclabel_opacity(void)
|
||||
}
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/arclabel_opacity" EXT_NAME);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user