main.c
判断输入参数及调用draw.c函数
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <config.h>
#include <draw.h>
#include <encoding_manager.h>
#include <fonts_manager.h>
#include <disp_manager.h>
#include <string.h>
/* ./show_file [-s Size] [-f freetype_font_file] [-h HZK] <text_file> */
int main(int argc, char **argv)
{
int iError;
unsigned int dwFontSize = 16;
char acHzkFile[128];
char acFreetypeFile[128];
char acTextFile[128];
char acDisplay[128];
char cOpr;
int bList = 0;
acHzkFile[0] = '\0';
acFreetypeFile[0] = '\0';
acTextFile[0] = '\0';
strcpy(acDisplay, "fb");
//1、使用getopt解析参数里面的选项,当遇到第一个选项字符时,并将全局变量optarg指向该选项的参数,这里使用while,找到了optstring中的所有选项
while ((iError = getopt(argc, argv, "ls:f:h:d:")) != -1)
{
switch(iError)
{
case 'l':
{
bList = 1;
break;
}
case 's':
{
dwFontSize = strtoul(optarg, NULL, 0);
break;
}
case 'f':
{
//2、指定长度的字符串拷贝
strncpy(acFreetypeFile, optarg, 128);
acFreetypeFile[127] = '\0';
break;
}
case 'h':
{
strncpy(acHzkFile, optarg, 128);
acHzkFile[127] = '\0';
break;
}
case 'd':
{
strncpy(acDisplay, optarg, 128);
acDisplay[127] = '\0';
break;
}
default:
{
printf("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);
printf("Usage: %s -l\n", argv[0]);
return -1;
break;
}
}
}
//3、optind代表optarg下一个要处理的命令行参数的索引,这里optind >= argc的话,代表没有对应的参数
if (!bList && (optind >= argc))
{
printf("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);
printf("Usage: %s -l\n", argv[0]);
return -1;
}
//4、disp显示结构体注册
iError = DisplayInit();
if (iError)
{
printf("DisplayInit error!\n");
return -1;
}
//5、glyph结构体注册
iError = FontsInit();
if (iError)
{
printf("FontsInit error!\n");
return -1;
}
//6、编码结构体注册
iError = EncodingInit();
if (iError)
{
printf("EncodingInit error!\n");
return -1;
}
if (bList)
{
//7、打印所有disp的结构体name(所有支持的disp方式:fb)
printf("supported display:\n");
ShowDispOpr();
//8、打印所有glyph的结构体name(所有获取glyph的方式:ascii,freetype,gbk)
printf("supported font:\n");
ShowFontOpr();
//9、打印所有支持编码的结构体name(所有支持的编码:ascii,utf-8,utf-16)
printf("supported encoding:\n");
ShowEncodingOpr();
return 0;
}
//10、optarg解析完参数后,未解析到的参数就是texstfile(novel_file)
strncpy(acTextFile, argv[optind], 128);
acTextFile[127] = '\0';
/*11、这个函数输入为text_file参数。进行操作:打开text_file,通过fstat找到text_file结尾(指针),
通过SelectEncodingOprForFile找到文件支持编码,
并且通过PT_EncodingOpr->iHeadLen找到text_file字符开始的位置(因为每个text_file的前几个字符为编码_flag)*/
iError = OpenTextFile(acTextFile);
if (iError)
{
printf("OpenTextFile error!\n");
return -1;
}
//12、通过font_init把char_size、hzk、simsun进行设置及打开,如果不成功,则释放掉font结构体和encode结构体
iError = SetTextDetail(acHzkFile, acFreetypeFile, dwFontSize);
if (iError)
{
printf("SetTextDetail error!\n");
return -1;
}
DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
//13、选择输入的disp方式(fb),并进行fbdeivceinit
iError = SelectAndInitDisplay(acDisplay);
if (iError)
{
printf("SelectAndInitDisplay error!\n");
return -1;
}
DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
/*14、把11步找到的text开头给到showonepage并进行页的控制(PT_PageDesc结构体),
showonepage里g_ptEncodingOprForFile->GetCodeFrmBuf、ptFontOpr->GetFontBitmap、ShowOneFont(showpixel)*/
iError = ShowNextPage();
DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
if (iError)
{
printf("Error to show first page\n");
return -1;
}
//15、使用getchar进行交互,判断进行下一页、上一页、退出操作
while (1)
{
printf("Enter 'n' to show next page, 'u' to show previous page, 'q' to exit: ");
do {
cOpr = getchar();
} while ((cOpr != 'n') && (cOpr != 'u') && (cOpr != 'q'));
if (cOpr == 'n')
{
ShowNextPage();
}
else if (cOpr == 'u')
{
ShowPrePage();
}
else
{
return 0;
}
}
return 0;
}
draw.c
draw.c调用三大模块函数
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <config.h>
#include <draw.h>
#include <encoding_manager.h>
#include <fonts_manager.h>
#include <disp_manager.h>
#include <string.h>
typedef struct PageDesc {
int iPage;
unsigned char *pucLcdFirstPosAtFile;
unsigned char *pucLcdNextPageFirstPosAtFile;
struct PageDesc *ptPrePage;
struct PageDesc *ptNextPage;
} T_PageDesc, *PT_PageDesc;
static int g_iFdTextFile;
static unsigned char *g_pucTextFileMem;
static unsigned char *g_pucTextFileMemEnd;
static PT_EncodingOpr g_ptEncodingOprForFile;
static PT_DispOpr g_ptDispOpr;
static unsigned char *g_pucLcdFirstPosAtFile;
static unsigned char *g_pucLcdNextPosAtFile;
static int g_dwFontSize;
static PT_PageDesc g_ptPages = NULL;
static PT_PageDesc g_ptCurPage = NULL;
int OpenTextFile(char *pcFileName)
{
struct stat tStat;
g_iFdTextFile = open(pcFileName, O_RDONLY);
if (0 > g_iFdTextFile)
{
DBG_PRINTF("can't open text file %s\n", pcFileName);
return -1;
}
if(fstat(g_iFdTextFile, &tStat))
{
DBG_PRINTF("can't get fstat\n");
return -1;
}
g_pucTextFileMem = (unsigned char *)mmap(NULL , tStat.st_size, PROT_READ, MAP_SHARED, g_iFdTextFile, 0);
if (g_pucTextFileMem == (unsigned char *)-1)
{
DBG_PRINTF("can't mmap for text file\n");
return -1;
}
g_pucTextFileMemEnd = g_pucTextFileMem + tStat.st_size;
g_ptEncodingOprForFile = SelectEncodingOprForFile(g_pucTextFileMem);
if (g_ptEncodingOprForFile)
{
g_pucLcdFirstPosAtFile = g_pucTextFileMem + g_ptEncodingOprForFile->iHeadLen;
return 0;
}
else
{
return -1;
}
}
int SetTextDetail(char *pcHZKFile, char *pcFileFreetype, unsigned int dwFontSize)
{
int iError = 0;
PT_FontOpr ptFontOpr;
PT_FontOpr ptTmp;
int iRet = -1;
g_dwFontSize = dwFontSize;
ptFontOpr = g_ptEncodingOprForFile->ptFontOprSupportedHead;
while (ptFontOpr)
{
if (strcmp(ptFontOpr->name, "ascii") == 0)
{
iError = ptFontOpr->FontInit(NULL, dwFontSize);
}
else if (strcmp(ptFontOpr->name, "gbk") == 0)
{
iError = ptFontOpr->FontInit(pcHZKFile, dwFontSize);
}
else
{
iError = ptFontOpr->FontInit(pcFileFreetype, dwFontSize);
}
DBG_PRINTF("%s, %d\n", ptFontOpr->name, iError);
ptTmp = ptFontOpr->ptNext;
if (iError == 0)
{
/* 比如对于ascii编码的文件, 可能用ascii字体也可能用gbk字体,
* 所以只要有一个FontInit成功, SetTextDetail最终就返回成功
*/
iRet = 0;
}
else
{
DelFontOprFrmEncoding(g_ptEncodingOprForFile, ptFontOpr);
}
ptFontOpr = ptTmp;
}
return iRet;
}
int SelectAndInitDisplay(char *pcName)
{
int iError;
g_ptDispOpr = GetDispOpr(pcName);
if (!g_ptDispOpr)
{
return -1;
}
iError = g_ptDispOpr->DeviceInit();
return iError;
}
int IncLcdX(int iX)
{
if (iX + 1 < g_ptDispOpr->iXres)
return (iX + 1);
else
return 0;
}
int IncLcdY(int iY)
{
if (iY + g_dwFontSize < g_ptDispOpr->iYres)
return (iY + g_dwFontSize);
else
return 0;
}
int RelocateFontPos(PT_FontBitMap ptFontBitMap)
{
int iLcdY;
int iDeltaX;
int iDeltaY;
if (ptFontBitMap->iYMax > g_ptDispOpr->iYres)
{
/* 满页了 */
return -1;
}
/* 超过LCD最右边 */
if (ptFontBitMap->iXMax > g_ptDispOpr->iXres)
{
/* 换行 */
iLcdY = IncLcdY(ptFontBitMap->iCurOriginY);
if (0 == iLcdY)
{
/* 满页了 */
return -1;
}
else
{
/* 没满页 */
iDeltaX = 0 - ptFontBitMap->iCurOriginX;
iDeltaY = iLcdY - ptFontBitMap->iCurOriginY;
ptFontBitMap->iCurOriginX += iDeltaX;
ptFontBitMap->iCurOriginY += iDeltaY;
ptFontBitMap->iNextOriginX += iDeltaX;
ptFontBitMap->iNextOriginY += iDeltaY;
ptFontBitMap->iXLeft += iDeltaX;
ptFontBitMap->iXMax += iDeltaX;
ptFontBitMap->iYTop += iDeltaY;
ptFontBitMap->iYMax += iDeltaY;;
return 0;
}
}
return 0;
}
int ShowOneFont(PT_FontBitMap ptFontBitMap)
{
int x;
int y;
unsigned char ucByte = 0;
int i = 0;
int bit;
if (ptFontBitMap->iBpp == 1)
{
for (y = ptFontBitMap->iYTop; y < ptFontBitMap->iYMax; y++)
{
i = (y - ptFontBitMap->iYTop) * ptFontBitMap->iPitch;
for (x = ptFontBitMap->iXLeft, bit = 7; x < ptFontBitMap->iXMax; x++)
{
if (bit == 7)
{
ucByte = ptFontBitMap->pucBuffer[i++];
}
if (ucByte & (1<<bit))
{
g_ptDispOpr->ShowPixel(x, y, COLOR_FOREGROUND);
}
else
{
/* 使用背景色, 不用描画 */
// g_ptDispOpr->ShowPixel(x, y, 0); /* 黑 */
}
bit--;
if (bit == -1)
{
bit = 7;
}
}
}
}
else if (ptFontBitMap->iBpp == 8)
{
for (y = ptFontBitMap->iYTop; y < ptFontBitMap->iYMax; y++)
for (x = ptFontBitMap->iXLeft; x < ptFontBitMap->iXMax; x++)
{
//g_ptDispOpr->ShowPixel(x, y, ptFontBitMap->pucBuffer[i++]);
if (ptFontBitMap->pucBuffer[i++])
g_ptDispOpr->ShowPixel(x, y, COLOR_FOREGROUND);
}
}
else
{
DBG_PRINTF("ShowOneFont error, can't support %d bpp\n", ptFontBitMap->iBpp);
return -1;
}
return 0;
}
int ShowOnePage(unsigned char *pucTextFileMemCurPos)
{
int iLen;
int iError;
unsigned char *pucBufStart;
unsigned int dwCode;
PT_FontOpr ptFontOpr;
T_FontBitMap tFontBitMap;
int bHasNotClrSceen = 1;
int bHasGetCode = 0;
tFontBitMap.iCurOriginX = 0;
tFontBitMap.iCurOriginY = g_dwFontSize;
pucBufStart = pucTextFileMemCurPos;
while (1)
{
iLen = g_ptEncodingOprForFile->GetCodeFrmBuf(pucBufStart, g_pucTextFileMemEnd, &dwCode);
if (0 == iLen)
{
/* 文件结束 */
if (!bHasGetCode)
{
return -1;
}
else
{
return 0;
}
}
bHasGetCode = 1;
pucBufStart += iLen;
/* 有些文本, \n\r两个一起才表示回车换行
* 碰到这种连续的\n\r, 只处理一次
*/
if (dwCode == '\n')
{
g_pucLcdNextPosAtFile = pucBufStart;
/* 回车换行 */
tFontBitMap.iCurOriginX = 0;
tFontBitMap.iCurOriginY = IncLcdY(tFontBitMap.iCurOriginY);
if (0 == tFontBitMap.iCurOriginY)
{
/* 显示完当前一屏了 */
return 0;
}
else
{
continue;
}
}
else if (dwCode == '\r')
{
continue;
}
else if (dwCode == '\t')
{
/* TAB键用一个空格代替 */
dwCode = ' ';
}
DBG_PRINTF("dwCode = 0x%x\n", dwCode);
ptFontOpr = g_ptEncodingOprForFile->ptFontOprSupportedHead;
while (ptFontOpr)
{
DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
iError = ptFontOpr->GetFontBitmap(dwCode, &tFontBitMap);
DBG_PRINTF("%s %s %d, ptFontOpr->name = %s, %d\n", __FILE__, __FUNCTION__, __LINE__, ptFontOpr->name, iError);
if (0 == iError)
{
DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
if (RelocateFontPos(&tFontBitMap))
{
/* 剩下的LCD空间不能满足显示这个字符 */
return 0;
}
DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
if (bHasNotClrSceen)
{
/* 首先清屏 */
g_ptDispOpr->CleanScreen(COLOR_BACKGROUND);
bHasNotClrSceen = 0;
}
DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
/* 显示一个字符 */
if (ShowOneFont(&tFontBitMap))
{
return -1;
}
tFontBitMap.iCurOriginX = tFontBitMap.iNextOriginX;
tFontBitMap.iCurOriginY = tFontBitMap.iNextOriginY;
g_pucLcdNextPosAtFile = pucBufStart;
/* 继续取出下一个编码来显示 */
break;
}
ptFontOpr = ptFontOpr->ptNext;
}
}
return 0;
}
static void RecordPage(PT_PageDesc ptPageNew)
{
PT_PageDesc ptPage;
if (!g_ptPages)
{
g_ptPages = ptPageNew;
}
else
{
ptPage = g_ptPages;
while (ptPage->ptNextPage)
{
ptPage = ptPage->ptNextPage;
}
ptPage->ptNextPage = ptPageNew;
ptPageNew->ptPrePage = ptPage;
}
}
int ShowNextPage(void)
{
int iError;
PT_PageDesc ptPage;
unsigned char *pucTextFileMemCurPos;
if (g_ptCurPage)
{
pucTextFileMemCurPos = g_ptCurPage->pucLcdNextPageFirstPosAtFile;
}
else
{
pucTextFileMemCurPos = g_pucLcdFirstPosAtFile;
}
iError = ShowOnePage(pucTextFileMemCurPos);
DBG_PRINTF("%s %d, %d\n", __FUNCTION__, __LINE__, iError);
if (iError == 0)
{
if (g_ptCurPage && g_ptCurPage->ptNextPage)
{
g_ptCurPage = g_ptCurPage->ptNextPage;
return 0;
}
ptPage = malloc(sizeof(T_PageDesc));
if (ptPage)
{
ptPage->pucLcdFirstPosAtFile = pucTextFileMemCurPos;
ptPage->pucLcdNextPageFirstPosAtFile = g_pucLcdNextPosAtFile;
ptPage->ptPrePage = NULL;
ptPage->ptNextPage = NULL;
g_ptCurPage = ptPage;
DBG_PRINTF("%s %d, pos = 0x%x\n", __FUNCTION__, __LINE__, (unsigned int)ptPage->pucLcdFirstPosAtFile);
RecordPage(ptPage);
return 0;
}
else
{
return -1;
}
}
return iError;
}
int ShowPrePage(void)
{
int iError;
DBG_PRINTF("%s %d\n", __FUNCTION__, __LINE__);
if (!g_ptCurPage || !g_ptCurPage->ptPrePage)
{
return -1;
}
DBG_PRINTF("%s %d, pos = 0x%x\n", __FUNCTION__, __LINE__, (unsigned int)g_ptCurPage->ptPrePage->pucLcdFirstPosAtFile);
iError = ShowOnePage(g_ptCurPage->ptPrePage->pucLcdFirstPosAtFile);
if (iError == 0)
{
DBG_PRINTF("%s %d\n", __FUNCTION__, __LINE__);
g_ptCurPage = g_ptCurPage->ptPrePage;
}
return iError;
}