diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/lcd-bitmap-common.c | 91 |
1 files changed, 57 insertions, 34 deletions
diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c index 81decadbcb..a102eaea66 100644 --- a/firmware/drivers/lcd-bitmap-common.c +++ b/firmware/drivers/lcd-bitmap-common.c | |||
@@ -447,44 +447,67 @@ void LCDFN(bmp)(const struct bitmap* bm, int x, int y) | |||
447 | void LCDFN(nine_segment_bmp)(const struct bitmap* bm, int x, int y, | 447 | void LCDFN(nine_segment_bmp)(const struct bitmap* bm, int x, int y, |
448 | int width, int height) | 448 | int width, int height) |
449 | { | 449 | { |
450 | int seg_w = bm->width / 3; | 450 | int seg_w, seg_h, src_x, src_y, dst_x, dst_y; |
451 | int seg_h = bm->height / 3; | 451 | /* if the bitmap dimensions are not multiples of 3 bytes reduce the |
452 | int src_x, src_y, dst_x, dst_y; | 452 | * inner segments accordingly. A 8x8 image becomes 3x3 for each |
453 | 453 | * corner, and 2x2 for the inner segments */ | |
454 | /* top */ | 454 | int corner_w = (bm->width + 2) / 3; |
455 | src_x = seg_w; src_y = 0; | 455 | int corner_h = (bm->height + 2) / 3; |
456 | dst_x = seg_w; dst_y = 0; | 456 | seg_w = bm->width - (2 * corner_w); |
457 | for (; dst_x < width - seg_w; dst_x += seg_w) | 457 | seg_h = bm->height - (2 * corner_h); |
458 | LCDFN(bmp_part)(bm, src_x, src_y, dst_x, dst_y, seg_w, seg_h); | 458 | |
459 | /* bottom */ | 459 | /* top & bottom in a single loop*/ |
460 | src_x = seg_w; src_y = bm->height - seg_h; | 460 | src_x = corner_w; |
461 | dst_x = seg_w; dst_y = height - seg_h; | 461 | dst_x = corner_w; |
462 | int src_y_top = 0; | ||
463 | int dst_y_top = 0; | ||
464 | int src_y_btm = bm->height - corner_h; | ||
465 | int dst_y_btm = height - corner_h; | ||
462 | for (; dst_x < width - seg_w; dst_x += seg_w) | 466 | for (; dst_x < width - seg_w; dst_x += seg_w) |
463 | LCDFN(bmp_part)(bm, src_x, src_y, dst_x, dst_y, seg_w, seg_h); | 467 | { |
468 | /* cap the last segment to the remaining width */ | ||
469 | int w = MIN(seg_w, (width - dst_x - seg_w)); | ||
470 | LCDFN(bmp_part)(bm, src_x, src_y_top, dst_x, dst_y_top, w, seg_h); | ||
471 | LCDFN(bmp_part)(bm, src_x, src_y_btm, dst_x, dst_y_btm, w, seg_h); | ||
472 | } | ||
464 | 473 | ||
465 | /* left */ | 474 | /* left & right in a single loop */ |
466 | src_x = 0; src_y = seg_h; | 475 | src_y = corner_h; |
467 | dst_x = 0; dst_y = seg_h; | 476 | dst_y = corner_h; |
468 | for (; dst_y < height - seg_h; dst_y += seg_h) | 477 | int src_x_l = 0; |
469 | LCDFN(bmp_part)(bm, src_x, src_y, dst_x, dst_y, seg_w, seg_h); | 478 | int dst_x_l = 0; |
470 | /* right */ | 479 | int src_x_r = bm->width - corner_w; |
471 | src_x = bm->width - seg_w; src_y = seg_h; | 480 | int dst_x_r = width - corner_w; |
472 | dst_x = width - seg_w; dst_y = seg_h; | ||
473 | for (; dst_y < height - seg_h; dst_y += seg_h) | ||
474 | LCDFN(bmp_part)(bm, src_x, src_y, dst_x, dst_y, seg_w, seg_h); | ||
475 | /* center */ | ||
476 | dst_y = seg_h; src_y = seg_h; src_x = seg_w; | ||
477 | for (; dst_y < height - seg_h; dst_y += seg_h) | 481 | for (; dst_y < height - seg_h; dst_y += seg_h) |
478 | { | 482 | { |
479 | dst_x = seg_w; | 483 | /* cap the last segment to the remaining height */ |
480 | for (; dst_x < width - seg_w; dst_x += seg_w) | 484 | int h = MIN(seg_h, (height - dst_y - seg_h)); |
481 | LCDFN(bmp_part)(bm, src_x, src_y, dst_x, dst_y, seg_w, seg_h); | 485 | LCDFN(bmp_part)(bm, src_x_l, src_y, dst_x_l, dst_y, seg_w, h); |
486 | LCDFN(bmp_part)(bm, src_x_r, src_y, dst_x_r, dst_y, seg_w, h); | ||
487 | } | ||
488 | /* center, need not be drawn if the desired rectangle is smaller than | ||
489 | * the sides. in that case the rect is completely filled already */ | ||
490 | if (width > (2*corner_w) && height > (2*corner_h)) | ||
491 | { | ||
492 | dst_y = src_y = corner_h; | ||
493 | src_x = corner_w; | ||
494 | for (; dst_y < height - seg_h; dst_y += seg_h) | ||
495 | { | ||
496 | /* cap the last segment to the remaining height */ | ||
497 | int h = MIN(seg_h, (height - dst_y - seg_h)); | ||
498 | dst_x = corner_w; | ||
499 | for (; dst_x < width - seg_w; dst_x += seg_w) | ||
500 | { | ||
501 | /* cap the last segment to the remaining width */ | ||
502 | int w = MIN(seg_w, (width - dst_x - seg_w)); | ||
503 | LCDFN(bmp_part)(bm, src_x, src_y, dst_x, dst_y, w, h); | ||
504 | } | ||
505 | } | ||
482 | } | 506 | } |
483 | |||
484 | /* 4 corners */ | 507 | /* 4 corners */ |
485 | LCDFN(bmp_part)(bm, 0, 0, x, y, seg_w, seg_h); | 508 | LCDFN(bmp_part)(bm, 0, 0, x, y, corner_w, corner_h); |
486 | LCDFN(bmp_part)(bm, bm->width - seg_w, 0, width - seg_w, 0, seg_w, seg_h); | 509 | LCDFN(bmp_part)(bm, bm->width - corner_w, 0, width - corner_w, 0, corner_w, corner_h); |
487 | LCDFN(bmp_part)(bm, 0, bm->width - seg_h, 0, height - seg_h, seg_w, seg_h); | 510 | LCDFN(bmp_part)(bm, 0, bm->width - corner_h, 0, height - corner_h, corner_w, corner_h); |
488 | LCDFN(bmp_part)(bm, bm->width - seg_w, bm->width - seg_h, | 511 | LCDFN(bmp_part)(bm, bm->width - corner_w, bm->width - corner_h, |
489 | width - seg_w, height - seg_h, seg_w, seg_h); | 512 | width - corner_w, height - corner_h, corner_w, corner_h); |
490 | } | 513 | } |