项目全部代码:https://github.com/studyalldaya/100ask_project1
按钮button抽象
一个button应该有名字(显示的text)、字体的大小、button的状态、button的region以及两个函数指针分别为画出button和点击之后要做的事。
#define BUTTON_DEFAULT_COLOR 0xff0000
#define BUTTON_CLICKED_COLOR 0x00ff00
#define BUTTON_TEXT_COLOR 0x000000
#define BUTTON_PERCENT_COLOR 0x0000ff
struct Button;
typedef int (*On_draw_ptr)(struct Button *btn, Display_buffer *buffer);
typedef int (*On_clicked_ptr)(struct Button *btn, Display_buffer *buffer, Input_data *inputData);
typedef struct Button {
char *name;
int fontSize;
int status;
Region btn_region;
On_draw_ptr on_draw;
On_clicked_ptr on_clicked;
} Button;
通过init_button函数初始化button的状态,名字,region,以及on_draw 和on_clicked ,如果传入了on_draw和on_clicked参数,函数指针就指向传入的函数,如果没有传入,就指向默认的函数。
void init_button(Button *btn, char *name, Region *region, On_draw_ptr on_draw, On_clicked_ptr on_clicked)
{
btn->status = 0;
btn->name = name;
if (region)
btn->btn_region = *region;
btn->on_draw = on_draw ? on_draw : default_on_draw;
btn->on_clicked = on_clicked ? on_clicked : default_on_clicked;
}
默认on_draw函数
default_on_draw函数绘制button并设置text大小并居中显示。绘制button就根据 btn_region,根据颜色循环点亮像素即可。
static int default_on_draw(struct Button *btn, Display_buffer *buffer)
{
/*绘制button区域*/
draw_region(&btn->btn_region, BUTTON_DEFAULT_COLOR);
/*居中显示文字*/
font_set_size(btn->fontSize);
draw_text_central(btn->name, &btn->btn_region, BUTTON_TEXT_COLOR);
/*flush 到 lcd或其它设备*/
flush_display_region(&btn->btn_region, buffer);
return 0;
}
居中显示文字,
先计算名字text的bbox框,构建一个Cartesian_region(虽然是叫笛卡尔坐标系,但是经过转换我们结构体里的x,y和region一样是region左上角坐标),通过text的region和button的region就能计算出第一个字符的原点(originX,Y,freetype的概念)。
/*计算第一个字符的原点*/
originX = region->x + (region->width - cartesianRegion.width) / 2 - cartesianRegion.x;//画图很容易理解
originY = region->y + (region->height - cartesianRegion.height) / 2 + cartesianRegion.y;
然后一个一个字符来绘制text
/*绘制*/
while (name[i]) {
fbm.currOriginX = originX;
fbm.currOriginY = originY;
//获得点阵
if (font_get_bitmap(name[i], &fbm)) {
printf("get bitmap err!\n");
return -1;
}
draw_font_bitmap(&fbm, color);
//更新原点
originX = fbm.nextOriginX;
originY = fbm.nextOriginY;
i++;
}
页面page抽象
一个页面需要名字,具体的业务,以及next指针,串联所有页面,之后方便在链表中找到对应page。上层manager层提供get_page函数获取对应name的page,然后执行该page的run函数即可执行项目业务代码。
typedef struct Page {
char *name;
void (*run)(void *param);
struct Page *next;
} Page;
void register_page(Page *pg);
void page_init(void);
Page *get_page(char *name);