1422 lines
41 KiB
C
1422 lines
41 KiB
C
#include "ui/ui_draw_arc.h"
|
|
#include "ui/lcd_spi/lcd_drive.h"
|
|
#include "ui/text_matrix.h"
|
|
#include "app_config.h"
|
|
void draw_rectangle(const area_t *coords, const area_t *clip, const draw_rect_dsc_t *dsc);
|
|
|
|
|
|
#if 0
|
|
color_t *disp_get_buffer_addr();
|
|
u16 disp_get_buffer_size();
|
|
u16 disp_get_buffer_line(u16 width);
|
|
void disp_set_buffer_rect(struct rect *rect);
|
|
void disp_get_buffer_rect(struct rect *rect);
|
|
void disp_buffer_flush(struct rect *rect, color_t *buffer);
|
|
void disp_buffer_clear(struct rect *rect, color_t color);
|
|
void *_mem_buf_get(int size);
|
|
void _mem_buf_release(void *buf);
|
|
#else
|
|
|
|
struct disp_param {
|
|
struct lcd_interface *lcd;
|
|
color_t *disp_buffer;
|
|
color_t *disp_buffer_0;
|
|
color_t *disp_buffer_1;
|
|
u16 pixel_len;
|
|
u8 *buf;
|
|
u32 len;
|
|
struct rect disp_rect;
|
|
color_t *line_buffer;
|
|
struct lcd_info info;
|
|
};
|
|
|
|
struct text_matrix_info {
|
|
int font_w;
|
|
int font_h;
|
|
u8 *pixel;
|
|
};
|
|
|
|
static struct disp_param param_t = {0};
|
|
#define __this (¶m_t)
|
|
|
|
/* disp_lcd_init(&ui_cfg_data); */
|
|
AT_UI_SIM_RAM
|
|
void disp_lcd_init(void *p)
|
|
{
|
|
|
|
__this->lcd = lcd_get_hdl();
|
|
|
|
if (__this->lcd->init) {
|
|
__this->lcd->init(p);
|
|
}
|
|
|
|
if (__this->lcd->backlight_ctrl) {
|
|
__this->lcd->backlight_ctrl(true);
|
|
}
|
|
|
|
|
|
if (__this->lcd->get_screen_info) {
|
|
__this->lcd->get_screen_info(&__this->info);
|
|
}
|
|
|
|
if (__this->lcd->buffer_malloc) {
|
|
__this->lcd->buffer_malloc(&__this->buf, &__this->len);
|
|
__this->disp_buffer = (color_t *)__this->buf;
|
|
__this->pixel_len = (__this->len / 4 * 4) / sizeof(color_t) / 2;
|
|
__this->disp_buffer_0 = __this->disp_buffer;
|
|
__this->disp_buffer_1 = &__this->disp_buffer[__this->len];
|
|
}
|
|
}
|
|
|
|
void ui_buffer_init(u8 *buf, u32 len)
|
|
{
|
|
|
|
__this->lcd = lcd_get_hdl();
|
|
|
|
__this->buf = buf;
|
|
__this->len = len;
|
|
__this->disp_buffer = (color_t *)__this->buf;
|
|
__this->pixel_len = (__this->len / 4 * 4) / sizeof(color_t) / 2;
|
|
__this->disp_buffer_0 = __this->disp_buffer;
|
|
__this->disp_buffer_1 = &__this->disp_buffer[__this->pixel_len];
|
|
|
|
/* printf("buffer : 0x%x, 0x%x, 0x%x\n", __this->disp_buffer, __this->disp_buffer_0, __this->disp_buffer_1); */
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
color_t *disp_get_buffer_addr()
|
|
{
|
|
return __this->disp_buffer;
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
u16 disp_get_buffer_size()
|
|
{
|
|
return __this->pixel_len;
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
u16 disp_get_buffer_line(u16 width)
|
|
{
|
|
return __this->pixel_len / width;
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
void disp_set_buffer_rect(struct rect *rect)
|
|
{
|
|
if (__this->disp_buffer == __this->disp_buffer_0) {
|
|
__this->disp_buffer = __this->disp_buffer_1;
|
|
} else {
|
|
__this->disp_buffer = __this->disp_buffer_0;
|
|
}
|
|
|
|
/* printf("buffer : 0x%x, 0x%x, 0x%x\n", __this->disp_buffer, __this->disp_buffer_0, __this->disp_buffer_1); */
|
|
memcpy(&__this->disp_rect, rect, sizeof(struct rect));
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
void disp_get_buffer_rect(struct rect *rect)
|
|
{
|
|
memcpy(rect, &__this->disp_rect, sizeof(struct rect));
|
|
}
|
|
|
|
void lcd_data_copy(u8 type, struct rect *rect, u8 *lcd_buf, int stride, int left, int top, int width, int height, int wait);
|
|
int lcd_qspi_st77903_mode();
|
|
|
|
AT_UI_SIM_RAM
|
|
void disp_buffer_flush(struct rect *rect, color_t *buffer)
|
|
{
|
|
|
|
__this->lcd->set_draw_area(rect->left, rect->left + rect->width - 1, rect->top, rect->top + rect->height - 1);
|
|
__this->lcd->draw((u8 *)buffer, rect->left, rect->left + rect->width - 1, rect->top, rect->top + rect->height - 1);
|
|
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
void disp_buffer_clear(struct rect *rect, u16 color)
|
|
{
|
|
int w;
|
|
int h;
|
|
|
|
if (rect->left < __this->disp_rect.left) {
|
|
rect->left = __this->disp_rect.left;
|
|
}
|
|
if (rect->top < __this->disp_rect.top) {
|
|
rect->top = __this->disp_rect.top;
|
|
}
|
|
if ((rect->left + rect->width) > (__this->disp_rect.left + __this->disp_rect.width)) {
|
|
rect->width = __this->disp_rect.left + __this->disp_rect.width - rect->left;
|
|
}
|
|
if ((rect->top + rect->height) > (__this->disp_rect.top + __this->disp_rect.height)) {
|
|
rect->height = __this->disp_rect.top + __this->disp_rect.height - rect->top;
|
|
}
|
|
|
|
//printf("__this->disp_buffer : 0x%x\n", __this->disp_buffer);
|
|
|
|
for (h = 0; h < rect->height; h++) {
|
|
for (w = 0; w < rect->width; w++) {
|
|
__this->disp_buffer[(rect->top + h - __this->disp_rect.top) * __this->disp_rect.width + (rect->left + w - __this->disp_rect.left)].full = color;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
void *_mem_buf_get(int size)
|
|
{
|
|
static color_t line_buffer[480];
|
|
|
|
if (!__this->line_buffer) {
|
|
__this->line_buffer = line_buffer;
|
|
}
|
|
|
|
/* printf("__this->line_buffer : 0x%x\n", __this->line_buffer); */
|
|
|
|
return __this->line_buffer;
|
|
}
|
|
AT_UI_SIM_RAM
|
|
void _mem_buf_release(void *buf)
|
|
{
|
|
|
|
}
|
|
AT_UI_SIM_RAM
|
|
u16 disp_get_pixel(int x, int y)
|
|
{
|
|
u16 color;
|
|
if ((x < __this->disp_rect.left) ||
|
|
(x > (__this->disp_rect.left + __this->disp_rect.width - 1)) ||
|
|
(y < __this->disp_rect.top) ||
|
|
(y > (__this->disp_rect.top + __this->disp_rect.height - 1))) {
|
|
return 0;
|
|
}
|
|
|
|
color = __this->disp_buffer[(y - __this->disp_rect.top) * __this->disp_rect.width + (x - __this->disp_rect.left)].full;
|
|
return color;
|
|
}
|
|
AT_UI_SIM_RAM
|
|
void disp_set_pixel(int x, int y, u16 color)
|
|
{
|
|
if ((x < __this->disp_rect.left) ||
|
|
(x > (__this->disp_rect.left + __this->disp_rect.width - 1)) ||
|
|
(y < __this->disp_rect.top) ||
|
|
(y > (__this->disp_rect.top + __this->disp_rect.height - 1))) {
|
|
return;
|
|
}
|
|
__this->disp_buffer[(y - __this->disp_rect.top) * __this->disp_rect.width + (x - __this->disp_rect.left)].full = (color >> 8) | (color & 0xff) << 8 ;
|
|
}
|
|
|
|
#endif
|
|
|
|
static void draw_full_border(const area_t *area_inner, const area_t *area_outer, const area_t *clip,
|
|
int radius, color_t color, u8 opa, u8 blend_mode);
|
|
|
|
AT_UI_SIM_RAM
|
|
void draw_rect_dsc_init(draw_rect_dsc_t *dsc)
|
|
{
|
|
_memset_00(dsc, sizeof(draw_rect_dsc_t));
|
|
dsc->border_color.full = COLOR_BLACK;
|
|
dsc->border_opa = OPA_COVER;
|
|
dsc->border_side = BORDER_SIDE_FULL;
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
bool _area_intersect(area_t *res_p, const area_t *a1_p, const area_t *a2_p)
|
|
{
|
|
res_p->x1 = MATH_MAX(a1_p->x1, a2_p->x1);
|
|
res_p->y1 = MATH_MAX(a1_p->y1, a2_p->y1);
|
|
res_p->x2 = MATH_MIN(a1_p->x2, a2_p->x2);
|
|
res_p->y2 = MATH_MIN(a1_p->y2, a2_p->y2);
|
|
|
|
bool union_ok = true;
|
|
if ((res_p->x1 > res_p->x2) || (res_p->y1 > res_p->y2)) {
|
|
union_ok = false;
|
|
}
|
|
|
|
return union_ok;
|
|
}
|
|
|
|
|
|
#if 0
|
|
AT_UI_SIM_RAM
|
|
void blend(u8 *mask_buf, int abs_x, int abs_y, int len, color_t color)
|
|
{
|
|
int i;
|
|
color_t mix_color;
|
|
color_t back_color;
|
|
u16 red, green, blue;
|
|
struct rect draw;
|
|
|
|
#if 0
|
|
for (i = 0; i < len; i++) {
|
|
if (mask_buf[i]) {
|
|
putchar('*');
|
|
} else {
|
|
putchar(' ');
|
|
}
|
|
}
|
|
putchar('\n');
|
|
#endif
|
|
|
|
/* disp_get_buffer_rect(&draw); */
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
u8 alpha = mask_buf[i];
|
|
if (alpha) {
|
|
u16 color_p = disp_get_pixel(abs_x + i, abs_y);
|
|
back_color.full = (color_p >> 8) | (color_p & 0xff) << 8;
|
|
|
|
red = (back_color.ch.red * (255 - alpha) + color.ch.red * alpha) / 255;
|
|
mix_color.ch.red = (red > 0x1f) ? 0x1f : red;
|
|
|
|
green = (back_color.ch.green * (255 - alpha) + color.ch.green * alpha) / 255;
|
|
green = (green > 0x3f) ? 0x3f : green;
|
|
mix_color.ch.green = green;
|
|
|
|
blue = (back_color.ch.blue * (255 - alpha) + color.ch.blue * alpha) / 255;
|
|
mix_color.ch.blue = (blue > 0x1f) ? 0x1f : blue;
|
|
|
|
disp_set_pixel(abs_x + i, abs_y, mix_color.full);
|
|
}
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
static bool get_rect_cover(const struct rect *a, const struct rect *b, struct rect *c);
|
|
|
|
AT_UI_SIM_RAM
|
|
void blend(u8 *mask_buf, int abs_x, int abs_y, int len, color_t color)
|
|
{
|
|
int i;
|
|
u16 red, green, blue;
|
|
u8 alpha;
|
|
u32 alpha2;
|
|
color_t c;
|
|
struct rect rect;
|
|
struct rect draw;
|
|
|
|
rect.left = abs_x;
|
|
rect.top = abs_y;
|
|
rect.width = len;
|
|
rect.height = 1;
|
|
|
|
if (!get_rect_cover(&__this->disp_rect, &rect, &draw)) {
|
|
return;
|
|
}
|
|
|
|
/* printf("%d, %d, %d, %d, %d\n", draw.top, disp_rect.top, draw.left, disp_rect.left, disp_rect.width); */
|
|
|
|
ASSERT(!memcmp(&rect, &draw, sizeof(struct rect)));
|
|
|
|
c.full = (color.full & 0xff) << 8 | (color.full >> 8);
|
|
|
|
//printf("%s c.full:0x%x color.full:0x%x\n",__func__,c.full,color.full);
|
|
|
|
color_t *color_p = &__this->disp_buffer[(draw.top/* abs_y */ - __this->disp_rect.top) * ((__this->disp_rect.width + 1) / 2 * 2) + (draw.left/*abs_x*/ - __this->disp_rect.left)];
|
|
|
|
u8 r, g, b;
|
|
r = color.ch.red ;
|
|
g = color.ch.green ;
|
|
b = color.ch.blue ;
|
|
|
|
for (i = 0; i < draw.width/* len */; i++) {
|
|
alpha = mask_buf[i];
|
|
alpha2 = (256 - alpha);
|
|
|
|
if (alpha == 0xff) {
|
|
color_p->full = c.full;
|
|
} else if (alpha) {
|
|
color_p->full = (color_p->full & 0xff) << 8 | (color_p->full >> 8);
|
|
|
|
red = (color_p->ch.red * alpha2 + r * alpha) >> 8;
|
|
green = (color_p->ch.green * alpha2 + g * alpha) >> 8;
|
|
blue = (color_p->ch.blue * alpha2 + b * alpha) >> 8;
|
|
|
|
color_p->full = (green >> 3) | (red << 3) | (blue << 8) | ((green & 0x7) << 13);
|
|
}
|
|
color_p ++;
|
|
}
|
|
}
|
|
|
|
|
|
AT_UI_SIM_RAM
|
|
static void draw_full_border(const area_t *area_inner, const area_t *area_outer, const area_t *clip,
|
|
int radius, color_t color, u8 opa, u8 blend_mode)
|
|
{
|
|
u8 other_mask_cnt = mask_get_cnt();
|
|
bool simple_mode = true;
|
|
if (other_mask_cnt) {
|
|
simple_mode = false;
|
|
}
|
|
|
|
int inner_w = area_get_width(area_inner);
|
|
int inner_h = area_get_height(area_inner);
|
|
int border_width = area_outer->x2 - area_inner->x2;
|
|
int rin = radius;
|
|
|
|
int short_side = MATH_MIN(inner_w, inner_h);
|
|
if (rin > short_side >> 1) {
|
|
rin = short_side >> 1;
|
|
}
|
|
|
|
int rout = rin + border_width;
|
|
|
|
int coords_out_w = area_get_width(area_outer);
|
|
int coords_out_h = area_get_height(area_outer);
|
|
short_side = MATH_MIN(coords_out_w, coords_out_h);
|
|
if (rout > short_side >> 1) {
|
|
rout = short_side >> 1;
|
|
}
|
|
|
|
area_t draw_area;
|
|
bool is_common;
|
|
is_common = _area_intersect(&draw_area, area_outer, clip);//判断刷新区域是否与外圆相交
|
|
if (is_common == false) {
|
|
return;
|
|
}
|
|
|
|
int draw_area_w = area_get_width(&draw_area);
|
|
|
|
mask_radius_param_t mask_rin_param;
|
|
mask_radius_init(&mask_rin_param, area_inner, rin, true);//内圆
|
|
int mask_rin_id = mask_add(&mask_rin_param, NULL);
|
|
|
|
mask_radius_param_t mask_rout_param;
|
|
mask_radius_init(&mask_rout_param, area_outer, rout, false);//外圆
|
|
int mask_rout_id = mask_add(&mask_rout_param, NULL);
|
|
|
|
u8 *mask_buf = _mem_buf_get(draw_area_w);
|
|
|
|
int corner_size = MATH_MAX(rout, border_width - 1);
|
|
|
|
int h;
|
|
u8 mask_res;
|
|
|
|
if (0/* simple_mode */) {
|
|
int upper_corner_end = area_outer->y1 + corner_size;
|
|
for (h = draw_area.y1; h <= upper_corner_end; h++) {
|
|
_memset_ff(mask_buf, draw_area_w);
|
|
mask_res = mask_apply(mask_buf, draw_area.x1, h, draw_area_w);
|
|
blend(mask_buf, draw_area.x1, h, draw_area_w, color);
|
|
}
|
|
|
|
int lower_corner_end = area_outer->y2 - corner_size;
|
|
if (lower_corner_end <= upper_corner_end) {
|
|
lower_corner_end = upper_corner_end + 1;
|
|
}
|
|
|
|
for (h = lower_corner_end; h <= draw_area.y2; h++) {
|
|
_memset_ff(mask_buf, draw_area_w);
|
|
mask_res = mask_apply(mask_buf, draw_area.x1, h, draw_area_w);
|
|
blend(mask_buf, draw_area.x1, h, draw_area_w, color);
|
|
}
|
|
} else {
|
|
for (h = draw_area.y1; h <= draw_area.y2; h++) {
|
|
_memset_ff(mask_buf, draw_area_w);
|
|
mask_res = mask_apply(mask_buf, draw_area.x1, h, draw_area_w);
|
|
blend(mask_buf, draw_area.x1, h, draw_area_w, color);
|
|
}
|
|
}
|
|
|
|
mask_remove_id(mask_rin_id);
|
|
mask_remove_id(mask_rout_id);
|
|
_mem_buf_release(mask_buf);
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
static void draw_quarter_0(quarter_draw_dsc_t *q)
|
|
{
|
|
area_t quarter_area;
|
|
|
|
if (q->start_quarter == 0 && q->end_quarter == 0 && q->start_angle < q->end_angle) {
|
|
quarter_area.y1 = q->center_y + ((_trigo_sin(q->start_angle) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
quarter_area.x2 = q->center_x + ((_trigo_sin(q->start_angle + 90) * (q->radius)) >> TRIGO_SHIFT);
|
|
|
|
quarter_area.y2 = q->center_y + ((_trigo_sin(q->end_angle) * q->radius) >> TRIGO_SHIFT);
|
|
quarter_area.x1 = q->center_x + ((_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
} else if (q->start_quarter == 0 || q->end_quarter == 0) {
|
|
if (q->start_quarter == 0) {
|
|
quarter_area.x1 = q->center_x;
|
|
quarter_area.y2 = q->center_y + q->radius;
|
|
|
|
quarter_area.y1 = q->center_y + ((_trigo_sin(q->start_angle) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
quarter_area.x2 = q->center_x + ((_trigo_sin(q->start_angle + 90) * (q->radius)) >> TRIGO_SHIFT);
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
}
|
|
if (q->end_quarter == 0) {
|
|
quarter_area.x2 = q->center_x + q->radius;
|
|
quarter_area.y1 = q->center_y;
|
|
|
|
quarter_area.y2 = q->center_y + ((_trigo_sin(q->end_angle) * q->radius) >> TRIGO_SHIFT);
|
|
quarter_area.x1 = q->center_x + ((_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
}
|
|
} else if ((q->start_quarter == q->end_quarter && q->start_quarter != 0 && q->end_angle < q->start_angle) ||
|
|
(q->start_quarter == 2 && q->end_quarter == 1) ||
|
|
(q->start_quarter == 3 && q->end_quarter == 2) ||
|
|
(q->start_quarter == 3 && q->end_quarter == 1)) {
|
|
quarter_area.x1 = q->center_x;
|
|
quarter_area.y1 = q->center_y;
|
|
quarter_area.x2 = q->center_x + q->radius;
|
|
quarter_area.y2 = q->center_y + q->radius;
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
}
|
|
}
|
|
AT_UI_SIM_RAM
|
|
static void draw_quarter_1(quarter_draw_dsc_t *q)
|
|
{
|
|
area_t quarter_area;
|
|
|
|
if (q->start_quarter == 1 && q->end_quarter == 1 && q->start_angle < q->end_angle) {
|
|
quarter_area.y2 = q->center_y + ((_trigo_sin(q->start_angle) * (q->radius)) >> TRIGO_SHIFT);
|
|
quarter_area.x2 = q->center_x + ((_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
|
|
quarter_area.y1 = q->center_y + ((_trigo_sin(q->end_angle) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
quarter_area.x1 = q->center_x + ((_trigo_sin(q->end_angle + 90) * (q->radius)) >> TRIGO_SHIFT);
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
} else if (q->start_quarter == 1 || q->end_quarter == 1) {
|
|
if (q->start_quarter == 1) {
|
|
quarter_area.x1 = q->center_x - q->radius;
|
|
quarter_area.y1 = q->center_y;
|
|
|
|
quarter_area.y2 = q->center_y + ((_trigo_sin(q->start_angle) * (q->radius)) >> TRIGO_SHIFT);
|
|
quarter_area.x2 = q->center_x + ((_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
}
|
|
if (q->end_quarter == 1) {
|
|
quarter_area.x2 = q->center_x - 1;
|
|
quarter_area.y2 = q->center_y + q->radius;
|
|
|
|
quarter_area.y1 = q->center_y + ((_trigo_sin(q->end_angle) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
quarter_area.x1 = q->center_x + ((_trigo_sin(q->end_angle + 90) * (q->radius)) >> TRIGO_SHIFT);
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
}
|
|
} else if ((q->start_quarter == q->end_quarter && q->start_quarter != 1 && q->end_angle < q->start_angle) ||
|
|
(q->start_quarter == 0 && q->end_quarter == 2) ||
|
|
(q->start_quarter == 0 && q->end_quarter == 3) ||
|
|
(q->start_quarter == 3 && q->end_quarter == 2)) {
|
|
quarter_area.x1 = q->center_x - q->radius;
|
|
quarter_area.y1 = q->center_y;
|
|
quarter_area.x2 = q->center_x - 1;
|
|
quarter_area.y2 = q->center_y + q->radius;
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
}
|
|
}
|
|
AT_UI_SIM_RAM
|
|
static void draw_quarter_2(quarter_draw_dsc_t *q)
|
|
{
|
|
area_t quarter_area;
|
|
|
|
if (q->start_quarter == 2 && q->end_quarter == 2 && q->start_angle < q->end_angle) {
|
|
quarter_area.x1 = q->center_x + ((_trigo_sin(q->start_angle + 90) * (q->radius)) >> TRIGO_SHIFT);
|
|
quarter_area.y2 = q->center_y + ((_trigo_sin(q->start_angle) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
|
|
quarter_area.y1 = q->center_y + ((_trigo_sin(q->end_angle) * q->radius) >> TRIGO_SHIFT);
|
|
quarter_area.x2 = q->center_x + ((_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
} else if (q->start_quarter == 2 || q->end_quarter == 2) {
|
|
if (q->start_quarter == 2) {
|
|
quarter_area.x2 = q->center_x - 1;
|
|
quarter_area.y1 = q->center_y - q->radius;
|
|
|
|
quarter_area.x1 = q->center_x + ((_trigo_sin(q->start_angle + 90) * (q->radius)) >> TRIGO_SHIFT);
|
|
quarter_area.y2 = q->center_y + ((_trigo_sin(q->start_angle) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
}
|
|
if (q->end_quarter == 2) {
|
|
quarter_area.x1 = q->center_x - q->radius;
|
|
quarter_area.y2 = q->center_y - 1;
|
|
|
|
quarter_area.x2 = q->center_x + ((_trigo_sin(q->end_angle + 90) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
quarter_area.y1 = q->center_y + ((_trigo_sin(q->end_angle) * (q->radius)) >> TRIGO_SHIFT);
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
}
|
|
} else if ((q->start_quarter == q->end_quarter && q->start_quarter != 2 && q->end_angle < q->start_angle) ||
|
|
(q->start_quarter == 0 && q->end_quarter == 3) ||
|
|
(q->start_quarter == 1 && q->end_quarter == 3) ||
|
|
(q->start_quarter == 1 && q->end_quarter == 0)) {
|
|
quarter_area.x1 = q->center_x - q->radius;
|
|
quarter_area.y1 = q->center_y - q->radius;
|
|
quarter_area.x2 = q->center_x - 1;
|
|
quarter_area.y2 = q->center_y - 1;
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
}
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
static void draw_quarter_3(quarter_draw_dsc_t *q)
|
|
{
|
|
area_t quarter_area;
|
|
|
|
if (q->start_quarter == 3 && q->end_quarter == 3 && q->start_angle < q->end_angle) {
|
|
quarter_area.x1 = q->center_x + ((_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
quarter_area.y1 = q->center_y + ((_trigo_sin(q->start_angle) * (q->radius)) >> TRIGO_SHIFT);
|
|
|
|
quarter_area.x2 = q->center_x + ((_trigo_sin(q->end_angle + 90) * (q->radius)) >> TRIGO_SHIFT);
|
|
quarter_area.y2 = q->center_y + ((_trigo_sin(q->end_angle) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
} else if (q->start_quarter == 3 || q->end_quarter == 3) {
|
|
if (q->start_quarter == 3) {
|
|
quarter_area.x2 = q->center_x + q->radius;
|
|
quarter_area.y2 = q->center_y - 1;
|
|
|
|
quarter_area.x1 = q->center_x + ((_trigo_sin(q->start_angle + 90) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
quarter_area.y1 = q->center_y + ((_trigo_sin(q->start_angle) * (q->radius)) >> TRIGO_SHIFT);
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
}
|
|
if (q->end_quarter == 3) {
|
|
quarter_area.x1 = q->center_x;
|
|
quarter_area.y1 = q->center_y - q->radius;
|
|
|
|
quarter_area.x2 = q->center_x + ((_trigo_sin(q->end_angle + 90) * (q->radius)) >> TRIGO_SHIFT);
|
|
quarter_area.y2 = q->center_y + ((_trigo_sin(q->end_angle) * (q->radius - q->width)) >> TRIGO_SHIFT);
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
}
|
|
} else if ((q->start_quarter == q->end_quarter && q->start_quarter != 3 && q->end_angle < q->start_angle) ||
|
|
(q->start_quarter == 2 && q->end_quarter == 0) ||
|
|
(q->start_quarter == 1 && q->end_quarter == 0) ||
|
|
(q->start_quarter == 2 && q->end_quarter == 1)) {
|
|
quarter_area.x1 = q->center_x;
|
|
quarter_area.y1 = q->center_y - q->radius;
|
|
quarter_area.x2 = q->center_x + q->radius;
|
|
quarter_area.y2 = q->center_y - 1;
|
|
|
|
bool ok = _area_intersect(&quarter_area, &quarter_area, q->clip_area);
|
|
if (ok) {
|
|
draw_rectangle(q->draw_area, &quarter_area, q->draw_dsc);
|
|
}
|
|
}
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
static void get_rounded_area(int angle, int radius, u8 tickness, area_t *res_area)
|
|
{
|
|
const u8 ps = 8;
|
|
const u8 pa = 127;
|
|
|
|
int thick_half = tickness / 2;
|
|
u8 thick_corr = (tickness & 0x01) ? 0 : 1;
|
|
|
|
int rx_corr;
|
|
int ry_corr;
|
|
|
|
if (angle > 90 && angle < 270) {
|
|
rx_corr = 0;
|
|
} else {
|
|
rx_corr = 0;
|
|
}
|
|
|
|
if (angle > 0 && angle < 180) {
|
|
ry_corr = 0;
|
|
} else {
|
|
ry_corr = 0;
|
|
}
|
|
|
|
int cir_x;
|
|
int cir_y;
|
|
|
|
cir_x = ((radius - rx_corr - thick_half) * _trigo_sin(90 - angle)) >> (TRIGO_SHIFT - ps);
|
|
cir_y = ((radius - ry_corr - thick_half) * _trigo_sin(angle)) >> (TRIGO_SHIFT - ps);
|
|
|
|
if (cir_x > 0) {
|
|
cir_x = (cir_x - pa) >> ps;
|
|
res_area->x1 = cir_x - thick_half + thick_corr;
|
|
res_area->x2 = cir_x + thick_half;
|
|
} else {
|
|
cir_x = (cir_x + pa) >> ps;
|
|
res_area->x1 = cir_x - thick_half;
|
|
res_area->x2 = cir_x + thick_half - thick_corr;
|
|
}
|
|
|
|
if (cir_y > 0) {
|
|
cir_y = (cir_y - pa) >> ps;
|
|
res_area->y1 = cir_y - thick_half + thick_corr;
|
|
res_area->y2 = cir_y + thick_half;
|
|
} else {
|
|
cir_y = (cir_y + pa) >> ps;
|
|
res_area->y1 = cir_y - thick_half;
|
|
res_area->y2 = cir_y + thick_half - thick_corr;
|
|
}
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
void draw_spec_arc(int center_x, int center_y, u16 radius, u16 start_angle, u16 end_angle,
|
|
const area_t *clip_area, const draw_line_dsc_t *dsc)
|
|
{
|
|
if (dsc->opa <= OPA_MIN) {
|
|
return;
|
|
}
|
|
if (dsc->width == 0) {
|
|
return;
|
|
}
|
|
if (start_angle == end_angle) {
|
|
return;
|
|
}
|
|
|
|
int width = dsc->width;
|
|
if (width > radius) {
|
|
width = radius;
|
|
}
|
|
|
|
draw_rect_dsc_t cir_dsc;
|
|
draw_rect_dsc_init(&cir_dsc);
|
|
cir_dsc.radius = RADIUS_CIRCLE;
|
|
cir_dsc.bg_opa = OPA_TRANSP;
|
|
cir_dsc.border_opa = dsc->opa;
|
|
cir_dsc.border_color = dsc->color;
|
|
cir_dsc.border_width = width;
|
|
|
|
area_t area;
|
|
area.x1 = center_x - radius;
|
|
area.y1 = center_y - radius;
|
|
area.x2 = center_x + radius - 1;
|
|
area.y2 = center_y + radius - 1;
|
|
|
|
if (start_angle + 360 == end_angle || start_angle == end_angle + 360) {
|
|
draw_rectangle(&area, clip_area, &cir_dsc);
|
|
return;
|
|
}
|
|
|
|
if (start_angle >= 360) {
|
|
start_angle -= 360;
|
|
}
|
|
if (end_angle >= 360) {
|
|
end_angle -= 360;
|
|
}
|
|
|
|
mask_angle_param_t mask_angle_param;
|
|
mask_angle_init(&mask_angle_param, center_x, center_y, start_angle, end_angle);
|
|
|
|
int mask_angle_id = mask_add(&mask_angle_param, NULL);
|
|
|
|
int angle_gap;
|
|
if (end_angle > start_angle) {
|
|
angle_gap = 360 - (end_angle - start_angle);
|
|
} else {
|
|
angle_gap = start_angle - end_angle;
|
|
}
|
|
if (angle_gap > SPLIT_ANGLE_GAP_LIMIT && radius > SPLIT_RADIUS_LIMIT) {
|
|
quarter_draw_dsc_t q_dsc;
|
|
q_dsc.center_x = center_x;
|
|
q_dsc.center_y = center_y;
|
|
q_dsc.radius = radius;
|
|
q_dsc.start_angle = start_angle;
|
|
q_dsc.end_angle = end_angle;
|
|
q_dsc.start_quarter = (start_angle / 90) & 0x3;
|
|
q_dsc.end_quarter = (end_angle / 90) & 0x3;
|
|
q_dsc.width = width;
|
|
q_dsc.draw_dsc = &cir_dsc;
|
|
q_dsc.draw_area = &area;
|
|
q_dsc.clip_area = clip_area;
|
|
|
|
draw_quarter_0(&q_dsc);
|
|
draw_quarter_1(&q_dsc);
|
|
draw_quarter_2(&q_dsc);
|
|
draw_quarter_3(&q_dsc);
|
|
} else {
|
|
draw_rectangle(&area, clip_area, &cir_dsc);
|
|
}
|
|
mask_remove_id(mask_angle_id);
|
|
|
|
if (dsc->round_start || dsc->round_end) {
|
|
draw_rect_dsc_t cir_dsc_backup;
|
|
_memcpy_small(&cir_dsc_backup, &cir_dsc, sizeof(draw_rect_dsc_t));
|
|
|
|
cir_dsc_backup.bg_color = dsc->color;
|
|
cir_dsc_backup.bg_opa = dsc->opa;
|
|
cir_dsc_backup.border_width = 0;
|
|
|
|
area_t round_area;
|
|
if (dsc->round_start) {
|
|
get_rounded_area(start_angle, radius, width, &round_area);
|
|
round_area.x1 += center_x;
|
|
round_area.x2 += center_x;
|
|
round_area.y1 += center_y;
|
|
round_area.y2 += center_y;
|
|
|
|
draw_rectangle(&round_area, clip_area, &cir_dsc_backup);
|
|
}
|
|
|
|
if (dsc->round_end) {
|
|
get_rounded_area(end_angle, radius, width, &round_area);
|
|
round_area.x1 += center_x;
|
|
round_area.x2 += center_x;
|
|
round_area.y1 += center_y;
|
|
round_area.y2 += center_y;
|
|
|
|
draw_rectangle(&round_area, clip_area, &cir_dsc_backup);
|
|
}
|
|
}
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
static void draw_border(const area_t *coords, const area_t *clip,
|
|
const draw_rect_dsc_t *dsc)
|
|
{
|
|
if (dsc->border_opa <= OPA_MIN) {
|
|
return;
|
|
}
|
|
if (dsc->border_width == 0) {
|
|
return;
|
|
}
|
|
if (dsc->border_side == BORDER_SIDE_NONE) {
|
|
return;
|
|
}
|
|
|
|
int coords_w = area_get_width(coords);
|
|
int coords_h = area_get_height(coords);
|
|
|
|
/* printf("dsc : 0x%x\n", dsc); */
|
|
/* printf("dsc->radius : %d\n", dsc->radius); */
|
|
int rout = dsc->radius;
|
|
int short_side = MATH_MIN(coords_w, coords_h);
|
|
if (rout > short_side >> 1) {
|
|
rout = short_side >> 1;
|
|
}
|
|
area_t area_inner;
|
|
area_copy(&area_inner, coords);
|
|
area_inner.x1 += ((dsc->border_side & BORDER_SIDE_LEFT) ? dsc->border_width : - (dsc->border_width + rout));
|
|
area_inner.x2 -= ((dsc->border_side & BORDER_SIDE_RIGHT) ? dsc->border_width : - (dsc->border_width + rout));
|
|
area_inner.y1 += ((dsc->border_side & BORDER_SIDE_TOP) ? dsc->border_width : - (dsc->border_width + rout));
|
|
area_inner.y2 -= ((dsc->border_side & BORDER_SIDE_BOTTOM) ? dsc->border_width : - (dsc->border_width + rout));
|
|
if (dsc->border_side == BORDER_SIDE_FULL) {
|
|
draw_full_border(&area_inner, coords, clip, dsc->radius, dsc->border_color, dsc->border_opa, 0);
|
|
} else {
|
|
u8 opa = dsc->border_opa;
|
|
if (opa > OPA_MAX) {
|
|
opa = OPA_COVER;
|
|
}
|
|
|
|
area_t draw_area;
|
|
bool is_common;
|
|
is_common = _area_intersect(&draw_area, coords, clip);
|
|
if (is_common == false) {
|
|
return;
|
|
}
|
|
|
|
int draw_area_w = area_get_width(&draw_area);
|
|
|
|
u8 *mask_buf = _mem_buf_get(draw_area_w);
|
|
|
|
int mask_rout_id = MASK_ID_INV;
|
|
mask_radius_param_t mask_rout_param;
|
|
if (rout > 0) {
|
|
mask_radius_init(&mask_rout_param, coords, rout, false);
|
|
mask_rout_id = mask_add(&mask_rout_param, NULL);
|
|
}
|
|
|
|
int rin = rout - dsc->border_width;
|
|
if (rin < 0) {
|
|
rin = 0;
|
|
}
|
|
mask_radius_param_t mask_rin_param;
|
|
mask_radius_init(&mask_rin_param, &area_inner, rout - dsc->border_width, true);
|
|
int mask_rin_id = mask_add(&mask_rin_param, NULL);
|
|
|
|
int corner_size = MATH_MAX(rout, dsc->border_width - 1);
|
|
|
|
int h;
|
|
area_t fill_area;
|
|
|
|
fill_area.x1 = coords->x1;
|
|
fill_area.x2 = coords->x2;
|
|
fill_area.y1 = draw_area.y1;
|
|
fill_area.y2 = fill_area.y1;
|
|
|
|
u32 buf_ofs = 0;
|
|
if (dsc->border_side == BORDER_SIDE_LEFT) {
|
|
fill_area.x2 = coords->x1 + corner_size;
|
|
} else if (dsc->border_side == BORDER_SIDE_RIGHT) {
|
|
fill_area.x1 = coords->x2 - corner_size;
|
|
buf_ofs = fill_area.x1 - coords->x1;
|
|
}
|
|
|
|
volatile bool top_only = false;
|
|
volatile bool bottom_only = false;
|
|
if (dsc->border_side == BORDER_SIDE_TOP) {
|
|
top_only = true;
|
|
}
|
|
if (dsc->border_side == BORDER_SIDE_BOTTOM) {
|
|
bottom_only = true;
|
|
}
|
|
if (dsc->border_side == (BORDER_SIDE_TOP | BORDER_SIDE_BOTTOM)) {
|
|
top_only = true;
|
|
bottom_only = true;
|
|
}
|
|
|
|
volatile bool normal = !top_only && !bottom_only ? true : false;
|
|
|
|
for (h = draw_area.y1; h <= draw_area.y2; h++) {
|
|
if (normal ||
|
|
(top_only && fill_area.y1 <= coords->y1 + corner_size) ||
|
|
(bottom_only && fill_area.y1 >= coords->y2 - corner_size)) {
|
|
_memset_ff(mask_buf, draw_area_w);
|
|
u8 mask_res = mask_apply(mask_buf, draw_area.x1, h, draw_area_w);
|
|
blend(mask_buf, draw_area.x1, h, draw_area_w, dsc->bg_color);
|
|
}
|
|
fill_area.y1++;
|
|
fill_area.y2++;
|
|
|
|
}
|
|
mask_remove_id(mask_rin_id);
|
|
mask_remove_id(mask_rout_id);
|
|
_mem_buf_release(mask_buf);
|
|
}
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
static void draw_bg(const area_t *coords, const area_t *clip,
|
|
const draw_rect_dsc_t *dsc)
|
|
{
|
|
|
|
if (dsc->bg_opa <= OPA_MIN) {
|
|
return;
|
|
}
|
|
|
|
area_t coords_bg;
|
|
area_copy(&coords_bg, coords);
|
|
|
|
|
|
u8 opa = dsc->bg_opa;
|
|
if (opa > OPA_MAX) {
|
|
opa = OPA_COVER;
|
|
}
|
|
|
|
area_t draw_area;
|
|
bool is_common;
|
|
is_common = _area_intersect(&draw_area, &coords_bg, clip);
|
|
if (is_common == false) {
|
|
return;
|
|
}
|
|
|
|
int draw_area_w = area_get_width(&draw_area);
|
|
|
|
u8 *mask_buf = _mem_buf_get(draw_area_w);
|
|
|
|
u16 other_mask_cnt = mask_get_cnt();
|
|
bool simple_mode = true;
|
|
if (other_mask_cnt) {
|
|
simple_mode = false;
|
|
}
|
|
|
|
int mask_rout_id = MASK_ID_INV;
|
|
int coords_w = area_get_width(&coords_bg);
|
|
int coords_h = area_get_height(&coords_bg);
|
|
|
|
int rout = dsc->radius;
|
|
int short_side = MATH_MIN(coords_w, coords_h);
|
|
if (rout > short_side >> 1) {
|
|
rout = short_side >> 1;
|
|
}
|
|
|
|
mask_radius_param_t mask_rout_param;
|
|
if (rout > 0) {
|
|
mask_radius_init(&mask_rout_param, &coords_bg, rout, false);
|
|
mask_rout_id = mask_add(&mask_rout_param, NULL);
|
|
}
|
|
|
|
int h;
|
|
u8 mask_res = MASK_RES_FULL_COVER;
|
|
for (h = draw_area.y1; h <= draw_area.y2; h++) {
|
|
_memset(mask_buf, opa, draw_area_w);
|
|
mask_res = mask_apply(mask_buf, draw_area.x1, h, draw_area_w);
|
|
blend(mask_buf, draw_area.x1, h, draw_area_w, dsc->bg_color);
|
|
}
|
|
|
|
mask_remove_id(mask_rout_id);
|
|
_mem_buf_release(mask_buf);
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
void draw_rectangle(const area_t *coords, const area_t *clip, const draw_rect_dsc_t *dsc)
|
|
{
|
|
if (dsc->border_width == 0) {
|
|
draw_bg(coords, clip, dsc);
|
|
} else {
|
|
draw_border(coords, clip, dsc); \
|
|
}
|
|
}
|
|
|
|
|
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
|
|
#define rect_left(r) ((r)->left)
|
|
#define rect_top(r) ((r)->top)
|
|
#define rect_right(r) ((r)->left + (r)->width)
|
|
#define rect_bottom(r) ((r)->top + (r)->height)
|
|
|
|
AT_UI_SIM_RAM
|
|
static bool get_rect_cover(const struct rect *a, const struct rect *b, struct rect *c)
|
|
{
|
|
int right, bottom;
|
|
|
|
c->top = MAX(a->top, b->top);
|
|
c->left = MAX(a->left, b->left);
|
|
right = MIN(rect_right(a), rect_right(b));
|
|
bottom = MIN(rect_bottom(a), rect_bottom(b));
|
|
if ((c->top < bottom) && (c->left < right)) {
|
|
c->width = right - c->left;
|
|
c->height = bottom - c->top;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
AT_UI_SIM_RAM
|
|
int get_text_matrix_info(struct text_matrix_info *info, u16 code)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < sizeof(text_matrix) / sizeof(text_matrix[0]); i++) {
|
|
if (code == text_matrix[i].code) {
|
|
info->font_w = text_matrix[i].width;
|
|
info->font_h = text_matrix[i].height;
|
|
info->pixel = &osd_str_matrix[text_matrix[i].offset];
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
AT_UI_SIM_RAM
|
|
int get_text_matrix_width(u16 code)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < sizeof(text_matrix) / sizeof(text_matrix[0]); i++) {
|
|
if (code == text_matrix[i].code) {
|
|
return text_matrix[i].width;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
AT_UI_SIM_RAM
|
|
int get_text_matrix_height(u16 code)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < sizeof(text_matrix) / sizeof(text_matrix[0]); i++) {
|
|
if (code == text_matrix[i].code) {
|
|
return text_matrix[i].height;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
AT_UI_SIM_RAM
|
|
void draw_text(struct rect *draw, int x, int y, u8 *str, int strlen, u16 color)
|
|
{
|
|
struct rect cover;
|
|
struct rect font_rect;
|
|
struct text_matrix_info info;
|
|
u8 *pixel;
|
|
int w;
|
|
int h;
|
|
int n;
|
|
u16 text;
|
|
|
|
font_rect.left = x;
|
|
font_rect.top = y;
|
|
|
|
for (n = 0; n < strlen;) {
|
|
if (str[n] & BIT(7)) {
|
|
text = (u16)(str[n] << 8) | str[n + 1];
|
|
n += 2;
|
|
} else {
|
|
text = str[n];
|
|
n++;
|
|
}
|
|
|
|
if (get_text_matrix_info(&info, text)) {
|
|
continue;
|
|
}
|
|
font_rect.width = info.font_w;
|
|
font_rect.height = info.font_h;
|
|
pixel = info.pixel;
|
|
|
|
if (get_rect_cover(draw, &font_rect, &cover)) {
|
|
for (h = 0; h < cover.height; h++) {
|
|
for (w = 0; w < cover.width; w++) {
|
|
int x = cover.left + w - font_rect.left;
|
|
int y = cover.top + h - font_rect.top;
|
|
|
|
if (pixel[y * ((info.font_w + 7) / 8) + x / 8] & BIT(7 - x % 8)) {
|
|
disp_set_pixel(cover.left + w, cover.top + h, color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
font_rect.left += info.font_w;
|
|
}
|
|
}
|
|
|
|
//
|
|
//void put_buf(const u8 *buf, int len)
|
|
//{
|
|
// int i;
|
|
// for (i = 0; i < len; i++) {
|
|
// if (i && (i % 0x10 == 0)) {
|
|
// printf(" \n");
|
|
// }
|
|
// printf("%02x ", buf[i]);
|
|
// }
|
|
// printf(" \n");
|
|
//}
|
|
|
|
void get_text_rect(u8 *str, int len, int *width, int *height)
|
|
{
|
|
int i;
|
|
int w, h;
|
|
int string_w;
|
|
int string_h;
|
|
u16 code;
|
|
//printf("str : %s\n", str);
|
|
//put_buf(str, len);
|
|
|
|
string_w = 0;
|
|
string_h = 0;
|
|
for (i = 0; i < len; i++) {
|
|
if (str[i] & BIT(7)) {
|
|
code = str[i] << 8 | str[i + 1];
|
|
i++;
|
|
} else {
|
|
code = str[i];
|
|
}
|
|
w = get_text_matrix_width(code);
|
|
h = get_text_matrix_height(code);
|
|
string_w += w;
|
|
if (string_h < h) {
|
|
string_h = h;
|
|
}
|
|
//printf("0x%x, %d x %d\n", code, w, h);
|
|
}
|
|
|
|
*width = string_w;
|
|
*height = string_h;
|
|
}
|
|
|
|
|
|
enum FILE_ENCODE {
|
|
FILE_ENCODE_UNKNOWN,
|
|
FILE_ENCODE_GBK,
|
|
FILE_ENCODE_UTF8,
|
|
};
|
|
|
|
static enum FILE_ENCODE file_encoding_detect()
|
|
{
|
|
static const u8 *text_encode_test = "升";
|
|
|
|
if(strlen(text_encode_test) == 3) {
|
|
if((text_encode_test[0] == 0xe5) && (text_encode_test[1] == 0x8d) && (text_encode_test[2] == 0x87)) {
|
|
return FILE_ENCODE_UTF8;
|
|
}
|
|
} else if (strlen(text_encode_test) == 2) {
|
|
if((text_encode_test[0] == 0xc9) && (text_encode_test[1] == 0xfd)) {
|
|
return FILE_ENCODE_GBK;
|
|
}
|
|
} else {
|
|
return FILE_ENCODE_UNKNOWN;
|
|
}
|
|
|
|
return FILE_ENCODE_UNKNOWN;
|
|
}
|
|
|
|
|
|
AT_UI_SIM_RAM
|
|
void draw_ring(int center_x, int center_y, int radius, u16 color, int percent)
|
|
{
|
|
u16 start_angle;
|
|
u16 end_angle;
|
|
area_t clip_area;
|
|
struct rect draw;
|
|
struct rect rect;
|
|
draw_line_dsc_t dsc;
|
|
int i;
|
|
|
|
if (percent < 0) {
|
|
percent += 100;
|
|
}
|
|
if (percent > 100) {
|
|
percent -= 100;
|
|
}
|
|
|
|
dsc.width = 15;
|
|
dsc.opa = 255;
|
|
dsc.round_start = 1;
|
|
dsc.round_end = 1;
|
|
|
|
rect.left = center_x - radius;
|
|
rect.top = center_y - radius;
|
|
rect.width = radius * 2;
|
|
rect.height = radius * 2;
|
|
|
|
memcpy(&draw, &rect, sizeof(struct rect));
|
|
|
|
/* printf("rect (%d, %d, %d, %d)\n", rect.left, rect.left + rect.width - 1, rect.top, rect.top + rect.height - 1); */
|
|
int block = disp_get_buffer_line(rect.width);
|
|
/* printf("block : %d\n", block); */
|
|
for (i = 0; i < (rect.height + block - 1) / block; i++) {
|
|
draw.top = rect.top + block * i;
|
|
draw.height = (rect.top + rect.height - draw.top) > block ? block : (rect.top + rect.height - draw.top);
|
|
|
|
disp_set_buffer_rect(&draw);
|
|
disp_buffer_clear(&draw, 0x0000);
|
|
|
|
clip_area.x1 = draw.left;
|
|
clip_area.x2 = draw.left + draw.width - 1;
|
|
clip_area.y1 = draw.top;
|
|
clip_area.y2 = draw.top + draw.height - 1;
|
|
|
|
/* printf("(%d, %d, %d, %d)\n", clip_area.x1, clip_area.x2, clip_area.y1, clip_area.y2); */
|
|
|
|
start_angle = 270;
|
|
end_angle = 270 + 360;
|
|
dsc.color.ch.red = 160 >> 3;
|
|
dsc.color.ch.green = 160 >> 2;
|
|
dsc.color.ch.blue = 160 >> 3;
|
|
/* dsc.color.full = 43540; */
|
|
draw_spec_arc(center_x, center_y, radius, start_angle, end_angle, &clip_area, &dsc);
|
|
|
|
u16 other_mask_cnt = mask_get_cnt();
|
|
ASSERT(other_mask_cnt == 0);
|
|
start_angle = 270;
|
|
end_angle = 270 + (360) * percent / 100;
|
|
dsc.color.full = color;
|
|
draw_spec_arc(center_x, center_y, radius, start_angle, end_angle, &clip_area, &dsc);
|
|
|
|
enum FILE_ENCODE file_encode = file_encoding_detect();
|
|
ASSERT(file_encode == FILE_ENCODE_GBK, ", file_encode : %d\n", file_encode);
|
|
|
|
const char *text_zh = "升级中...";
|
|
const char *text_zh1 = "请不要断电!";
|
|
const char *text_zh2 = "升级完毕";
|
|
const char *text_zh3 = "机器即将重启";
|
|
const char *text_zh4 = "升级进度:";
|
|
u8 num_buf[32] = {0};
|
|
int text_width = 0;
|
|
int text_height = 0;
|
|
int line_height = 0;
|
|
int interval = 8;
|
|
|
|
memcpy(num_buf, text_zh4, strlen(text_zh4));
|
|
sprintf(&num_buf[strlen(text_zh4)], "%d%%", percent);
|
|
|
|
if (percent < 100) { //升级中
|
|
get_text_rect(text_zh, strlen(text_zh), &text_width, &text_height);
|
|
//printf("%s , %d x %d\n", text_zh, text_width, text_height);
|
|
line_height = text_height + interval;
|
|
draw_text(&draw, rect.left + (rect.width - text_width) / 2, rect.top + (rect.height - line_height * 3) / 2, text_zh, strlen(text_zh), 0xf800);
|
|
|
|
get_text_rect(text_zh1, strlen(text_zh1), &text_width, &text_height);
|
|
//printf("%s , %d x %d\n", text_zh, text_width, text_height);
|
|
line_height = text_height + interval;
|
|
draw_text(&draw, rect.left + (rect.width - text_width) / 2, rect.top + (rect.height - line_height * 3) / 2 + line_height, text_zh1, strlen(text_zh1), 0xf800);
|
|
|
|
get_text_rect(num_buf, strlen(num_buf), &text_width, &text_height);
|
|
//printf("%s , %d x %d\n", num_buf, text_width, text_height);
|
|
line_height = text_height + interval;
|
|
draw_text(&draw, rect.left + (rect.width - text_width) / 2, rect.top + (rect.height - line_height * 3) / 2 + line_height * 2, num_buf, strlen(num_buf), 0x07e0);
|
|
|
|
} else { // 升级完成
|
|
get_text_rect(text_zh2, strlen(text_zh2), &text_width, &text_height);
|
|
//printf("%s , %d x %d\n", text_zh2, text_width, text_height);
|
|
line_height = text_height + interval;
|
|
draw_text(&draw, rect.left + (rect.width - text_width) / 2, rect.top + (rect.height - line_height * 3) / 2, text_zh2, strlen(text_zh2), 0xf800);
|
|
|
|
get_text_rect(text_zh3, strlen(text_zh3), &text_width, &text_height);
|
|
//printf("%s , %d x %d\n", text_zh3, text_width, text_height);
|
|
line_height = text_height + interval;
|
|
draw_text(&draw, rect.left + (rect.width - text_width) / 2, rect.top + (rect.height - line_height * 3) / 2 + line_height, text_zh3, strlen(text_zh3), 0xf800);
|
|
|
|
get_text_rect(num_buf, strlen(num_buf), &text_width, &text_height);
|
|
//printf("%s , %d x %d\n", num_buf, text_width, text_height);
|
|
line_height = text_height + interval;
|
|
draw_text(&draw, rect.left + (rect.width - text_width) / 2, rect.top + (rect.height - line_height * 3) / 2 + line_height * 2, num_buf, strlen(num_buf), 0x07e0);
|
|
}
|
|
|
|
disp_buffer_flush(&draw, disp_get_buffer_addr());
|
|
}
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
void ui_draw_ring(int center_x, int center_y, int radius, u16 color, u16 bg_color,int percent)
|
|
{
|
|
u16 start_angle;
|
|
u16 end_angle;
|
|
area_t clip_area;
|
|
struct rect draw;
|
|
struct rect rect;
|
|
draw_line_dsc_t dsc;
|
|
int i;
|
|
|
|
if (percent < 0) {
|
|
percent += 100;
|
|
}
|
|
if (percent > 100) {
|
|
percent -= 100;
|
|
}
|
|
|
|
dsc.width = 15;
|
|
dsc.opa = 255;
|
|
dsc.round_start = 1;
|
|
dsc.round_end = 1;
|
|
|
|
rect.left = center_x - radius;
|
|
rect.top = center_y - radius;
|
|
rect.width = radius * 2;
|
|
rect.height = radius * 2;
|
|
|
|
memcpy(&draw, &rect, sizeof(struct rect));
|
|
|
|
/* printf("rect (%d, %d, %d, %d)\n", rect.left, rect.left + rect.width - 1, rect.top, rect.top + rect.height - 1); */
|
|
int block = disp_get_buffer_line(rect.width);
|
|
/* printf("block : %d\n", block); */
|
|
for (i = 0; i < (rect.height + block - 1) / block; i++) {
|
|
draw.top = rect.top + block * i;
|
|
draw.height = (rect.top + rect.height - draw.top) > block ? block : (rect.top + rect.height - draw.top);
|
|
|
|
disp_set_buffer_rect(&draw);
|
|
disp_buffer_clear(&draw, 0x0000);
|
|
|
|
clip_area.x1 = draw.left;
|
|
clip_area.x2 = draw.left + draw.width - 1;
|
|
clip_area.y1 = draw.top;
|
|
clip_area.y2 = draw.top + draw.height - 1;
|
|
|
|
/* printf("(%d, %d, %d, %d)\n", clip_area.x1, clip_area.x2, clip_area.y1, clip_area.y2); */
|
|
|
|
start_angle = 270;
|
|
end_angle = 270 + 360;
|
|
dsc.color.ch.red = (bg_color >> 11)&0x1f;
|
|
dsc.color.ch.green = (bg_color >> 5)&0x3f;
|
|
dsc.color.ch.blue = (bg_color & 0x1f);
|
|
/* dsc.color.full = 43540; */
|
|
draw_spec_arc(center_x, center_y, radius, start_angle, end_angle, &clip_area, &dsc);
|
|
|
|
u16 other_mask_cnt = mask_get_cnt();
|
|
ASSERT(other_mask_cnt == 0);
|
|
start_angle = 270;
|
|
end_angle = 270 + (360) * percent / 100;
|
|
dsc.color.full = color;
|
|
draw_spec_arc(center_x, center_y, radius, start_angle, end_angle, &clip_area, &dsc);
|
|
disp_buffer_flush(&draw, disp_get_buffer_addr());
|
|
}
|
|
}
|
|
|
|
AT_UI_SIM_RAM
|
|
void draw_bar(int percent)
|
|
{
|
|
area_t coords = {
|
|
.x1 = 143,
|
|
.y1 = 103,
|
|
.x2 = 336,
|
|
.y2 = 115,
|
|
};
|
|
area_t clip = {
|
|
.x1 = 143,
|
|
.y1 = 103,
|
|
.x2 = 336,
|
|
.y2 = 115,
|
|
};
|
|
draw_rect_dsc_t dsc = {
|
|
.radius = 32767,
|
|
.bg_color = {
|
|
/* .ch = { */
|
|
/* .blue = 27, */
|
|
/* .green = 53, */
|
|
/* .red = 26, */
|
|
/* }, */
|
|
.full = 54971,
|
|
},
|
|
.bg_opa = 255,
|
|
|
|
.border_width = 0,
|
|
.border_side = 15,
|
|
.border_opa = 255,
|
|
};
|
|
|
|
printf("draw bar\n");
|
|
draw_rectangle(&coords, &clip, &dsc);
|
|
|
|
area_t coords_t;
|
|
memcpy(&coords_t, &coords, sizeof(area_t));
|
|
coords_t.x2 = coords.x1 + (coords.x2 - coords.x1 + 1 - (coords.y2 - coords.y1)) * percent / 100 + (coords.y2 - coords.y1) - 1;
|
|
dsc.bg_color.full = 0xf800;
|
|
if (coords_t.x2 > coords.x1) {
|
|
draw_rectangle(&coords_t, &clip, &dsc);
|
|
}
|
|
}
|