改进
1.改进字体#
- 找出最长的name
- 确定font size
- 先设置一个字体大小,算出文字外框
- 放大或者缩小,以适配Button
- 再算出合适的字体大小
在page/mainpage.c
中GenerateButtons函数中添加,计算字体大小的函数GetFontSizeForAllButton
:
static void GenerateButtons(void)
{
/* 算出单个按钮的width,height */
/* 居中:计算每个按钮的region */
for (row = 0; (row < rows) && (i < n); row++) //计算region
{
cur_start_y = start_y + row * height;
// pre_start_x = start_x - width;
for (col = 0; (col < n_per_line) && (i < n); col++)
{
...
/* InitButton */
InitButton(GetItemCfgByIndex(i)->name, pButton, NULL, NULL, MainPageOnPressed);
}
}
前面代码保持不变,省略
iFontSize = GetFontSizeForAllButton();
// SetFontSize(iFontSize);
/* 显示:OnDraw */
for (i = 0; i < n; i++)
{
g_atButtons[i].iFontSize = iFontSize;
g_atButtons[i].OnDraw(&g_atButtons[i], pDispBuff);
}
}
static int GetFontSizeForAllButton(void)
{
int i;
int max_len = -1;
int max_index = 0;
int len;
RegionCartesian tRegionCar;
float k, kx, ky;
/* 1.找出name最长的Button */
for (i = 0; i < g_iButtonCnt; i++)
{
if ((len = strlen(g_atButtons[i].name)) > max_len)
{
max_len = len;
max_index = i;
}
}
/* 2.以font_size = 100,算出它的外框 */
SetFontSize(100);
GetStringRegionCar(g_atButtons[max_index].name, &tRegionCar);
/* 3.把文字的外框缩放为Button的外框 */
kx = (float)g_atButtons[max_index].tRegion.iWidth / tRegionCar.iWidth;
ky = (float)g_atButtons[max_index].tRegion.iHight / tRegionCar.iHight;
if (kx < ky)
{
k = kx;
}
else
{
k = ky;
}
/* 4.反算出font size, 只取0.8大小,避免文字过于接近边界 */
return k * 100 * 0.8;
}
计算外框函数
GetStringRegionCar
:参考"01_all_series_quickstart\04_嵌入式Linux应用开发基础知识\source\10_freetype\04_show_line\show_line.c"
获取字符串的外框的左上角坐标与宽和高,保存到定义在common.h
中的笛卡尔坐标区域的结构体common.h
typedef struct RegionCartesian{int iLeftUpX;int iLeftUpY;int iWidth;int iHight;} RegionCartesian, *PRegionCartesian;freetype.c的FreetypeGetStringRegionCar函数
获取字符串的外框的左上角坐标与宽和高,将函数放入Fontopr结构体static int FreetypeGetStringRegionCar(char *str, PRegionCartesian ptRegionCar){int i;int error;FT_BBox bbox;FT_BBox glyph_bbox;FT_Vector pen;FT_Glyph glyph;FT_GlyphSlot slot = g_tFace->glyph;/* 初始化 */bbox.xMin = bbox.yMin = 32000;bbox.xMax = bbox.yMax = -32000;/* 指定原点为(0, 0) */pen.x = 0;pen.y = 0;/* 计算每个字符的bounding box *//* 先translate, 再load char, 就可以得到它的外框了 */for (i = 0; i < strlen(str); i++){/* 转换:transformation */FT_Set_Transform(g_tFace, 0, &pen);/* 加载位图: load glyph image into the slot (erase previous one) */error = FT_Load_Char(g_tFace, str[i], FT_LOAD_RENDER);if (error){printf("FT_Load_Char error\n");return -1;}/* 取出glyph */error = FT_Get_Glyph(g_tFace->glyph, &glyph);if (error){printf("FT_Get_Glyph error!\n");return -1;}/* 从glyph得到外框: bbox */FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &glyph_bbox);/* 更新外框 */if (glyph_bbox.xMin < bbox.xMin)bbox.xMin = glyph_bbox.xMin;if (glyph_bbox.yMin < bbox.yMin)bbox.yMin = glyph_bbox.yMin;if (glyph_bbox.xMax > bbox.xMax)bbox.xMax = glyph_bbox.xMax;if (glyph_bbox.yMax > bbox.yMax)bbox.yMax = glyph_bbox.yMax;/* 计算下一个字符的原点: increment pen position */pen.x += slot->advance.x;pen.y += slot->advance.y;}/* return string bbox */ptRegionCar->iLeftUpX = bbox.xMin;ptRegionCar->iLeftUpY = bbox.yMax;ptRegionCar->iWidth = bbox.xMax - bbox.xMin + 1;ptRegionCar->iHight = bbox.yMax - bbox.yMin + 1;return 0;}static FontOpr g_tFreetypeOpr = {.name = "freetype",.FontInit = FreetypeFontInit,.SetFontSize = FreetypeSetFontSize,.GetFontBitMap = FreetypeGetFontBitMap,.GetStringRegionCar = FreetypeGetStringRegionCar,};font_manager
上层字体管理系统中,提供接口函数int GetStringRegionCar(char *str, PRegionCartesian ptRegionCar){return g_ptDefaultFontOpr->GetStringRegionCar(str, ptRegionCar);}
tips:将framebuffer转换为图片
开发板:把fb0的数据拷贝处理
[root@imx6ull:/mnt]# cat /dev/fb0 > 1.raw在虚拟机里:转换为bmp文件
./fb2bmp
2.规范函数API命名#
主要是将管理系统相关的初始化函数改名为系统注册函数,与下层具体部件初始化区分
int main(int argc, char **argv)
{
// PDispBuff ptBuffer;
int err;
if (argc != 2)
{
printf("Usage: %s <font_file>\n", argv[0]);
return -1;
}
/* 初始化显示系统 */
DisplaySystemRegister();
SelectDefaultDisplay("fb");
InitDefaultDisplay();
// ptBuffer = GetDisplayBuffer(); //获得显存buffer
/* 初始化输入系统 */
IntputSystemRegister();
IntputDeviceInit();
/* 初始化文字系统 */
FontSystemRegister();
err = SelectAndInitFont("freetype", argv[1]);
if (err)
{
printf("SelectAndInitFont err\n");
return -1;
}
/* 初始化页面系统 */ // UI系统不需要初始化,直接获取按键即可
PageSystemRegister();
/* 运行业务系统的主页面 */
Page("main")->Run(NULL);
return 0;
}
3.支持配置文件的command#
修改MainPageOnPressed
函数,在按钮被按下时能够调用配置文件的command:
调用command文件,传入当前状态。
static int MainPageOnPressed(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent)
{
unsigned int dwColor = BUTTON_DEFAULT_COLOR;
char name[100];
char status[100];
char *strButton = ptButton->name;
char *command_status[3] = {"err",
"ok",
"percent"};
int command_status_index = 0;
char command[1000];
PItemCfg ptItemCfg;
/* 1. 对于触摸屏事件 */
if (ptInputEvent->iType == INPUT_TYPE_TOUCH && ptInputEvent->iPressure == 0) // 松开的时候响应
{
/* 1.1 分辨能否被点击 */
if (0 == GetItemCfgByName(ptButton->name)->bCanBeTouched)
{
return -1;
}
/* 1.2 修改颜色 */
ptButton->status = !ptButton->status;
if (1 == ptButton->status)
{
dwColor = BUTTON_PRESSED_COLOR;
command_status_index = 1;
}
}
/* 2. 对于网络事件 */
else if (ptInputEvent->iType == INPUT_TYPE_NET)
{
/* 2.1 根据传入字符串修改颜色 */
sscanf(ptInputEvent->str, "%s %s", name, status);
if (strcmp(status, "ok") == 0)
{
command_status_index = 1;
dwColor = BUTTON_PRESSED_COLOR;
}
else if (strcmp(status, "err") == 0)
{
command_status_index = 0;
dwColor = BUTTON_DEFAULT_COLOR;
}
else if (status[0] >= '0' && status[0] <= '9')
{
command_status_index = 2;
dwColor = BUTTON_PERCENT_COLOR;
strButton = status;
}
else
{
return -1;
}
}
else
{
return -1; //其余输入事件无法处理
}
//绘制底色
DrawRegion(&ptButton->tRegion, dwColor);
//居中写文字
DrawTextInRegionCentrl(strButton, &ptButton->tRegion, BUTTON_TEXT_COLOR);
// flush to lcd or web
FlushDisplayRegion(&ptButton->tRegion, ptDispBuff);
/* 执行command */
ptItemCfg = GetItemCfgByName(ptButton->name);
if (ptItemCfg->command[0] != '\0')
{
//把命令和按钮状态拷贝到command数组
sprintf(command, "%s %s", ptItemCfg->command, command_status[command_status_index]);
system(command);
}
return 0;
}
上机:
编写一个led.sh
#!/bin/sh
status=$1
if [ "$status" = "ok" ]
then
echo "led has been tested, it is ok"
fi
if [ "$status" = "err" ]
then
echo "led has been tested, it is err"
fi
拷贝到bin目录,修改执行权限
[root@imx6ull:/mnt/31_improve_command]# ls
Makefile built-in.o config etc include led.sh simsun.ttc ui ??????.txt
Makefile.build business display font input page test unittest
[root@imx6ull:/mnt/31_improve_command]# cp led.sh /bin/
[root@imx6ull:/mnt/31_improve_command]# chmod +x /bin/led.sh
如果无法执行,需要在虚拟机转换:
dos2unix led.sh
请点击左侧菜单(移动端为右下角)选择要查看的所有笔记吧。