要在lcd上显示图标,要事先规划出各图片的坐标。
typedef struct PageLayout {
int iTopLeftX; /* 这个区域的左上角、右下角坐标 */
int iTopLeftY;
int iBotRightX;
int iBotRightY;
int iBpp; /* 一个象素用多少位来表示 */
int iMaxTotalBytes; //最大图标总字节数
PT_Layout atLayout; /* 数组: 这个区域分成好几个小区域 */
}T_PageLayout, *PT_PageLayout;
typedef struct Layout {
int iTopLeftX;
int iTopLeftY;
int iBotRightX;
int iBotRightY;
char *strIconName; //图标名字
}T_Layout, *PT_Layout;
在每个页面中都有g_at–PageIconsLayout[]数组来确定该界面各图标的位置。在Show–Page函数中根据数组中的位置,逐一描画出各图标数据。分配的内存没有释放,而是改变一下状态,当下次还要用到的时候直接调用不用重新布局。
static T_Layout g_atMainPageIconsLayout[] = {
{0, 0, 0, 0, "browse_mode.bmp"},
{0, 0, 0, 0, "continue_mod.bmp"},
{0, 0, 0, 0, "setting.bmp"},
{0, 0, 0, 0, NULL},
};
static T_PageLayout g_tMainPageLayout = {
.iMaxTotalBytes = 0,
.atLayout = g_atMainPageIconsLayout,
};
计算页面中各图标座标值
static void CalcMainPageLayout(PT_PageLayout ptPageLayout){
int iStartY; //图标起始y位置
int iWidth; //图标宽度
int iHeight; //图标高度
int iXres, iYres, iBpp; //LCD分辨率
int iTmpTotalBytes; //图标总字节数
PT_Layout atLayout; //页面布局数组
atLayout = ptPageLayout->atLayout;
GetDispResolution(&iXres, &iYres, &iBpp); //获得LCD分辨率
ptPageLayout->iBpp = iBpp;
/* ----------------------
* 1/2 * iHeight
* browse_mode.bmp iHeight
* 1/2 * iHeight
* continue_mod.bmp iHeight
* 1/2 * iHeight
* setting.bmp iHeight
* 1/2 * iHeight
* ----------------------*/
iHeight = iYres * 2 / 10;
iWidth = iHeight;
iStartY = iHeight / 2;
/* select_fold图标 */
atLayout[0].iTopLeftY = iStartY;
atLayout[0].iBotRightY = atLayout[0].iTopLeftY + iHeight - 1;
atLayout[0].iTopLeftX = (iXres - iWidth * 2) / 2;
atLayout[0].iBotRightX = atLayout[0].iTopLeftX + iWidth * 2 - 1;
iTmpTotalBytes = (atLayout[0].iBotRightX - atLayout[0].iTopLeftX + 1) * (atLayout[0].iBotRightY - atLayout[0].iTopLeftY + 1) * iBpp / 8;
if (ptPageLayout->iMaxTotalBytes < iTmpTotalBytes)
ptPageLayout->iMaxTotalBytes = iTmpTotalBytes;
/* interval图标 */
atLayout[1].iTopLeftY = atLayout[0].iBotRightY + iHeight / 2 + 1;
atLayout[1].iBotRightY = atLayout[1].iTopLeftY + iHeight - 1;
atLayout[1].iTopLeftX = (iXres - iWidth * 2) / 2;
atLayout[1].iBotRightX = atLayout[1].iTopLeftX + iWidth * 2 - 1;
iTmpTotalBytes = (atLayout[1].iBotRightX - atLayout[1].iTopLeftX + 1) * (atLayout[1].iBotRightY - atLayout[1].iTopLeftY + 1) * iBpp / 8;
if (ptPageLayout->iMaxTotalBytes < iTmpTotalBytes)
ptPageLayout->iMaxTotalBytes = iTmpTotalBytes;
/* return图标 */
atLayout[2].iTopLeftY = atLayout[1].iBotRightY + iHeight / 2 + 1;
atLayout[2].iBotRightY = atLayout[2].iTopLeftY + iHeight - 1;
atLayout[2].iTopLeftX = (iXres - iWidth * 2) / 2;
atLayout[2].iBotRightX = atLayout[2].iTopLeftX + iWidth * 2 - 1;
iTmpTotalBytes = (atLayout[2].iBotRightX - atLayout[2].iTopLeftX + 1) * (atLayout[2].iBotRightY - atLayout[2].iTopLeftY + 1) * iBpp / 8;
if (ptPageLayout->iMaxTotalBytes < iTmpTotalBytes)
ptPageLayout->iMaxTotalBytes = iTmpTotalBytes;
}
显示"主页面"
static void ShowMainPage(PT_PageLayout ptPageLayout){
PT_VideoMem ptVideoMem;
PT_Layout atLayout = ptPageLayout->atLayout;
/* 1. 获得显存 */
ptVideoMem = GetVideoMem(ID("main"), 1);
/* 2. 描画数据 */
/* 如果还没有计算过各图标的坐标 */
if (atLayout[0].iTopLeftX == 0)
CalcMainPageLayout(ptPageLayout);
GeneratePage(ptPageLayout, ptVideoMem);
/* 3. 刷到设备上去 */
FlushVideoMemToDev(ptVideoMem);
/* 4. 解放显存 */
PutVideoMem(ptVideoMem);
}
render.c
取出BMP格式的图标文件中的象素数据,包含文件操作,参数包括BMP格式的图标文件名,它位于/etc/digitpic/icons目录下,PixelDatas图片的象素数据结构体,解析BMP格式的图标获得图像信息存放在PixelDatas内。
int GetPixelDatasForIcon(char *strFileName, PT_PixelDatas ptPixelDatas){
T_FileMap tFileMap;
int iError;
int iXres, iYres, iBpp;
/* 图标存在 /etc/digitpic/icons */
snprintf(tFileMap.strFileName, 128, "%s/%s", ICON_PATH, strFileName); //文件名加上路径
tFileMap.strFileName[127] = '\0';
MapFile(&tFileMap); //映射文件
Parser("bmp")->isSupport(&tFileMap); //能否支持该格式文件解析
GetDispResolution(&iXres, &iYres, &iBpp); //获取LCD分辨率
ptPixelDatas->iBpp = iBpp; //设置bpp为lcd的bpp
Parser("bmp")->GetPixelDatas(&tFileMap, ptPixelDatas); //获得bmp文件的数据
UnMapFile(&tFileMap); //取消映射
return 0;
}
void FreePixelDatasForIcon(PT_PixelDatas ptPixelDatas){
Parser("bmp")->FreePixelDatas(ptPixelDatas); //释放图像数据所占缓冲区
}
page_manager.c
从图标文件中解析出图像数据并放在指定区域,从而生成页面数据,参数为ptPageLayout内含多个图标的文件名和显示区域,ptVideoMem在这个VideoMem里构造页面数据。根据ptPageLayout中的布局,将这个页面构造出来。
int GeneratePage(PT_PageLayout ptPageLayout, PT_VideoMem ptVideoMem){
T_PixelDatas tOriginIconPixelDatas;
T_PixelDatas tIconPixelDatas;
int iError;
PT_Layout atLayout = ptPageLayout->atLayout; //图标布局
/* 描画数据: VideoMem中的页面数据未生成的情况下才执行下面操作 */
if (ptVideoMem->ePicState != PS_GENERATED){
ClearVideoMem(ptVideoMem, COLOR_BACKGROUND); //清除缓存
tIconPixelDatas.iBpp = ptPageLayout->iBpp;
/* 分配一个临时的内存, 它用来存放缩放后的图标数据 */
tIconPixelDatas.aucPixelDatas = malloc(ptPageLayout->iMaxTotalBytes);
while (atLayout->strIconName){
/* 取得图标文件的象素数据 */
GetPixelDatasForIcon(atLayout->strIconName, &tOriginIconPixelDatas);
tIconPixelDatas.iHeight = atLayout->iBotRightY - atLayout->iTopLeftY + 1;
tIconPixelDatas.iWidth = atLayout->iBotRightX - atLayout->iTopLeftX+ 1;
tIconPixelDatas.iLineBytes = tIconPixelDatas.iWidth * tIconPixelDatas.iBpp / 8;
tIconPixelDatas.iTotalBytes = tIconPixelDatas.iLineBytes * tIconPixelDatas.iHeight;
/* 把原始的图标象素数据缩放为指定大小 */
PicZoom(&tOriginIconPixelDatas, &tIconPixelDatas);
/* 把缩放后的图标数据,合并到VideoMem的指定区域 */
PicMerge(atLayout->iTopLeftX, atLayout->iTopLeftY, &tIconPixelDatas, &ptVideoMem->tPixelDatas);
/* 释放原始的图标象素数据 */
FreePixelDatasForIcon(&tOriginIconPixelDatas);
atLayout++;
}
free(tIconPixelDatas.aucPixelDatas); /* 数据上面分配的临时内存 */
ptVideoMem->ePicState = PS_GENERATED;
}
return 0;
}