acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
lv_meter.c (27236B)
1 /** 2 * @file lv_meter.c 3 * 4 */ 5 6 /********************* 7 * INCLUDES 8 *********************/ 9 #include "lv_meter.h" 10 #if LV_USE_METER != 0 11 12 #include "../../../misc/lv_assert.h" 13 14 /********************* 15 * DEFINES 16 *********************/ 17 #define MY_CLASS &lv_meter_class 18 19 /********************** 20 * TYPEDEFS 21 **********************/ 22 23 /********************** 24 * STATIC PROTOTYPES 25 **********************/ 26 static void lv_meter_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); 27 static void lv_meter_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); 28 static void lv_meter_event(const lv_obj_class_t * class_p, lv_event_t * e); 29 static void draw_arcs(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, const lv_area_t * scale_area); 30 static void draw_ticks_and_labels(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, const lv_area_t * scale_area); 31 static void draw_needles(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, const lv_area_t * scale_area); 32 static void inv_arc(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t old_value, int32_t new_value); 33 static void inv_line(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value); 34 35 /********************** 36 * STATIC VARIABLES 37 **********************/ 38 const lv_obj_class_t lv_meter_class = { 39 .constructor_cb = lv_meter_constructor, 40 .destructor_cb = lv_meter_destructor, 41 .event_cb = lv_meter_event, 42 .instance_size = sizeof(lv_meter_t), 43 .base_class = &lv_obj_class 44 }; 45 46 /********************** 47 * MACROS 48 **********************/ 49 50 /********************** 51 * GLOBAL FUNCTIONS 52 **********************/ 53 54 lv_obj_t * lv_meter_create(lv_obj_t * parent) 55 { 56 LV_LOG_INFO("begin"); 57 lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); 58 lv_obj_class_init_obj(obj); 59 return obj; 60 } 61 62 /*===================== 63 * Add scale 64 *====================*/ 65 66 lv_meter_scale_t * lv_meter_add_scale(lv_obj_t * obj) 67 { 68 LV_ASSERT_OBJ(obj, MY_CLASS); 69 lv_meter_t * meter = (lv_meter_t *)obj; 70 71 lv_meter_scale_t * scale = _lv_ll_ins_head(&meter->scale_ll); 72 LV_ASSERT_MALLOC(scale); 73 lv_memset_00(scale, sizeof(lv_meter_scale_t)); 74 75 scale->angle_range = 270; 76 scale->rotation = 90 + (360 - scale->angle_range) / 2; 77 scale->min = 0; 78 scale->max = 100; 79 scale->tick_cnt = 6; 80 scale->tick_length = 8; 81 scale->tick_width = 2; 82 scale->label_gap = 2; 83 84 return scale; 85 } 86 87 void lv_meter_set_scale_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t cnt, uint16_t width, uint16_t len, 88 lv_color_t color) 89 { 90 scale->tick_cnt = cnt; 91 scale->tick_width = width; 92 scale->tick_length = len; 93 scale->tick_color = color; 94 lv_obj_invalidate(obj); 95 } 96 97 void lv_meter_set_scale_major_ticks(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t nth, uint16_t width, 98 uint16_t len, lv_color_t color, int16_t label_gap) 99 { 100 scale->tick_major_nth = nth; 101 scale->tick_major_width = width; 102 scale->tick_major_length = len; 103 scale->tick_major_color = color; 104 scale->label_gap = label_gap; 105 lv_obj_invalidate(obj); 106 } 107 108 void lv_meter_set_scale_range(lv_obj_t * obj, lv_meter_scale_t * scale, int32_t min, int32_t max, uint32_t angle_range, 109 uint32_t rotation) 110 { 111 scale->min = min; 112 scale->max = max; 113 scale->angle_range = angle_range; 114 scale->rotation = rotation; 115 lv_obj_invalidate(obj); 116 } 117 118 /*===================== 119 * Add indicator 120 *====================*/ 121 122 lv_meter_indicator_t * lv_meter_add_needle_line(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, 123 lv_color_t color, int16_t r_mod) 124 { 125 LV_ASSERT_OBJ(obj, MY_CLASS); 126 lv_meter_t * meter = (lv_meter_t *)obj; 127 lv_meter_indicator_t * indic = _lv_ll_ins_head(&meter->indicator_ll); 128 LV_ASSERT_MALLOC(indic); 129 lv_memset_00(indic, sizeof(lv_meter_indicator_t)); 130 indic->scale = scale; 131 indic->opa = LV_OPA_COVER; 132 133 indic->type = LV_METER_INDICATOR_TYPE_NEEDLE_LINE; 134 indic->type_data.needle_line.width = width; 135 indic->type_data.needle_line.color = color; 136 indic->type_data.needle_line.r_mod = r_mod; 137 lv_obj_invalidate(obj); 138 139 return indic; 140 } 141 142 lv_meter_indicator_t * lv_meter_add_needle_img(lv_obj_t * obj, lv_meter_scale_t * scale, const void * src, 143 lv_coord_t pivot_x, lv_coord_t pivot_y) 144 { 145 LV_ASSERT_OBJ(obj, MY_CLASS); 146 lv_meter_t * meter = (lv_meter_t *)obj; 147 lv_meter_indicator_t * indic = _lv_ll_ins_head(&meter->indicator_ll); 148 LV_ASSERT_MALLOC(indic); 149 lv_memset_00(indic, sizeof(lv_meter_indicator_t)); 150 indic->scale = scale; 151 indic->opa = LV_OPA_COVER; 152 153 indic->type = LV_METER_INDICATOR_TYPE_NEEDLE_IMG; 154 indic->type_data.needle_img.src = src; 155 indic->type_data.needle_img.pivot.x = pivot_x; 156 indic->type_data.needle_img.pivot.y = pivot_y; 157 lv_obj_invalidate(obj); 158 159 return indic; 160 } 161 162 lv_meter_indicator_t * lv_meter_add_arc(lv_obj_t * obj, lv_meter_scale_t * scale, uint16_t width, lv_color_t color, 163 int16_t r_mod) 164 { 165 LV_ASSERT_OBJ(obj, MY_CLASS); 166 lv_meter_t * meter = (lv_meter_t *)obj; 167 lv_meter_indicator_t * indic = _lv_ll_ins_head(&meter->indicator_ll); 168 LV_ASSERT_MALLOC(indic); 169 lv_memset_00(indic, sizeof(lv_meter_indicator_t)); 170 indic->scale = scale; 171 indic->opa = LV_OPA_COVER; 172 173 indic->type = LV_METER_INDICATOR_TYPE_ARC; 174 indic->type_data.arc.width = width; 175 indic->type_data.arc.color = color; 176 indic->type_data.arc.r_mod = r_mod; 177 178 lv_obj_invalidate(obj); 179 return indic; 180 } 181 182 lv_meter_indicator_t * lv_meter_add_scale_lines(lv_obj_t * obj, lv_meter_scale_t * scale, lv_color_t color_start, 183 lv_color_t color_end, bool local, int16_t width_mod) 184 { 185 LV_ASSERT_OBJ(obj, MY_CLASS); 186 lv_meter_t * meter = (lv_meter_t *)obj; 187 lv_meter_indicator_t * indic = _lv_ll_ins_head(&meter->indicator_ll); 188 LV_ASSERT_MALLOC(indic); 189 lv_memset_00(indic, sizeof(lv_meter_indicator_t)); 190 indic->scale = scale; 191 indic->opa = LV_OPA_COVER; 192 193 indic->type = LV_METER_INDICATOR_TYPE_SCALE_LINES; 194 indic->type_data.scale_lines.color_start = color_start; 195 indic->type_data.scale_lines.color_end = color_end; 196 indic->type_data.scale_lines.local_grad = local; 197 indic->type_data.scale_lines.width_mod = width_mod; 198 199 lv_obj_invalidate(obj); 200 return indic; 201 } 202 203 /*===================== 204 * Set indicator value 205 *====================*/ 206 207 void lv_meter_set_indicator_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) 208 { 209 int32_t old_start = indic->start_value; 210 int32_t old_end = indic->end_value; 211 indic->start_value = value; 212 indic->end_value = value; 213 214 if(indic->type == LV_METER_INDICATOR_TYPE_ARC) { 215 inv_arc(obj, indic, old_start, value); 216 inv_arc(obj, indic, old_end, value); 217 } 218 else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG || indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { 219 inv_line(obj, indic, old_start); 220 inv_line(obj, indic, old_end); 221 inv_line(obj, indic, value); 222 } 223 else { 224 lv_obj_invalidate(obj); 225 } 226 } 227 228 void lv_meter_set_indicator_start_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) 229 { 230 int32_t old_value = indic->start_value; 231 indic->start_value = value; 232 233 if(indic->type == LV_METER_INDICATOR_TYPE_ARC) { 234 inv_arc(obj, indic, old_value, value); 235 } 236 else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG || indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { 237 inv_line(obj, indic, old_value); 238 inv_line(obj, indic, value); 239 } 240 else { 241 lv_obj_invalidate(obj); 242 } 243 } 244 245 void lv_meter_set_indicator_end_value(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) 246 { 247 int32_t old_value = indic->end_value; 248 indic->end_value = value; 249 250 if(indic->type == LV_METER_INDICATOR_TYPE_ARC) { 251 inv_arc(obj, indic, old_value, value); 252 } 253 else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG || indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { 254 inv_line(obj, indic, old_value); 255 inv_line(obj, indic, value); 256 } 257 else { 258 lv_obj_invalidate(obj); 259 } 260 } 261 262 /********************** 263 * STATIC FUNCTIONS 264 **********************/ 265 266 static void lv_meter_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) 267 { 268 LV_UNUSED(class_p); 269 LV_TRACE_OBJ_CREATE("begin"); 270 271 lv_meter_t * meter = (lv_meter_t *)obj; 272 273 _lv_ll_init(&meter->scale_ll, sizeof(lv_meter_scale_t)); 274 _lv_ll_init(&meter->indicator_ll, sizeof(lv_meter_indicator_t)); 275 276 LV_TRACE_OBJ_CREATE("finished"); 277 } 278 279 static void lv_meter_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj) 280 { 281 LV_UNUSED(class_p); 282 LV_ASSERT_OBJ(obj, MY_CLASS); 283 lv_meter_t * meter = (lv_meter_t *)obj; 284 _lv_ll_clear(&meter->indicator_ll); 285 _lv_ll_clear(&meter->scale_ll); 286 287 } 288 289 static void lv_meter_event(const lv_obj_class_t * class_p, lv_event_t * e) 290 { 291 LV_UNUSED(class_p); 292 293 lv_res_t res = lv_obj_event_base(MY_CLASS, e); 294 if(res != LV_RES_OK) return; 295 296 lv_event_code_t code = lv_event_get_code(e); 297 lv_obj_t * obj = lv_event_get_target(e); 298 if(code == LV_EVENT_DRAW_MAIN) { 299 lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); 300 lv_area_t scale_area; 301 lv_obj_get_content_coords(obj, &scale_area); 302 303 draw_arcs(obj, draw_ctx, &scale_area); 304 draw_ticks_and_labels(obj, draw_ctx, &scale_area); 305 draw_needles(obj, draw_ctx, &scale_area); 306 307 lv_coord_t r_edge = lv_area_get_width(&scale_area) / 2; 308 lv_point_t scale_center; 309 scale_center.x = scale_area.x1 + r_edge; 310 scale_center.y = scale_area.y1 + r_edge; 311 312 lv_draw_rect_dsc_t mid_dsc; 313 lv_draw_rect_dsc_init(&mid_dsc); 314 lv_obj_init_draw_rect_dsc(obj, LV_PART_INDICATOR, &mid_dsc); 315 lv_coord_t w = lv_obj_get_style_width(obj, LV_PART_INDICATOR) / 2; 316 lv_coord_t h = lv_obj_get_style_height(obj, LV_PART_INDICATOR) / 2; 317 lv_area_t nm_cord; 318 nm_cord.x1 = scale_center.x - w; 319 nm_cord.y1 = scale_center.y - h; 320 nm_cord.x2 = scale_center.x + w; 321 nm_cord.y2 = scale_center.y + h; 322 lv_draw_rect(draw_ctx, &mid_dsc, &nm_cord); 323 } 324 } 325 326 static void draw_arcs(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, const lv_area_t * scale_area) 327 { 328 lv_meter_t * meter = (lv_meter_t *)obj; 329 330 lv_draw_arc_dsc_t arc_dsc; 331 lv_draw_arc_dsc_init(&arc_dsc); 332 arc_dsc.rounded = lv_obj_get_style_arc_rounded(obj, LV_PART_ITEMS); 333 334 lv_coord_t r_out = lv_area_get_width(scale_area) / 2 ; 335 lv_point_t scale_center; 336 scale_center.x = scale_area->x1 + r_out; 337 scale_center.y = scale_area->y1 + r_out; 338 339 lv_opa_t opa_main = lv_obj_get_style_opa(obj, LV_PART_MAIN); 340 lv_meter_indicator_t * indic; 341 342 lv_obj_draw_part_dsc_t part_draw_dsc; 343 lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); 344 part_draw_dsc.arc_dsc = &arc_dsc; 345 part_draw_dsc.part = LV_PART_INDICATOR; 346 part_draw_dsc.class_p = MY_CLASS; 347 part_draw_dsc.type = LV_METER_DRAW_PART_ARC; 348 349 _LV_LL_READ_BACK(&meter->indicator_ll, indic) { 350 if(indic->type != LV_METER_INDICATOR_TYPE_ARC) continue; 351 352 arc_dsc.color = indic->type_data.arc.color; 353 arc_dsc.width = indic->type_data.arc.width; 354 arc_dsc.opa = indic->opa > LV_OPA_MAX ? opa_main : (opa_main * indic->opa) >> 8; 355 356 lv_meter_scale_t * scale = indic->scale; 357 358 int32_t start_angle = lv_map(indic->start_value, scale->min, scale->max, scale->rotation, 359 scale->rotation + scale->angle_range); 360 int32_t end_angle = lv_map(indic->end_value, scale->min, scale->max, scale->rotation, 361 scale->rotation + scale->angle_range); 362 363 part_draw_dsc.radius = r_out + indic->type_data.arc.r_mod; 364 part_draw_dsc.sub_part_ptr = indic; 365 part_draw_dsc.p1 = &scale_center; 366 367 lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); 368 lv_draw_arc(draw_ctx, &arc_dsc, &scale_center, part_draw_dsc.radius, start_angle, end_angle); 369 lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); 370 } 371 } 372 373 static void draw_ticks_and_labels(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, const lv_area_t * scale_area) 374 { 375 lv_meter_t * meter = (lv_meter_t *)obj; 376 377 lv_point_t p_center; 378 lv_coord_t r_edge = LV_MIN(lv_area_get_width(scale_area) / 2, lv_area_get_height(scale_area) / 2); 379 p_center.x = scale_area->x1 + r_edge; 380 p_center.y = scale_area->y1 + r_edge; 381 382 lv_draw_line_dsc_t line_dsc; 383 lv_draw_line_dsc_init(&line_dsc); 384 lv_obj_init_draw_line_dsc(obj, LV_PART_TICKS, &line_dsc); 385 line_dsc.raw_end = 1; 386 387 lv_draw_label_dsc_t label_dsc; 388 lv_draw_label_dsc_init(&label_dsc); 389 lv_obj_init_draw_label_dsc(obj, LV_PART_TICKS, &label_dsc); 390 391 lv_meter_scale_t * scale; 392 393 lv_draw_mask_radius_param_t inner_minor_mask; 394 lv_draw_mask_radius_param_t inner_major_mask; 395 lv_draw_mask_radius_param_t outer_mask; 396 397 lv_obj_draw_part_dsc_t part_draw_dsc; 398 lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); 399 part_draw_dsc.class_p = MY_CLASS; 400 part_draw_dsc.part = LV_PART_TICKS; 401 part_draw_dsc.type = LV_METER_DRAW_PART_TICK; 402 part_draw_dsc.line_dsc = &line_dsc; 403 404 _LV_LL_READ_BACK(&meter->scale_ll, scale) { 405 part_draw_dsc.sub_part_ptr = scale; 406 407 lv_coord_t r_out = r_edge + scale->r_mod; 408 lv_coord_t r_in_minor = r_out - scale->tick_length; 409 lv_coord_t r_in_major = r_out - scale->tick_major_length; 410 411 lv_area_t area_inner_minor; 412 area_inner_minor.x1 = p_center.x - r_in_minor; 413 area_inner_minor.y1 = p_center.y - r_in_minor; 414 area_inner_minor.x2 = p_center.x + r_in_minor; 415 area_inner_minor.y2 = p_center.y + r_in_minor; 416 lv_draw_mask_radius_init(&inner_minor_mask, &area_inner_minor, LV_RADIUS_CIRCLE, true); 417 418 lv_area_t area_inner_major; 419 area_inner_major.x1 = p_center.x - r_in_major; 420 area_inner_major.y1 = p_center.y - r_in_major; 421 area_inner_major.x2 = p_center.x + r_in_major - 1; 422 area_inner_major.y2 = p_center.y + r_in_major - 1; 423 lv_draw_mask_radius_init(&inner_major_mask, &area_inner_major, LV_RADIUS_CIRCLE, true); 424 425 lv_area_t area_outer; 426 area_outer.x1 = p_center.x - r_out; 427 area_outer.y1 = p_center.y - r_out; 428 area_outer.x2 = p_center.x + r_out - 1; 429 area_outer.y2 = p_center.y + r_out - 1; 430 lv_draw_mask_radius_init(&outer_mask, &area_outer, LV_RADIUS_CIRCLE, false); 431 int16_t outer_mask_id = lv_draw_mask_add(&outer_mask, NULL); 432 433 int16_t inner_act_mask_id = LV_MASK_ID_INV; /*Will be added later*/ 434 435 uint32_t minor_cnt = scale->tick_major_nth ? scale->tick_major_nth - 1 : 0xFFFF; 436 uint16_t i; 437 for(i = 0; i < scale->tick_cnt; i++) { 438 minor_cnt++; 439 bool major = false; 440 if(minor_cnt == scale->tick_major_nth) { 441 minor_cnt = 0; 442 major = true; 443 } 444 445 int32_t value_of_line = lv_map(i, 0, scale->tick_cnt - 1, scale->min, scale->max); 446 part_draw_dsc.value = value_of_line; 447 448 lv_color_t line_color = major ? scale->tick_major_color : scale->tick_color; 449 lv_color_t line_color_ori = line_color; 450 451 lv_coord_t line_width_ori = major ? scale->tick_major_width : scale->tick_width; 452 lv_coord_t line_width = line_width_ori; 453 454 lv_meter_indicator_t * indic; 455 _LV_LL_READ_BACK(&meter->indicator_ll, indic) { 456 if(indic->type != LV_METER_INDICATOR_TYPE_SCALE_LINES) continue; 457 if(value_of_line >= indic->start_value && value_of_line <= indic->end_value) { 458 line_width += indic->type_data.scale_lines.width_mod; 459 460 if(indic->type_data.scale_lines.color_start.full == indic->type_data.scale_lines.color_end.full) { 461 line_color = indic->type_data.scale_lines.color_start; 462 } 463 else { 464 lv_opa_t ratio; 465 if(indic->type_data.scale_lines.local_grad) { 466 ratio = lv_map(value_of_line, indic->start_value, indic->end_value, LV_OPA_TRANSP, LV_OPA_COVER); 467 } 468 else { 469 ratio = lv_map(value_of_line, scale->min, scale->max, LV_OPA_TRANSP, LV_OPA_COVER); 470 } 471 line_color = lv_color_mix(indic->type_data.scale_lines.color_end, indic->type_data.scale_lines.color_start, ratio); 472 } 473 } 474 } 475 476 /*`* 256` for extra precision*/ 477 int32_t angle_upscale = ((i * scale->angle_range) << 8) / (scale->tick_cnt - 1); 478 479 int32_t angle_low = (angle_upscale >> 8); 480 int32_t angle_high = angle_low + 1; 481 int32_t angle_rem = angle_upscale & 0xFF; 482 483 /*Interpolate sine and cos*/ 484 int32_t sin_low = lv_trigo_sin(angle_low + scale->rotation); 485 int32_t sin_high = lv_trigo_sin(angle_high + scale->rotation); 486 int32_t sin_mid = (sin_low * (256 - angle_rem) + sin_high * angle_rem) >> 8; 487 488 int32_t cos_low = lv_trigo_cos(angle_low + scale->rotation); 489 int32_t cos_high = lv_trigo_cos(angle_high + scale->rotation); 490 int32_t cos_mid = (cos_low * (256 - angle_rem) + cos_high * angle_rem) >> 8; 491 492 line_dsc.color = line_color; 493 line_dsc.width = line_width; 494 /*Use the interpolated angle to get the outer x and y coordinates. 495 *Draw a little bit longer lines to be sure the mask will clip them correctly*/ 496 lv_point_t p_outer; 497 p_outer.x = (int32_t)(((int32_t)cos_mid * (r_out + line_width) + 127) >> (LV_TRIGO_SHIFT)) + p_center.x; 498 p_outer.y = (int32_t)(((int32_t)sin_mid * (r_out + line_width) + 127) >> (LV_TRIGO_SHIFT)) + p_center.y; 499 500 part_draw_dsc.p1 = &p_outer; 501 part_draw_dsc.p1 = &p_center; 502 part_draw_dsc.id = i; 503 part_draw_dsc.label_dsc = &label_dsc; 504 505 /*Draw the text*/ 506 if(major) { 507 lv_draw_mask_remove_id(outer_mask_id); 508 uint32_t r_text = r_in_major - scale->label_gap; 509 lv_point_t p; 510 p.x = (int32_t)((int32_t)((int32_t)cos_mid * r_text + 127) >> LV_TRIGO_SHIFT) + p_center.x; 511 p.y = (int32_t)((int32_t)((int32_t)sin_mid * r_text + 127) >> LV_TRIGO_SHIFT) + p_center.y; 512 513 lv_draw_label_dsc_t label_dsc_tmp; 514 lv_memcpy(&label_dsc_tmp, &label_dsc, sizeof(label_dsc_tmp)); 515 516 part_draw_dsc.label_dsc = &label_dsc_tmp; 517 char buf[16]; 518 519 lv_snprintf(buf, sizeof(buf), "%" LV_PRId32, value_of_line); 520 part_draw_dsc.text = buf; 521 522 lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); 523 524 lv_point_t label_size; 525 lv_txt_get_size(&label_size, part_draw_dsc.text, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, 526 LV_COORD_MAX, LV_TEXT_FLAG_NONE); 527 528 lv_area_t label_cord; 529 label_cord.x1 = p.x - label_size.x / 2; 530 label_cord.y1 = p.y - label_size.y / 2; 531 label_cord.x2 = label_cord.x1 + label_size.x; 532 label_cord.y2 = label_cord.y1 + label_size.y; 533 534 lv_draw_label(draw_ctx, part_draw_dsc.label_dsc, &label_cord, part_draw_dsc.text, NULL); 535 536 outer_mask_id = lv_draw_mask_add(&outer_mask, NULL); 537 } 538 else { 539 part_draw_dsc.label_dsc = NULL; 540 part_draw_dsc.text = NULL; 541 lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); 542 } 543 544 inner_act_mask_id = lv_draw_mask_add(major ? &inner_major_mask : &inner_minor_mask, NULL); 545 lv_draw_line(draw_ctx, &line_dsc, &p_outer, &p_center); 546 lv_draw_mask_remove_id(inner_act_mask_id); 547 lv_event_send(obj, LV_EVENT_DRAW_MAIN_END, &part_draw_dsc); 548 549 line_dsc.color = line_color_ori; 550 line_dsc.width = line_width_ori; 551 552 } 553 lv_draw_mask_free_param(&inner_minor_mask); 554 lv_draw_mask_free_param(&inner_major_mask); 555 lv_draw_mask_free_param(&outer_mask); 556 lv_draw_mask_remove_id(outer_mask_id); 557 } 558 } 559 560 561 static void draw_needles(lv_obj_t * obj, lv_draw_ctx_t * draw_ctx, const lv_area_t * scale_area) 562 { 563 lv_meter_t * meter = (lv_meter_t *)obj; 564 565 lv_coord_t r_edge = lv_area_get_width(scale_area) / 2; 566 lv_point_t scale_center; 567 scale_center.x = scale_area->x1 + r_edge; 568 scale_center.y = scale_area->y1 + r_edge; 569 570 lv_draw_line_dsc_t line_dsc; 571 lv_draw_line_dsc_init(&line_dsc); 572 lv_obj_init_draw_line_dsc(obj, LV_PART_ITEMS, &line_dsc); 573 574 lv_draw_img_dsc_t img_dsc; 575 lv_draw_img_dsc_init(&img_dsc); 576 lv_obj_init_draw_img_dsc(obj, LV_PART_ITEMS, &img_dsc); 577 lv_opa_t opa_main = lv_obj_get_style_opa(obj, LV_PART_MAIN); 578 579 lv_obj_draw_part_dsc_t part_draw_dsc; 580 lv_obj_draw_dsc_init(&part_draw_dsc, draw_ctx); 581 part_draw_dsc.class_p = MY_CLASS; 582 part_draw_dsc.p1 = &scale_center; 583 584 lv_meter_indicator_t * indic; 585 _LV_LL_READ_BACK(&meter->indicator_ll, indic) { 586 lv_meter_scale_t * scale = indic->scale; 587 part_draw_dsc.sub_part_ptr = indic; 588 589 if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { 590 int32_t angle = lv_map(indic->end_value, scale->min, scale->max, scale->rotation, scale->rotation + scale->angle_range); 591 lv_coord_t r_out = r_edge + scale->r_mod + indic->type_data.needle_line.r_mod; 592 lv_point_t p_end; 593 p_end.y = (lv_trigo_sin(angle) * (r_out)) / LV_TRIGO_SIN_MAX + scale_center.y; 594 p_end.x = (lv_trigo_cos(angle) * (r_out)) / LV_TRIGO_SIN_MAX + scale_center.x; 595 line_dsc.color = indic->type_data.needle_line.color; 596 line_dsc.width = indic->type_data.needle_line.width; 597 line_dsc.opa = indic->opa > LV_OPA_MAX ? opa_main : (opa_main * indic->opa) >> 8; 598 599 part_draw_dsc.id = LV_METER_DRAW_PART_NEEDLE_LINE; 600 part_draw_dsc.line_dsc = &line_dsc; 601 part_draw_dsc.p2 = &p_end; 602 603 lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); 604 lv_draw_line(draw_ctx, &line_dsc, &scale_center, &p_end); 605 lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); 606 } 607 else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG) { 608 if(indic->type_data.needle_img.src == NULL) continue; 609 610 int32_t angle = lv_map(indic->end_value, scale->min, scale->max, scale->rotation, scale->rotation + scale->angle_range); 611 lv_img_header_t info; 612 lv_img_decoder_get_info(indic->type_data.needle_img.src, &info); 613 lv_area_t a; 614 a.x1 = scale_center.x - indic->type_data.needle_img.pivot.x; 615 a.y1 = scale_center.y - indic->type_data.needle_img.pivot.y; 616 a.x2 = a.x1 + info.w - 1; 617 a.y2 = a.y1 + info.h - 1; 618 619 img_dsc.opa = indic->opa > LV_OPA_MAX ? opa_main : (opa_main * indic->opa) >> 8; 620 img_dsc.pivot.x = indic->type_data.needle_img.pivot.x; 621 img_dsc.pivot.y = indic->type_data.needle_img.pivot.y; 622 angle = angle * 10; 623 if(angle > 3600) angle -= 3600; 624 img_dsc.angle = angle; 625 626 part_draw_dsc.img_dsc = &img_dsc; 627 628 lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_draw_dsc); 629 lv_draw_img(draw_ctx, &img_dsc, &a, indic->type_data.needle_img.src); 630 lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_draw_dsc); 631 } 632 } 633 } 634 635 static void inv_arc(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t old_value, int32_t new_value) 636 { 637 bool rounded = lv_obj_get_style_arc_rounded(obj, LV_PART_ITEMS); 638 639 lv_area_t scale_area; 640 lv_obj_get_content_coords(obj, &scale_area); 641 642 lv_coord_t r_out = lv_area_get_width(&scale_area) / 2; 643 lv_point_t scale_center; 644 scale_center.x = scale_area.x1 + r_out; 645 scale_center.y = scale_area.y1 + r_out; 646 647 r_out += indic->type_data.arc.r_mod; 648 649 lv_meter_scale_t * scale = indic->scale; 650 651 int32_t start_angle = lv_map(old_value, scale->min, scale->max, scale->rotation, scale->angle_range + scale->rotation); 652 int32_t end_angle = lv_map(new_value, scale->min, scale->max, scale->rotation, scale->angle_range + scale->rotation); 653 654 lv_area_t a; 655 lv_draw_arc_get_area(scale_center.x, scale_center.y, r_out, LV_MIN(start_angle, end_angle), LV_MAX(start_angle, 656 end_angle), indic->type_data.arc.width, rounded, &a); 657 lv_obj_invalidate_area(obj, &a); 658 } 659 660 661 static void inv_line(lv_obj_t * obj, lv_meter_indicator_t * indic, int32_t value) 662 { 663 lv_area_t scale_area; 664 lv_obj_get_content_coords(obj, &scale_area); 665 666 lv_coord_t r_out = lv_area_get_width(&scale_area) / 2; 667 lv_point_t scale_center; 668 scale_center.x = scale_area.x1 + r_out; 669 scale_center.y = scale_area.y1 + r_out; 670 671 lv_meter_scale_t * scale = indic->scale; 672 673 if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_LINE) { 674 int32_t angle = lv_map(value, scale->min, scale->max, scale->rotation, scale->rotation + scale->angle_range); 675 r_out += scale->r_mod + indic->type_data.needle_line.r_mod; 676 lv_point_t p_end; 677 p_end.y = (lv_trigo_sin(angle) * (r_out)) / LV_TRIGO_SIN_MAX + scale_center.y; 678 p_end.x = (lv_trigo_cos(angle) * (r_out)) / LV_TRIGO_SIN_MAX + scale_center.x; 679 680 lv_area_t a; 681 a.x1 = LV_MIN(scale_center.x, p_end.x) - indic->type_data.needle_line.width - 2; 682 a.y1 = LV_MIN(scale_center.y, p_end.y) - indic->type_data.needle_line.width - 2; 683 a.x2 = LV_MAX(scale_center.x, p_end.x) + indic->type_data.needle_line.width + 2; 684 a.y2 = LV_MAX(scale_center.y, p_end.y) + indic->type_data.needle_line.width + 2; 685 686 lv_obj_invalidate_area(obj, &a); 687 } 688 else if(indic->type == LV_METER_INDICATOR_TYPE_NEEDLE_IMG) { 689 int32_t angle = lv_map(value, scale->min, scale->max, scale->rotation, scale->rotation + scale->angle_range); 690 lv_img_header_t info; 691 lv_img_decoder_get_info(indic->type_data.needle_img.src, &info); 692 693 angle = angle * 10; 694 if(angle > 3600) angle -= 3600; 695 696 scale_center.x -= indic->type_data.needle_img.pivot.x; 697 scale_center.y -= indic->type_data.needle_img.pivot.y; 698 lv_area_t a; 699 _lv_img_buf_get_transformed_area(&a, info.w, info.h, angle, LV_IMG_ZOOM_NONE, &indic->type_data.needle_img.pivot); 700 a.x1 += scale_center.x - 2; 701 a.y1 += scale_center.y - 2; 702 a.x2 += scale_center.x + 2; 703 a.y2 += scale_center.y + 2; 704 705 lv_obj_invalidate_area(obj, &a); 706 } 707 } 708 #endif