所学均来自百问网
目录
1. 按钮改进
freetype.c
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 */
//*abbox = bbox;
ptRegionCar->iLeftUpX = bbox.xMin;
ptRegionCar->iLeftUpY = bbox.yMax;
ptRegionCar->iWidth = bbox.xMax - bbox.xMin + 1;
ptRegionCar->iHeigh = bbox.yMax - bbox.yMin + 1;
return 0;
}
main_page.c
static int GetFontSizeForAllButton(void)
{
int i;
int max_len = -1;
int max_index = 0;
int len;
RegionCartesian tRegionCar;
float k,kx,ky;
// 找出name最长的Button
for(i = 0; i < g_tButtonCnt; i++)
{
len = strlen(g_tButtons[i].name);
if(len > max_len)
{
max_len = len;
max_index = i;
}
}
// 以font_size = 100 为例 算出它的外框
SetFontSize(100);
GetStringRegionCar(g_tButtons[max_index].name,&tRegionCar);
// 把文字的外框缩放为Button的外框
kx = (float)g_tButtons[max_index].tRegion.iWidth / tRegionCar.iWidth;
ky = (float)g_tButtons[max_index].tRegion.iHeigh / tRegionCar.iHeigh;
if(kx < ky)
k = kx;
else
k = ky;
// 反算出font_size 只取80% 避免文字太靠近边界
return k * 100 * 0.8;
}
disp_manager.c
void DrawTextInRegionCentral(char *name,PRegion ptRegion,unsigned int dwColor)
{
FontBitMap tFontBitMap;
int iOriginX,iOriginY;
int i = 0;
int error;
RegionCartesian tRegionCar;
// 计算字符的外框
GetStringRegionCar(name, &tRegionCar);
// 算出第一个字符的origin
iOriginX = ptRegion->iLeftUpX + (ptRegion->iWidth - tRegionCar.iWidth) / 2 - tRegionCar.iLeftUpX;
iOriginY = ptRegion->iLeftUpY + (ptRegion->iHeigh - tRegionCar.iHeigh) / 2 + tRegionCar.iLeftUpY;
// 逐个绘制
while(name[i])
{
// 获得位图
tFontBitMap.iCurOriginX = iOriginX;
tFontBitMap.iCurOriginY = iOriginY;
error = GetFontBitMap(name[i], &tFontBitMap);
if(error)
{
printf("GetFontBitMap err\n");
return;
}
// 绘制
DrawFontBitMap(&tFontBitMap,dwColor);
iOriginX = tFontBitMap.iNextOriginX;
iOriginY = tFontBitMap.iNextOriginY;
i++;
}
}
common.h
#ifndef __COMMON_H
#define __COMMON_H
typedef struct Region{
int iLeftUpX;
int iLeftUpY;
int iWidth;
int iHeigh;
}Region,*PRegion;
// 笛卡尔坐标系
typedef struct RegionCartesian{
int iLeftUpX;
int iLeftUpY;
int iWidth;
int iHeigh;
}RegionCartesian,*PRegionCartesian;
#ifndef NULL
#define NULL (void *)0
#endif
#endif
效果
2. 函数名改进
main.c的函数名修改如下,相关设置以下函数的文件均也改名
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <disp_manager.h>
#include <font_manager.h>
#include <input_manager.h>
#include <page_manager.h>
int main(int argc, char **argv)
{
int error;
if (argc != 2)
{
printf("Usage: %s <font_file>\n", argv[0]);
return -1;
}
/* 初始化显示系统 */
DisplaySystemRegister(); /* 以前是: DisplayInit(); */
SelectDefaultDisplay("fb");
InitDefaultDisplay();
/* 初始化输入系统 */
InputSystemRegister(); /* 以前是: InputInit(); */
IntpuDeviceInit();
/* 初始化文字系统 */
FontSystemRegister(); /* 以前是: FontsRegister(); */
error = SelectAndInitFont("freetype", argv[1]);
if (error)
{
printf("SelectAndInitFont err\n");
return -1;
}
/* 初始化页面系统 */
PageSystemRegister(); /* 以前是: PagesRegister(); */
/* 运行业务系统的主页面 */
Page("main")->Run(NULL);
return 0;
}
3. 支持配置文件的command
main_page.c
#include <page_manager.h>
#include <stdio.h>
#include <config.h>
#include <math.h>
#include <string.h>
#include <ui.h>
#include <stdlib.h>
static Button g_tButtons[ITEMCFG_MAX_NUM];
static int g_tButtonCnt;
#define X_GAP 5 // 每个按钮间隔距离
#define Y_GAP 5
static int MainPageOnPressed(struct Button *ptButton,PDispBuff ptDispBuff,PInputEvent ptInputEvent)
{
unsigned int dwColor = BUTTON_DEFAULT_COLOR; // 默认颜色
char name[100];
char status[100];
char *strButton;
char *command_status[3] = {"err","ok","percent"};
int command_status_index = 0;
char command[1000];
PItemCfg ptItemCfg;
strButton = ptButton->name;
// 对于触摸屏
if(ptInputEvent->iType == INPUT_TYPE_TOUCH)
{
// 能否被点击
if(GetItemCfgByName(ptButton->name)->bCanBeTouched == 0)
return -1;
// 修改颜色
ptButton->status = !ptButton->status;
if(ptButton->status)
{
dwColor = BUTTON_PRESSEN_COLOR;
command_status_index = 1;
}
}
else if(ptInputEvent->iType == INPUT_TYPE_NET)
{
// 对于网络类事件
// 根据传入的字符串修改颜色:wifi ok, wifi err,wifi 78
sscanf(ptInputEvent->str,"%s %s",name,status);
if(strcmp(status,"ok") == 0)
{
command_status_index = 1;
dwColor = BUTTON_PRESSEN_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);
// 居中显示文字
DrawTextInRegionCentral(strButton,&ptButton->tRegion,BUTTON_TEXT_COLOR);
// 刷新
FlushDisplayRegion(&ptButton->tRegion,ptDispBuff);
// 执行command
ptItemCfg = GetItemCfgByName(ptButton->name);
if(ptItemCfg->command[0] != '\0')
{
sprintf(command,"%s %s",ptItemCfg->command,command_status[command_status_index]);
system(command);
}
return 0;
}
static int GetFontSizeForAllButton(void)
{
int i;
int max_len = -1;
int max_index = 0;
int len;
RegionCartesian tRegionCar;
float k,kx,ky;
// 找出name最长的Button
for(i = 0; i < g_tButtonCnt; i++)
{
len = strlen(g_tButtons[i].name);
if(len > max_len)
{
max_len = len;
max_index = i;
}
}
// 以font_size = 100 为例 算出它的外框
SetFontSize(100);
GetStringRegionCar(g_tButtons[max_index].name,&tRegionCar);
// 把文字的外框缩放为Button的外框
kx = (float)g_tButtons[max_index].tRegion.iWidth / tRegionCar.iWidth;
ky = (float)g_tButtons[max_index].tRegion.iHeigh / tRegionCar.iHeigh;
if(kx < ky)
k = kx;
else
k = ky;
// 反算出font_size 只取80% 避免文字太靠近边界
return k * 100 * 0.8;
}
static void GenerateButtons(void)
{
int width,height;
int n_per_line;
int row,rows;
int col;
int n;
PDispBuff pDispBuff;
int xres,yres;
int start_x,start_y;
PButton pButton;
int i = 0;
int pre_start_x,pre_start_y;
int iFontSize;
// 多少个按钮
g_tButtonCnt = n = GetItemCfgCount();
// 获得x y的分辨率
pDispBuff = GetDisplayBuffer();
xres = pDispBuff->iXres;
yres = pDispBuff->iYres;
width = sqrt(1.0 / 0.618 * xres * yres / n);//算出理想宽度 但可能会使按钮越界
n_per_line = xres / width + 1;//算出每一行能显示的按钮个数
// 算出单个按钮的高度和宽度
width = xres / n_per_line;
height = 0.618 * width;
// 按钮显示的起始x坐标
start_x = (xres - width * n_per_line) / 2;
// 算出一列有多少个按钮
rows = n / n_per_line;
if(rows * n_per_line < n)
rows++; //算出小数则加1
// 按钮显示的起始y坐标
start_y = (yres - rows * height) / 2;
// 居中显示:计算每个按钮的region
for(row = 0; (row < rows) && (i < n); row++)
{
pre_start_y = start_y + row * height;
pre_start_x = start_x - width;
for(col = 0; (col < n_per_line) && (i < n); col++)
{
pButton = &g_tButtons[i];
// 下一个按钮的位置
pButton->tRegion.iLeftUpX = pre_start_x + width;
pButton->tRegion.iLeftUpY = pre_start_y;
pButton->tRegion.iWidth = width - X_GAP;
pButton->tRegion.iHeigh = height - Y_GAP;
pre_start_x = pButton->tRegion.iLeftUpX;
// 初始化按钮
InitButton(pButton, GetItemCfgByIndex(i)->name, NULL, NULL, MainPageOnPressed);
i++;
}
}
iFontSize = GetFontSizeForAllButton();
//SetFontSize(iFontSize);
// 显示
for(i = 0; i < n;i++)
{
g_tButtons[i].iFoneSize = iFontSize;
g_tButtons[i].OnDraw(&g_tButtons[i],pDispBuff);
}
}
static int isTouchPointInRegion(int iX,int iY,PRegion ptRegion)
{
if(iX < ptRegion->iLeftUpX || iX >= ptRegion->iLeftUpX + ptRegion->iWidth)
return 0;
if(iY < ptRegion->iLeftUpY || iY >= ptRegion->iLeftUpY + ptRegion->iHeigh)
return 0;
return 1;
}
static PButton GetButtonByName(char *name)
{
int i;
for(i = 0; i < g_tButtonCnt;i++)
{
if(strcmp(name,g_tButtons[i].name) == 0)
return &g_tButtons[i];
}
return NULL;
}
static PButton GetButtonByInputEvent(PInputEvent ptInputEvent)
{
int i;
char name[100];
if(ptInputEvent->iType == INPUT_TYPE_TOUCH)
{
for(i = 0; i < g_tButtonCnt;i++)
{
if(isTouchPointInRegion(ptInputEvent->iX,ptInputEvent->iY,&g_tButtons[i].tRegion))
return &g_tButtons[i];
}
}else if(ptInputEvent->iType == INPUT_TYPE_NET)
{
sscanf(ptInputEvent->str,"%s",name);
return GetButtonByName(name);
}else
{
return NULL;
}
return NULL;
}
static void MainPageRun(void *pParams)
{
int error;
InputEvent tInputEvent;
PButton ptButton;
PDispBuff ptDispBuff = GetDisplayBuffer();
// 读取配置文件
error = ParseConfigFile();
if(error)
return;
// 根据配置文件生成按钮、界面
GenerateButtons();
while(1)
{
// 读取输入事件
error = GetInputEvent(&tInputEvent);
if(error)
continue;
// 根据输入事件找到按钮
ptButton = GetButtonByInputEvent(&tInputEvent);
if(!ptButton)
continue;
// 调用按钮的OnPressed函数
ptButton->OnPressed(ptButton,ptDispBuff,&tInputEvent);
}
}
static PageAction g_tMainPage = {
.name = "main",
.Run = MainPageRun,
};
void MainPageRegister(void)
{
PageRegister(&g_tMainPage);
}
len.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 fail"
fi