电子书总结

参考:https://blog.csdn.net/qq_21792169/article/details/51052666

1.框架

链接:https://pan.baidu.com/s/1qn0kP3zGUdU6VVtL8GWQTQ
提取码:mwwe

2.文件管理

工程目录结构:

include头文件目录:

包含所有头文件

config.h为配置文件

ifndef _CONFIG_H

define _CONFIG_H

include <stdio.h>

include <debug_manager.h>

define FB_DEVICE_NAME "/dev/fb0"

define COLOR_BACKGROUND 0xE7DBB5 /* 泛黄的纸 */

define COLOR_FOREGROUND 0x514438 /* 褐色字体 */

//#define DBG_PRINTF(...)
#define DBG_PRINTF DebugPrint

endif /* _CONFIG_H */

其中Makefile为:https://www.cnblogs.com/huangdengtao/p/12324579.html

3.流程图

我只画了一些。

链接:https://pan.baidu.com/s/1XpkjpMV8ztXE9kwxYODCLA
提取码:m31u

链接:https://pan.baidu.com/s/15MQXs7nPHUCQaXjEk0QxNA
提取码:4fba

4.各个模块的具体分析

display模块(display目录)

Makefile

obj-y += disp_manager.o
obj-y += fb.o

display_manager.h

ifndef _DISP_MANAGER_H

define _DISP_MANAGER_H

typedef struct DispOpr {
char name;
int iXres;
int iYres;
int iBpp;
int (
DeviceInit)(void);
int (ShowPixel)(int iPenX, int iPenY, unsigned int dwColor);
int (
CleanScreen)(unsigned int dwBackColor);
struct DispOpr *ptNext;
}T_DispOpr, *PT_DispOpr;

int RegisterDispOpr(PT_DispOpr ptDispOpr); // 注册链表
void ShowDispOpr(void); // 打印链表中的每个name
int DisplayInit(void); // fb设备注册金链表
int FBInit(void); // 把结构体注册到链表

endif /* _DISP_MANAGER_H */

display_manager.c

include <config.h>

include <disp_manager.h>

include <string.h>

static PT_DispOpr g_ptDispOprHead; // 链表头

int RegisterDispOpr(PT_DispOpr ptDispOpr)
{
PT_DispOpr ptTmp;

if (!g_ptDispOprHead)
{
g_ptDispOprHead = ptDispOpr;
ptDispOpr->ptNext = NULL;
}
else
{
ptTmp = g_ptDispOprHead;
while (ptTmp->ptNext)
{
ptTmp = ptTmp->ptNext;
}
ptTmp->ptNext = ptDispOpr;
ptDispOpr->ptNext = NULL;
}

return 0;
}

void ShowDispOpr(void)
{
int i = 0;
PT_DispOpr ptTmp = g_ptDispOprHead;

while (ptTmp)
{
printf("%02d %s\n", i++, ptTmp->name);
ptTmp = ptTmp->ptNext;
}
}

/* 根据name在链表中查找匹配的链表 */
PT_DispOpr GetDispOpr(char *pcName)
{
PT_DispOpr ptTmp = g_ptDispOprHead;

while (ptTmp)
{
if (strcmp(ptTmp->name, pcName) == 0)
{
return ptTmp;
}
ptTmp = ptTmp->ptNext;
}
return NULL;
}

int DisplayInit(void)
{
int iError;

iError = FBInit();

return iError;
}

fb.c

/* 这里是具体的设备的初始化了 */
#include <config.h>
#include <disp_manager.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <string.h>

/* 函数声明,用来初始化结构体中的成员函数 */
static int FBDeviceInit(void);
static int FBShowPixel(int iX, int iY, unsigned int dwColor);
static int FBCleanScreen(unsigned int dwBackColor);

static int g_fd;

static struct fb_var_screeninfo g_tFBVar;
static struct fb_fix_screeninfo g_tFBFix;
static unsigned char *g_pucFBMem;
static unsigned int g_dwScreenSize;

static unsigned int g_dwLineWidth;
static unsigned int g_dwPixelWidth;

static T_DispOpr g_tFBOpr = {
.name = "fb",
.DeviceInit = FBDeviceInit,
.ShowPixel = FBShowPixel,
.CleanScreen = FBCleanScreen,
};

static int FBDeviceInit(void)
{
int ret;

/* FB_DEVICE_NAME在配置文件中已经声明 */
g_fd = open(FB_DEVICE_NAME, O_RDWR);
if (0 > g_fd)
{
DBG_PRINTF("can't open %s\n", FB_DEVICE_NAME);
}

ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar);
if (ret < 0)
{
DBG_PRINTF("can't get fb's var\n");
return -1;
}

ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix);
if (ret < 0)
{
DBG_PRINTF("can't get fb's fix\n");
return -1;
}

g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8;
g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0);
if (0 > g_pucFBMem)
{
DBG_PRINTF("can't mmap\n");
return -1;
}

g_tFBOpr.iXres = g_tFBVar.xres;
g_tFBOpr.iYres = g_tFBVar.yres;
g_tFBOpr.iBpp = g_tFBVar.bits_per_pixel;

g_dwLineWidth = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;
g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;

return 0;
}

static int FBShowPixel(int iX, int iY, unsigned int dwColor)
{
unsigned char *pucFB;
unsigned short *pwFB16bpp;
unsigned int pdwFB32bpp;
unsigned short wColor16bpp; /
565 */
int iRed;
int iGreen;
int iBlue;

if ((iX >= g_tFBVar.xres) || (iY >= g_tFBVar.yres))
{
DBG_PRINTF("out of region\n");
return -1;
}

pucFB = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX;
pwFB16bpp = (unsigned short *)pucFB;
pdwFB32bpp = (unsigned int *)pucFB;

switch (g_tFBVar.bits_per_pixel)
{
case 8:
{
*pucFB = (unsigned char)dwColor;
break;
}
case 16:
{
iRed = (dwColor >> (16+3)) & 0x1f;
iGreen = (dwColor >> (8+2)) & 0x3f;
iBlue = (dwColor >> 3) & 0x1f;
wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;
*pwFB16bpp = wColor16bpp;
break;
}
case 32:
{
*pdwFB32bpp = dwColor;
break;
}
default :
{
DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);
return -1;
}
}

return 0;
}
/* 注意这里16bpp和32bpp清屏时时一位一位的清 */
static int FBCleanScreen(unsigned int dwBackColor)
{
unsigned char *pucFB;
unsigned short *pwFB16bpp;
unsigned int pdwFB32bpp;
unsigned short wColor16bpp; /
565 */
int iRed;
int iGreen;
int iBlue;
int i = 0;

pucFB = g_pucFBMem;
pwFB16bpp = (unsigned short *)pucFB;
pdwFB32bpp = (unsigned int *)pucFB;

switch (g_tFBVar.bits_per_pixel)
{
case 8:
{
memset(g_pucFBMem, dwBackColor, g_dwScreenSize);
break;
}
case 16:
{
iRed = (dwBackColor >> (16+3)) & 0x1f;
iGreen = (dwBackColor >> (8+2)) & 0x3f;
iBlue = (dwBackColor >> 3) & 0x1f;
wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;
while (i < g_dwScreenSize)
{
*pwFB16bpp = wColor16bpp;
pwFB16bpp++;
i += 2;
}
break;
}
case 32:
{
while (i < g_dwScreenSize)
{
*pdwFB32bpp = dwBackColor;
pdwFB32bpp++;
i += 4;
}
break;
}
default :
{
DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);
return -1;
}
}

return 0;
}

/* 把结构体注册到链表 */
int FBInit(void)
{
return RegisterDispOpr(&g_tFBOpr);
}

font模块(fonts目录)

Makefile

obj-y += ascii.o
obj-y += fonts_manager.o
obj-y += freetype.o
obj-y += gbk.o

fonts_manager.h

ifndef _FONTS_MANAGER_H

define _FONTS_MANAGER_H

typedef struct FontBitMap {
int iXLeft;
int iYTop;
int iXMax;
int iYMax;
int iBpp;
int iPitch; /* 对于单色位图, 两行象素之间的跨度 */
int iCurOriginX;
int iCurOriginY;
int iNextOriginX;
int iNextOriginY;
unsigned char *pucBuffer;
}T_FontBitMap, *PT_FontBitMap;

typedef struct FontOpr {
char name;
int (
FontInit)(char pcFontFile, unsigned int dwFontSize);
int (
GetFontBitmap)(unsigned int dwCode, PT_FontBitMap ptFontBitMap);
struct FontOpr *ptNext;
}T_FontOpr, *PT_FontOpr;

int RegisterFontOpr(PT_FontOpr ptFontOpr);
void ShowFontOpr(void);
int FontsInit(void); // 初始化ASCIIIni(void), GBKInit(void), FreeTypeInit(void)
int ASCIIInit(void);
int GBKInit(void);
int FreeTypeInit(void);
PT_FontOpr GetFontOpr(char *pcName);

endif /* _FONTS_MANAGER_H */

fonts_manager.c

include <config.h>

include <fonts_manager.h>

include <string.h>

static PT_FontOpr g_ptFontOprHead = NULL;

int RegisterFontOpr(PT_FontOpr ptFontOpr)
{
PT_FontOpr ptTmp;

if (!g_ptFontOprHead)
{
g_ptFontOprHead = ptFontOpr;
ptFontOpr->ptNext = NULL;
}
else
{
ptTmp = g_ptFontOprHead;
while (ptTmp->ptNext)
{
ptTmp = ptTmp->ptNext;
}
ptTmp->ptNext = ptFontOpr;
ptFontOpr->ptNext = NULL;
}

return 0;
}

void ShowFontOpr(void)
{
int i = 0;
PT_FontOpr ptTmp = g_ptFontOprHead;

while (ptTmp)
{
printf("%02d %s\n", i++, ptTmp->name);
ptTmp = ptTmp->ptNext;
}
}

PT_FontOpr GetFontOpr(char *pcName)
{
PT_FontOpr ptTmp = g_ptFontOprHead;

while (ptTmp)
{
if (strcmp(ptTmp->name, pcName) == 0)
{
return ptTmp;
}
ptTmp = ptTmp->ptNext;
}
return NULL;
}

int FontsInit(void)
{
int iError;

iError = ASCIIInit();
if (iError)
{
DBG_PRINTF("ASCIIInit error!\n");
return -1;
}

iError = GBKInit();
if (iError)
{
DBG_PRINTF("GBKInit error!\n");
return -1;
}

iError = FreeTypeInit();
if (iError)
{
DBG_PRINTF("FreeTypeInit error!\n");
return -1;
}

return 0;
}

asiic.c

include <config.h>

include <fonts_manager.h>

define FONTDATAMAX 4096

static int ASCIIFontInit(char *pcFontFile, unsigned int dwFontSize);
static int ASCIIGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap);

static T_FontOpr g_tASCIIFontOpr = {
.name = "ascii",
.FontInit = ASCIIFontInit,
.GetFontBitmap = ASCIIGetFontBitmap,
};

static const unsigned char fontdata_8x16[FONTDATAMAX] = {
/* 英文点阵(略) */
};

static int ASCIIFontInit(char *pcFontFile, unsigned int dwFontSize)
{
if (dwFontSize != 16)
{
//DBG_PRINTF("ASCII can't support %d font size\n", dwFontSize);
return -1;
}
return 0;
}

/* 编码的位图转化为字体的位图 */
static int ASCIIGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap)
{
int iPenX = ptFontBitMap->iCurOriginX;
int iPenY = ptFontBitMap->iCurOriginY;

if (dwCode > (unsigned int)0x80)
{
//DBG_PRINTF("don't support this code : 0x%x\n", dwCode);
return -1;
}

ptFontBitMap->iXLeft = iPenX;
ptFontBitMap->iYTop = iPenY - 16;
ptFontBitMap->iXMax = iPenX + 8;
ptFontBitMap->iYMax = iPenY;
ptFontBitMap->iBpp = 1;
ptFontBitMap->iPitch = 1;
ptFontBitMap->pucBuffer = (unsigned char *)&fontdata_8x16[dwCode * 16];;

ptFontBitMap->iNextOriginX = iPenX + 8;
ptFontBitMap->iNextOriginY = iPenY;

return 0;
}

int ASCIIInit(void)
{
return RegisterFontOpr(&g_tASCIIFontOpr);
}

gbk.c

include <config.h>

include <fonts_manager.h>

include <sys/types.h>

include <sys/stat.h>

include <fcntl.h>

include <sys/mman.h>

include <unistd.h>

static int GBKFontInit(char *pcFontFile, unsigned int dwFontSize);
static int GBKGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap);

static T_FontOpr g_tGBKFontOpr = {
.name = "gbk",
.FontInit = GBKFontInit,
.GetFontBitmap = GBKGetFontBitmap,
};

static int g_iFdHZK;
static unsigned char *g_pucHZKMem;
static unsigned char *g_pucHZKMemEnd;

static int GBKFontInit(char *pcFontFile, unsigned int dwFontSize)
{
struct stat tStat;

if (16 != dwFontSize)
{
DBG_PRINTF("GBK can't support %d fontsize\n", dwFontSize);
return -1;
}

g_iFdHZK = open(pcFontFile, O_RDONLY);
if (g_iFdHZK < 0)
{
DBG_PRINTF("can't open %s\n", pcFontFile);
return -1;
}
if(fstat(g_iFdHZK, &tStat))
{
DBG_PRINTF("can't get fstat\n");
return -1;
}
g_pucHZKMem = (unsigned char *)mmap(NULL , tStat.st_size, PROT_READ, MAP_SHARED, g_iFdHZK, 0);
if (g_pucHZKMem == (unsigned char *)-1)
{
DBG_PRINTF("can't mmap for hzk16\n");
return -1;
}
g_pucHZKMemEnd = g_pucHZKMem + tStat.st_size;
return 0;
}

static int GBKGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap)
{
int iArea;
int iWhere;

int iPenX = ptFontBitMap->iCurOriginX;
int iPenY = ptFontBitMap->iCurOriginY;

DBG_PRINTF("%s %s %d\n", FILE, FUNCTION, LINE);

if (dwCode & 0xffff0000)
{
DBG_PRINTF("don't support this code : 0x%x\n", dwCode);
return -1;
}

iArea = (int)(dwCode & 0xff) - 0xA1;
iWhere = (int)((dwCode >> 8) & 0xff) - 0xA1;

if ((iArea < 0) || (iWhere < 0))
{
DBG_PRINTF("%s %s %d\n", FILE, FUNCTION, LINE);
return -1;
}

ptFontBitMap->iXLeft = iPenX;
ptFontBitMap->iYTop = iPenY - 16;
ptFontBitMap->iXMax = iPenX + 16;
ptFontBitMap->iYMax = iPenY;
ptFontBitMap->iBpp = 1;
ptFontBitMap->iPitch = 2;
ptFontBitMap->pucBuffer = g_pucHZKMem + (iArea * 94 + iWhere)*32;;

if (ptFontBitMap->pucBuffer >= g_pucHZKMemEnd)
{
return -1;
}

ptFontBitMap->iNextOriginX = iPenX + 16;
ptFontBitMap->iNextOriginY = iPenY;

DBG_PRINTF("%s %s %d\n", FILE, FUNCTION, LINE);
return 0;
}

int GBKInit(void)
{
return RegisterFontOpr(&g_tGBKFontOpr);
}

freetype.c

include <config.h>

include <fonts_manager.h>

include <ft2build.h>

include FT_FREETYPE_H

include FT_GLYPH_H

static int FreeTypeFontInit(char *pcFontFile, unsigned int dwFontSize);
static int FreeTypeGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap);

static T_FontOpr g_tFreeTypeFontOpr = {
.name = "freetype",
.FontInit = FreeTypeFontInit,
.GetFontBitmap = FreeTypeGetFontBitmap,
};

static FT_Library g_tLibrary;
static FT_Face g_tFace;
static FT_GlyphSlot g_tSlot;

static int FreeTypeFontInit(char *pcFontFile, unsigned int dwFontSize)
{
int iError;

/* 显示矢量字体 /
iError = FT_Init_FreeType(&g_tLibrary ); /
initialize library /
/
error handling omitted */
if (iError)
{
DBG_PRINTF("FT_Init_FreeType failed\n");
return -1;
}

iError = FT_New_Face(g_tLibrary, pcFontFile, 0, &g_tFace); /* create face object /
/
error handling omitted */
if (iError)
{
DBG_PRINTF("FT_Init_FreeType failed\n");
return -1;
}

g_tSlot = g_tFace->glyph;

iError = FT_Set_Pixel_Sizes(g_tFace, dwFontSize, 0);
if (iError)
{
DBG_PRINTF("FT_Set_Pixel_Sizes failed : %d\n", dwFontSize);
return -1;
}

return 0;
}

static int FreeTypeGetFontBitmap(unsigned int dwCode, PT_FontBitMap ptFontBitMap)
{
int iError;
int iPenX = ptFontBitMap->iCurOriginX;
int iPenY = ptFontBitMap->iCurOriginY;
#if 0
FT_Vector tPen;

tPen.x = 0;
tPen.y = 0;

/* set transformation */
FT_Set_Transform(g_tFace, 0, &tPen);
#endif

/* load glyph image into the slot (erase previous one) */
//iError = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER );
iError = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
if (iError)
{
DBG_PRINTF("FT_Load_Char error for code : 0x%x\n", dwCode);
return -1;
}

//DBG_PRINTF("iPenX = %d, iPenY = %d, bitmap_left = %d, bitmap_top = %d, width = %d, rows = %d\n", iPenX, iPenY, g_tSlot->bitmap_left, g_tSlot->bitmap_top, g_tSlot->bitmap.width, g_tSlot->bitmap.rows);
ptFontBitMap->iXLeft = iPenX + g_tSlot->bitmap_left;
ptFontBitMap->iYTop = iPenY - g_tSlot->bitmap_top;
ptFontBitMap->iXMax = ptFontBitMap->iXLeft + g_tSlot->bitmap.width;
ptFontBitMap->iYMax = ptFontBitMap->iYTop + g_tSlot->bitmap.rows;
ptFontBitMap->iBpp = 1;
ptFontBitMap->iPitch = g_tSlot->bitmap.pitch;
ptFontBitMap->pucBuffer = g_tSlot->bitmap.buffer;

ptFontBitMap->iNextOriginX = iPenX + g_tSlot->advance.x / 64;
ptFontBitMap->iNextOriginY = iPenY;

//DBG_PRINTF("iXLeft = %d, iYTop = %d, iXMax = %d, iYMax = %d, iNextOriginX = %d, iNextOriginY = %d\n", ptFontBitMap->iXLeft, ptFontBitMap->iYTop, ptFontBitMap->iXMax, ptFontBitMap->iYMax, ptFontBitMap->iNextOriginX, ptFontBitMap->iNextOriginY);

return 0;
}

int FreeTypeInit(void)
{
return RegisterFontOpr(&g_tFreeTypeFontOpr);
}

enconding模块(enconding目录)

Makefile

obj-y += ascii.o
obj-y += encoding_manager.o
obj-y += utf-16be.o
obj-y += utf-16le.o
obj-y += utf-8.o

enconding_manager.h

ifndef _ENCODING_MANAGER_H

define _ENCODING_MANAGER_H

include <fonts_manager.h>

include <disp_manager.h>

typedef struct EncodingOpr {
char name;
int iHeadLen; // 头部的长度
PT_FontOpr ptFontOprSupportedHead; //
int (
isSupport)(unsigned char pucBufHead); // 支持
int (
GetCodeFrmBuf)(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode); // 得到编码
struct EncodingOpr *ptNext;
}T_EncodingOpr, *PT_EncodingOpr;

int RegisterEncodingOpr(PT_EncodingOpr ptEncodingOpr);
void ShowEncodingOpr(void);
PT_DispOpr GetDispOpr(char *pcName);
PT_EncodingOpr SelectEncodingOprForFile(unsigned char *pucFileBufHead); // 根据文件的头部编码在链表中寻找匹配的字形编码
int AddFontOprForEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr);
int DelFontOprFrmEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr);
int EncodingInit(void);
int AsciiEncodingInit(void);
int Utf16beEncodingInit(void);
int Utf16leEncodingInit(void);
int Utf8EncodingInit(void);

endif /* _ENCODING_MANAGER_H */

enconding_manager.c

include <config.h>

include <encoding_manager.h>

include <string.h>

include <stdlib.h>

static PT_EncodingOpr g_ptEncodingOprHead;

int RegisterEncodingOpr(PT_EncodingOpr ptEncodingOpr)
{
PT_EncodingOpr ptTmp;

if (!g_ptEncodingOprHead)
{
g_ptEncodingOprHead = ptEncodingOpr;
ptEncodingOpr->ptNext = NULL;
}
else
{
ptTmp = g_ptEncodingOprHead;
while (ptTmp->ptNext)
{
ptTmp = ptTmp->ptNext;
}
ptTmp->ptNext = ptEncodingOpr;
ptEncodingOpr->ptNext = NULL;
}

return 0;
}

void ShowEncodingOpr(void)
{
int i = 0;
PT_EncodingOpr ptTmp = g_ptEncodingOprHead;

while (ptTmp)
{
printf("%02d %s\n", i++, ptTmp->name);
ptTmp = ptTmp->ptNext;
}
}

PT_EncodingOpr SelectEncodingOprForFile(unsigned char *pucFileBufHead)
{
PT_EncodingOpr ptTmp = g_ptEncodingOprHead;

while (ptTmp)
{
if (ptTmp->isSupport(pucFileBufHead))
return ptTmp;
else
ptTmp = ptTmp->ptNext;
}
return NULL;
}

/* 在链表中加入每个编码支持的字形 */
int AddFontOprForEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr)
{
PT_FontOpr ptFontOprCpy;

if (!ptEncodingOpr || !ptFontOpr)
{
return -1;
}
else
{
ptFontOprCpy = malloc(sizeof(T_FontOpr));
if (!ptFontOprCpy)
{
return -1;
}
else
{
memcpy(ptFontOprCpy, ptFontOpr, sizeof(T_FontOpr));
ptFontOprCpy->ptNext = ptEncodingOpr->ptFontOprSupportedHead;
ptEncodingOpr->ptFontOprSupportedHead = ptFontOprCpy;
return 0;
}
}
}

/* 在链表中删除每个编码支持的字形 */
int DelFontOprFrmEncoding(PT_EncodingOpr ptEncodingOpr, PT_FontOpr ptFontOpr)
{
PT_FontOpr ptTmp;
PT_FontOpr ptPre;

if (!ptEncodingOpr || !ptFontOpr)
{
return -1;
}
else
{
ptTmp = ptEncodingOpr->ptFontOprSupportedHead;
if (strcmp(ptTmp->name, ptFontOpr->name) == 0)
{
/* 删除头节点 */
ptEncodingOpr->ptFontOprSupportedHead = ptTmp->ptNext;
free(ptTmp);
return 0;
}

ptPre = ptEncodingOpr->ptFontOprSupportedHead;
ptTmp = ptPre->ptNext;
while (ptTmp)
{
if (strcmp(ptTmp->name, ptFontOpr->name) == 0)
{
/* 从链表里取出、释放 */
ptPre->ptNext = ptTmp->ptNext;
free(ptTmp);
return 0;
}
else
{
ptPre = ptTmp;
ptTmp = ptTmp->ptNext;
}
}

return -1;
}
}

int EncodingInit(void)
{
int iError;

iError = AsciiEncodingInit();
if (iError)
{
DBG_PRINTF("AsciiEncodingInit error!\n");
return -1;
}

iError = Utf16leEncodingInit();
if (iError)
{
DBG_PRINTF("Utf16leEncodingInit error!\n");
return -1;
}

iError = Utf16beEncodingInit();
if (iError)
{
DBG_PRINTF("Utf16beEncodingInit error!\n");
return -1;
}

iError = Utf8EncodingInit();
if (iError)
{
DBG_PRINTF("Utf8EncodingInit error!\n");
return -1;
}

return 0;
}

asiic.c(具体的编码文件)

include <config.h>

include <encoding_manager.h>

include <string.h>

static int isAsciiCoding(unsigned char *pucBufHead);
static int AsciiGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);

static T_EncodingOpr g_tAsciiEncodingOpr = {
.name = "ascii",
.iHeadLen = 0,
.isSupport = isAsciiCoding,
.GetCodeFrmBuf = AsciiGetCodeFrmBuf,
};

static int isAsciiCoding(unsigned char *pucBufHead)
{
const char aStrUtf8[] = {0xEF, 0xBB, 0xBF, 0};
const char aStrUtf16le[] = {0xFF, 0xFE, 0};
const char aStrUtf16be[] = {0xFE, 0xFF, 0};

if (strncmp((const char)pucBufHead, aStrUtf8, 3) == 0)
{
/
UTF-8 /
return 0;
}
else if (strncmp((const char
)pucBufHead, aStrUtf16le, 2) == 0)
{
/* UTF-16 little endian /
return 0;
}
else if (strncmp((const char
)pucBufHead, aStrUtf16be, 2) == 0)
{
/* UTF-16 big endian */
return 0;
}
else
{
return 1;
}
}

/* Get字的编码 */
static int AsciiGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode)
{
unsigned char *pucBuf = pucBufStart;
unsigned char c = *pucBuf;

/* 当判断出来不支持UTF-8,UTF-16Be和UTF-16le后。还需要判断为asiic值还是GBK码
* (pucBuf < pucBufEnd) && (c < (unsigned char)0x80):判断为asiic值
* ((pucBuf + 1) < pucBufEnd) && (c >= (unsigned char)0x80):判断为GBK码。注:因为GBK码为2字节所以这里需要加1
/
if ((pucBuf < pucBufEnd) && (c < (unsigned char)0x80))
{
/
返回ASCII码 */
*pdwCode = (unsigned int)c;
return 1;
}

if (((pucBuf + 1) < pucBufEnd) && (c >= (unsigned char)0x80))
{
/* 返回GBK码 */
*pdwCode = pucBuf[0] + (((unsigned int)pucBuf[1])<<8);
return 2;
}

if (pucBuf < pucBufEnd)
{
/* 可能文件有损坏, 但是还是返回一个码, 即使它是错误的 */
pdwCode = (unsigned int)c;
return 1;
}
else
{
/
文件处理完毕 */
return 0;
}
}

/* 使当前编码支持freetype, ascii, gbk字形。同时注册链表 */
int AsciiEncodingInit(void)
{
AddFontOprForEncoding(&g_tAsciiEncodingOpr, GetFontOpr("freetype"));
AddFontOprForEncoding(&g_tAsciiEncodingOpr, GetFontOpr("ascii"));
AddFontOprForEncoding(&g_tAsciiEncodingOpr, GetFontOpr("gbk"));
return RegisterEncodingOpr(&g_tAsciiEncodingOpr);
}

utf-8.c

include <config.h>

include <encoding_manager.h>

include <string.h>

static int isUtf8Coding(unsigned char *pucBufHead);
static int Utf8GetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);

static T_EncodingOpr g_tUtf8EncodingOpr = {
.name = "utf-8",
.iHeadLen = 3,
.isSupport = isUtf8Coding,
.GetCodeFrmBuf = Utf8GetCodeFrmBuf,
};

static int isUtf8Coding(unsigned char pucBufHead)
{
const char aStrUtf8[] = {0xEF, 0xBB, 0xBF, 0};
if (strncmp((const char
)pucBufHead, aStrUtf8, 3) == 0)
{
/* UTF-8 */
return 1;
}
else
{
return 0;
}
}

/* 获得前导为1的位的个数
* 比如二进制数 11001111 的前导1有2位
* 11100001 的前导1有3位
*/
static int GetPreOneBits(unsigned char ucVal)
{
int i;
int j = 0;

for (i = 7; i >= 0; i--)
{
if (!(ucVal & (1<<i)))
break;
else
j++;
}
return j;

}

static int Utf8GetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode)
{
#if 0
对于UTF-8编码中的任意字节B,如果B的第一位为0,则B为ASCII码,并且B独立的表示一个字符;
如果B的第一位为1,第二位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的一个字节,并且不为字符的第一个字节编码;
如果B的前两位为1,第三位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由两个字节表示;
如果B的前三位为1,第四位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由三个字节表示;
如果B的前四位为1,第五位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由四个字节表示;

因此,对UTF-8编码中的任意字节,根据第一位,可判断是否为ASCII字符;
根据前二位,可判断该字节是否为一个字符编码的第一个字节;
根据前四位(如果前两位均为1),可确定该字节为字符编码的第一个字节,并且可判断对应的字符由几个字节表示;
根据前五位(如果前四位为1),可判断编码是否有错误或数据传输过程中是否有错误。
#endif

int i;
int iNum;
unsigned char ucVal;
unsigned int dwSum = 0;

if (pucBufStart >= pucBufEnd)
{
/* 文件结束 /
return 0;
}
/
注意下面的构造 */
ucVal = pucBufStart[0];
iNum = GetPreOneBits(pucBufStart[0]);

if ((pucBufStart + iNum) > pucBufEnd)
{
/* 文件结束 */
return 0;
}

if (iNum == 0)
{
/* ASCII */
*pdwCode = pucBufStart[0];
return 1;
}
else
{
ucVal = ucVal << iNum;
ucVal = ucVal >> iNum;
dwSum += ucVal;
for (i = 1; i < iNum; i++)
{
ucVal = pucBufStart[i] & 0x3f;
dwSum = dwSum << 6;
dwSum += ucVal;
}
*pdwCode = dwSum;
return iNum;
}
}

int Utf8EncodingInit(void)
{
AddFontOprForEncoding(&g_tUtf8EncodingOpr, GetFontOpr("freetype"));
AddFontOprForEncoding(&g_tUtf8EncodingOpr, GetFontOpr("ascii"));
return RegisterEncodingOpr(&g_tUtf8EncodingOpr);
}

utf-16be.c

include <config.h>

include <encoding_manager.h>

include <string.h>

static int isUtf16beCoding(unsigned char *pucBufHead);
static int Utf16beGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);

static T_EncodingOpr g_tUtf16beEncodingOpr = {
.name = "utf-16be",
.iHeadLen = 2,
.isSupport = isUtf16beCoding,
.GetCodeFrmBuf = Utf16beGetCodeFrmBuf,
};

/* 用两字节表示一个字:注意大字节序和小字节序 */
static int isUtf16beCoding(unsigned char *pucBufHead)
{
const char aStrUtf16be[] = {0xFE, 0xFF, 0};

if (strncmp((const char)pucBufHead, aStrUtf16be, 2) == 0)
{
/
UTF-16 big endian */
return 1;
}
else
{
return 0;
}
}

static int Utf16beGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode)
{
if (pucBufStart + 1 < pucBufEnd)
{
pdwCode = (((unsigned int)pucBufStart[0])<<8) + pucBufStart[1];
return 2;
}
else
{
/
文件结束 */
return 0;
}
}

int Utf16beEncodingInit(void)
{
AddFontOprForEncoding(&g_tUtf16beEncodingOpr, GetFontOpr("freetype"));
AddFontOprForEncoding(&g_tUtf16beEncodingOpr, GetFontOpr("ascii"));
return RegisterEncodingOpr(&g_tUtf16beEncodingOpr);
}

utf-16le.c

include <config.h>

include <encoding_manager.h>

include <string.h>

static int isUtf16leCoding(unsigned char *pucBufHead);
static int Utf16leGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode);

static T_EncodingOpr g_tUtf16leEncodingOpr = {
.name = "utf-16le",
.iHeadLen = 2,
.isSupport = isUtf16leCoding,
.GetCodeFrmBuf = Utf16leGetCodeFrmBuf,
};

static int isUtf16leCoding(unsigned char *pucBufHead)
{
const char aStrUtf16le[] = {0xFF, 0xFE, 0};
if (strncmp((const char )pucBufHead, aStrUtf16le, 2) == 0)
{
/
UTF-16 little endian */
return 1;
}
else
{
return 0;
}
}

static int Utf16leGetCodeFrmBuf(unsigned char *pucBufStart, unsigned char *pucBufEnd, unsigned int *pdwCode)
{
if (pucBufStart + 1 < pucBufEnd)
{
pdwCode = (((unsigned int)pucBufStart[1])<<8) + pucBufStart[0];
return 2;
}
else
{
/
文件结束 */
return 0;
}
}

int Utf16leEncodingInit(void)
{
AddFontOprForEncoding(&g_tUtf16leEncodingOpr, GetFontOpr("freetype"));
AddFontOprForEncoding(&g_tUtf16leEncodingOpr, GetFontOpr("ascii"));
return RegisterEncodingOpr(&g_tUtf16leEncodingOpr);
}

input模块(input目录)

Makefile

obj-y += input_manager.o
obj-y += stdin.o
obj-y += touchscreen.o

input_manager.h

ifndef _INPUT_MANAGER_H

define _INPUT_MANAGER_H

include <sys/time.h>

include <pthread.h>

define INPUT_TYPE_STDIN 0

define INPUT_TYPE_TOUCHSCREEN 1

define INPUT_VALUE_UP 0

define INPUT_VALUE_DOWN 1

define INPUT_VALUE_EXIT 2

define INPUT_VALUE_UNKNOWN -1

typedef struct InputEvent {
struct timeval tTime;
int iType; /* stdin, touchsceen /
int iVal; /
*/
}T_InputEvent, *PT_InputEvent;

typedef struct InputOpr {
char name;
pthread_t tTreadID; // 线程ID
int (
DeviceInit)(void);
int (DeviceExit)(void);
int (
GetInputEvent)(PT_InputEvent ptInputEvent);
struct InputOpr *ptNext;
}T_InputOpr, *PT_InputOpr;

int InputInit(void);
int RegisterInputOpr(PT_InputOpr ptInputOpr);
void ShowInputOpr(void);
int AllInputDevicesInit(void);
int GetInputEvent(PT_InputEvent ptInputEvent);

int StdinInit(void);
int TouchScreenInit(void);

endif /* _INPUT_MANAGER_H */

input_manager.c

include <config.h>

include <input_manager.h>

include <string.h>

static PT_InputOpr g_ptInputOprHead; // PT_InputOpr结构体
static T_InputEvent g_tInputEvent; // T_InputEvent 结构体

static pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER; // 互斥锁
static pthread_cond_t g_tConVar = PTHREAD_COND_INITIALIZER; // 条件变量

int RegisterInputOpr(PT_InputOpr ptInputOpr)
{
PT_InputOpr ptTmp;

if (!g_ptInputOprHead)
{
g_ptInputOprHead = ptInputOpr;
ptInputOpr->ptNext = NULL;
}
else
{
ptTmp = g_ptInputOprHead;
while (ptTmp->ptNext)
{
ptTmp = ptTmp->ptNext;
}
ptTmp->ptNext = ptInputOpr;
ptInputOpr->ptNext = NULL;
}

return 0;
}

void ShowInputOpr(void)
{
int i = 0;
PT_InputOpr ptTmp = g_ptInputOprHead;

while (ptTmp)
{
printf("%02d %s\n", i++, ptTmp->name);
ptTmp = ptTmp->ptNext;
}
}

/* 线程函数 */
static void *InputEventTreadFunction(void *pVoid)
{
T_InputEvent tInputEvent;

/* 定义函数指针 /
int (
GetInputEvent)(PT_InputEvent ptInputEvent);
GetInputEvent = (int (*)(PT_InputEvent))pVoid;

while (1)
{
if(0 == GetInputEvent(&tInputEvent))
{
/* 唤醒主线程, 把tInputEvent的值赋给一个全局变量 /
/
访问临界资源前,先获得互斥量 /
/
上锁 */
pthread_mutex_lock(&g_tMutex);
g_tInputEvent = tInputEvent;

/* 唤醒主线程 */
pthread_cond_signal(&g_tConVar);

/* 释放互斥量 */
pthread_mutex_unlock(&g_tMutex);
}
}

return NULL;
}

int AllInputDevicesInit(void)
{
PT_InputOpr ptTmp = g_ptInputOprHead;
int iError = -1;

while (ptTmp)
{
if (0 == ptTmp->DeviceInit())
{
/* 创建子线程 */
pthread_create(&ptTmp->tTreadID, NULL, InputEventTreadFunction, ptTmp->GetInputEvent);
iError = 0;
}
ptTmp = ptTmp->ptNext;
}
return iError;
}

int GetInputEvent(PT_InputEvent ptInputEvent)
{
/* 休眠 */
pthread_mutex_lock(&g_tMutex);
pthread_cond_wait(&g_tConVar, &g_tMutex);

/* 被唤醒后,返回数据 */
*ptInputEvent = g_tInputEvent;
pthread_mutex_unlock(&g_tMutex);
return 0;
}

int InputInit(void)
{
int iError;
iError = StdinInit();
iError |= TouchScreenInit();
return iError;
}

stdin.c

/* 使用轮询的方式去访问 */
#include <input_manager.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>

static int StdinDevInit(void)
{
struct termios tTTYState;

//get the terminal state
tcgetattr(STDIN_FILENO, &tTTYState);

//turn off canonical mode
tTTYState.c_lflag &= ~ICANON;
//minimum of number input read.
tTTYState.c_cc[VMIN] = 1; /* 有一个数据时就立刻返回 */

//set the terminal attributes.
tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState);

return 0;
}

static int StdinDevExit(void)
{

struct termios tTTYState;

//get the terminal state
tcgetattr(STDIN_FILENO, &tTTYState);

//turn on canonical mode
tTTYState.c_lflag |= ICANON;

//set the terminal attributes.
tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState);
return 0;
}

static int StdinGetInputEvent(PT_InputEvent ptInputEvent)
{
/* 如果有数据就读取、处理、返回
* 如果没有数据, 立刻返回, 不等待
*/

/* select, poll 可以参数 UNIX环境高级编程 */

char c;

/* 处理数据 */
ptInputEvent->iType = INPUT_TYPE_STDIN;

c = fgetc(stdin); /* 会休眠直到有输入 */
gettimeofday(&ptInputEvent->tTime, NULL);

if (c == 'u')
{
ptInputEvent->iVal = INPUT_VALUE_UP;
}
else if (c == 'n')
{
ptInputEvent->iVal = INPUT_VALUE_DOWN;
}
else if (c == 'q')
{
ptInputEvent->iVal = INPUT_VALUE_EXIT;
}
else
{
ptInputEvent->iVal = INPUT_VALUE_UNKNOWN;
}
return 0;
}

static T_InputOpr g_tStdinOpr = {
.name = "stdin",
.DeviceInit = StdinDevInit,
.DeviceExit = StdinDevExit,
.GetInputEvent = StdinGetInputEvent,
};

int StdinInit(void)
{
return RegisterInputOpr(&g_tStdinOpr);
}

touchscreen.c

include <config.h>

include <input_manager.h>

include <stdlib.h>

include <tslib.h>

include <draw.h>

/* 参考tslib里的ts_print.c */

static struct tsdev *g_tTSDev;
static int giXres;
static int giYres;

/* 注意: 由于要用到LCD的分辨率, 此函数要在SelectAndInitDisplay之后调用 */
static int TouchScreenDevInit(void)
{
char *pcTSName = NULL;

/* getenv从环境中取字符串,获取环境变量的值
* 指定触摸屏设备 TSLIB_TSDEVICE=/dev/input/touchscreen0
/
if ((pcTSName = getenv("TSLIB_TSDEVICE")) != NULL )
{
g_tTSDev = ts_open(pcTSName, 0); /
以阻塞方式打开 */
}
else
{
g_tTSDev = ts_open("/dev/event0", 1);
}

if (!g_tTSDev) {
DBG_PRINTF(APP_ERR"ts_open error!\n");
return -1;
}

/* 配置 */
if (ts_config(g_tTSDev)) {
DBG_PRINTF("ts_config error!\n");
return -1;
}

if (GetDispResolution(&giXres, &giYres))
{
return -1;
}

return 0;
}

static int TouchScreenDevExit(void)
{
return 0;
}

static int isOutOf500ms(struct timeval *ptPreTime, struct timeval *ptNowTime)
{
int iPreMs;
int iNowMs;

iPreMs = ptPreTime->tv_sec * 1000 + ptPreTime->tv_usec / 1000;
iNowMs = ptNowTime->tv_sec * 1000 + ptNowTime->tv_usec / 1000;

return (iNowMs > iPreMs + 500);
}

static int TouchScreenGetInputEvent(PT_InputEvent ptInputEvent)
{
struct ts_sample tSamp;
struct ts_sample tSampPressed;
struct ts_sample tSampReleased;
int iRet;
int bStart = 0;
int iDelta;

static struct timeval tPreTime;

while (1)
{
iRet = ts_read(g_tTSDev, &tSamp, 1); /* 如果无数据则休眠 /
if (iRet == 1)
{
if ((tSamp.pressure > 0) && (bStart == 0))
{
/
刚按下 /
/
记录刚开始压下的点 */
tSampPressed = tSamp;
bStart = 1;
}

if (tSamp.pressure <= 0)
{
/* 松开 */
tSampReleased = tSamp;

/* 处理数据 */
if (!bStart)
{
return -1;
}
else
{
iDelta = tSampReleased.x - tSampPressed.x;
ptInputEvent->tTime = tSampReleased.tv;
ptInputEvent->iType = INPUT_TYPE_TOUCHSCREEN;

if (iDelta > giXres/5)
{
/* 翻到上一页 /
ptInputEvent->iVal = INPUT_VALUE_UP;
}
else if (iDelta < 0 - giXres/5)
{
/
翻到下一页 */
ptInputEvent->iVal = INPUT_VALUE_DOWN;
}
else
{
ptInputEvent->iVal = INPUT_VALUE_UNKNOWN;
}
return 0;
}
}
}
else
{
return -1;
}
}

return 0;
}

static T_InputOpr g_tTouchScreenOpr = {
.name = "touchscreen",
.DeviceInit = TouchScreenDevInit,
.DeviceExit = TouchScreenDevExit,
.GetInputEvent = TouchScreenGetInputEvent,
};

int TouchScreenInit(void)
{
return RegisterInputOpr(&g_tTouchScreenOpr);
}

debug模块(debug目录)

Makefile

obj-y += debug_manager.o
obj-y += stdout.o
obj-y += netprint.o

debug_manager.h

ifndef _DEBUG_MANAGER_H

define _DEBUG_MANAGER_H

define APP_EMERG "<0>" /* system is unusable */

define APP_ALERT "<1>" /* action must be taken immediately */

define APP_CRIT "<2>" /* critical conditions */

define APP_ERR "<3>" /* error conditions */

define APP_WARNING "<4>" /* warning conditions */

define APP_NOTICE "<5>" /* normal but significant condition */

define APP_INFO "<6>" /* informational */

define APP_DEBUG "<7>" /* debug-level messages */

define DEFAULT_DBGLEVEL 4

typedef struct DebugOpr {
char name;
int isCanUse;
int (
DebugInit)(void);
int (DebugExit)(void);
int (
DebugPrint)(char *strData);
struct DebugOpr *ptNext;
}T_DebugOpr, *PT_DebugOpr;

int RegisterDebugOpr(PT_DebugOpr ptDebugOpr);
void ShowDebugOpr(void);
PT_DebugOpr GetDebugOpr(char *pcName);
int SetDbgLevel(char *strBuf);
int SetDbgChanel(char *strBuf);
int DebugInit(void);
int DebugPrint(const char *pcFormat, ...);
int InitDebugChanel(void);

endif /* _DEBUG_MANAGER_H */

ifndef _DEBUG_MANAGER_H

define _DEBUG_MANAGER_H

/* 打印优先级设置 /
#define APP_EMERG "<0>" /
system is unusable /
#define APP_ALERT "<1>" /
action must be taken immediately /
#define APP_CRIT "<2>" /
critical conditions /
#define APP_ERR "<3>" /
error conditions /
#define APP_WARNING "<4>" /
warning conditions /
#define APP_NOTICE "<5>" /
normal but significant condition /
#define APP_INFO "<6>" /
informational /
#define APP_DEBUG "<7>" /
debug-level messages */

define DEFAULT_DBGLEVEL 4

typedef struct DebugOpr {
char name;
int isCanUse;
int (
DebugInit)(void);
int (DebugExit)(void);
int (
DebugPrint)(char *strData);
struct DebugOpr *ptNext;
}T_DebugOpr, *PT_DebugOpr;

int RegisterDebugOpr(PT_DebugOpr ptDebugOpr);
void ShowDebugOpr(void);
PT_DebugOpr GetDebugOpr(char *pcName);
int SetDbgLevel(char *strBuf);
int SetDbgChanel(char *strBuf);
int DebugInit(void);
int DebugPrint(const char *pcFormat, ...);
int InitDebugChanel(void);

endif /* _DEBUG_MANAGER_H */

debug_manager.c

include <config.h>

include <debug_manager.h>

include <string.h>

include <stdio.h>

include <stdarg.h>

static PT_DebugOpr g_ptDebugOprHead;
static int g_iDbgLevelLimit = 8;

int RegisterDebugOpr(PT_DebugOpr ptDebugOpr)
{
PT_DebugOpr ptTmp;

if (!g_ptDebugOprHead)
{
g_ptDebugOprHead = ptDebugOpr;
ptDebugOpr->ptNext = NULL;
}
else
{
ptTmp = g_ptDebugOprHead;
while (ptTmp->ptNext)
{
ptTmp = ptTmp->ptNext;
}
ptTmp->ptNext = ptDebugOpr;
ptDebugOpr->ptNext = NULL;
}

return 0;
}

void ShowDebugOpr(void)
{
int i = 0;
PT_DebugOpr ptTmp = g_ptDebugOprHead;

while (ptTmp)
{
printf("%02d %s\n", i++, ptTmp->name);
ptTmp = ptTmp->ptNext;
}
}

PT_DebugOpr GetDebugOpr(char *pcName)
{
PT_DebugOpr ptTmp = g_ptDebugOprHead;

while (ptTmp)
{
if (strcmp(ptTmp->name, pcName) == 0)
{
return ptTmp;
}
ptTmp = ptTmp->ptNext;
}
return NULL;
}

/* strBuf = "dbglevel=6" */
int SetDbgLevel(char *strBuf)
{
g_iDbgLevelLimit = strBuf[9] - '0';
return 0;
}

/*
* stdout=0 : 关闭stdout打印
* stdout=1 : 打开stdout打印
* netprint=0 : 关闭netprint打印
* netprint=1 : 打开netprint打印
*/

int SetDbgChanel(char *strBuf)
{
char pStrTmp;
char strName[100];
PT_DebugOpr ptTmp;
/
strchr函数功能为在一个串中查找给定字符的第一个匹配之处 */
pStrTmp = strchr(strBuf, '=');
if (!pStrTmp)
{
return -1;
}
else
{
strncpy(strName, strBuf, pStrTmp-strBuf);
strName[pStrTmp-strBuf] = '\0';
ptTmp = GetDebugOpr(strName);
if (!ptTmp)
return -1;

if (pStrTmp[1] == '0')
ptTmp->isCanUse = 0;
else
ptTmp->isCanUse = 1;
return 0;
}

}

int DebugPrint(const char *pcFormat, ...)
{
char strTmpBuf[1000];
char *pcTmp;
va_list tArg;
int iNum;
PT_DebugOpr ptTmp = g_ptDebugOprHead;
int dbglevel = DEFAULT_DBGLEVEL;

/* va_start函数来获取参数列表中的参数 */
va_start (tArg, pcFormat);

/* int vsprintf(char *string, char *format, va_list param);//将param 按格式format写入字符串string中 */
iNum = vsprintf (strTmpBuf, pcFormat, tArg);
va_end (tArg);
strTmpBuf[iNum] = '\0';

pcTmp = strTmpBuf;

/* 根据打印级别决定是否打印 */
if ((strTmpBuf[0] == '<') && (strTmpBuf[2] == '>'))
{
dbglevel = strTmpBuf[1] - '0';
if (dbglevel >= 0 && dbglevel <= 9)
{
pcTmp = strTmpBuf + 3;
}
else
{
dbglevel = DEFAULT_DBGLEVEL;
}
}

if (dbglevel > g_iDbgLevelLimit)
{
return -1;
}

/* 调用链表中所有isCanUse为1的结构体的DebugPrint函数 */
while (ptTmp)
{
if (ptTmp->isCanUse)
{
ptTmp->DebugPrint(pcTmp);
}
ptTmp = ptTmp->ptNext;
}

return 0;

}

int DebugInit(void)
{
int iError;

iError = StdoutInit();
iError |= NetPrintInit();
return iError;
}

int InitDebugChanel(void)
{
PT_DebugOpr ptTmp = g_ptDebugOprHead;
while (ptTmp)
{
if (ptTmp->isCanUse && ptTmp->DebugInit)
{
ptTmp->DebugInit();
}
ptTmp = ptTmp->ptNext;
}

return 0;}

stdout.c

include <config.h>

include <debug_manager.h>

include <stdio.h>

include <string.h>

static int StdoutDebugPrint(char strData)
{
/
直接把输出信息用printf打印出来 */
printf("%s", strData);
return strlen(strData);
}

static T_DebugOpr g_tStdoutDbgOpr = {
.name = "stdout",
.isCanUse = 1,
.DebugPrint = StdoutDebugPrint,
};

int StdoutInit(void)
{
return RegisterDebugOpr(&g_tStdoutDbgOpr);
}

netprint.c(不难看出采用的是UDP协议)

include <config.h>

include <debug_manager.h>

include <sys/types.h> /* See NOTES */

include <sys/socket.h>

include <string.h>

include <sys/socket.h>

include <netinet/in.h>

include <arpa/inet.h>

include <unistd.h>

include <stdio.h>

include <signal.h>

include <stdlib.h>

include <pthread.h>

define SERVER_PORT 5678

/* 分配16k的buf /
#define PRINT_BUF_SIZE (16
1024)

static int g_iSocketServer;
static struct sockaddr_in g_tSocketServerAddr;
static struct sockaddr_in g_tSocketClientAddr;
static int g_iHaveConnected = 0;
static char *g_pcNetPrintBuf;
static int g_iReadPos = 0;
static int g_iWritePos = 0;

static pthread_t g_tSendTreadID;
static pthread_t g_tRecvTreadID;

static pthread_mutex_t g_tNetDbgSendMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t g_tNetDbgSendConVar = PTHREAD_COND_INITIALIZER;

/* 环形缓冲区 */
static int isFull(void)
{
return (((g_iWritePos + 1) % PRINT_BUF_SIZE) == g_iReadPos);
}

static int isEmpty(void)
{
return (g_iWritePos == g_iReadPos);
}

static int PutData(char cVal)
{
if (isFull())
return -1;
else
{
g_pcNetPrintBuf[g_iWritePos] = cVal;
g_iWritePos = (g_iWritePos + 1) % PRINT_BUF_SIZE;
return 0;
}
}

static int GetData(char *pcVal)
{
if (isEmpty())
return -1;
else
{
*pcVal = g_pcNetPrintBuf[g_iReadPos];
g_iReadPos = (g_iReadPos + 1) % PRINT_BUF_SIZE;
return 0;
}
}

static void *NetDbgSendTreadFunction(void *pVoid)
{
char strTmpBuf[512];
char cVal;
int i;
int iAddrLen;
int iSendLen;

while (1)
{
/* 平时休眠 */
pthread_mutex_lock(&g_tNetDbgSendMutex);
pthread_cond_wait(&g_tNetDbgSendConVar, &g_tNetDbgSendMutex);
pthread_mutex_unlock(&g_tNetDbgSendMutex);

while (g_iHaveConnected && !isEmpty())
{
i = 0;

/* 把环形缓冲区的数据取出来, 最多取512字节 */
while ((i < 512) && (0 == GetData(&cVal)))
{
strTmpBuf[i] = cVal;
i++;
}

/* 执行到这里, 表示被唤醒 /
/
用sendto函数发送打印信息给客户端 */
iAddrLen = sizeof(struct sockaddr);
iSendLen = sendto(g_iSocketServer, strTmpBuf, i, 0,
(const struct sockaddr *)&g_tSocketClientAddr, iAddrLen);

}

}
return NULL;
}

static void *NetDbgRecvTreadFunction(void *pVoid)
{
socklen_t iAddrLen;
int iRecvLen;
char ucRecvBuf[1000];
struct sockaddr_in tSocketClientAddr;

while (1)
{
iAddrLen = sizeof(struct sockaddr);
DBG_PRINTF("in NetDbgRecvTreadFunction\n");
iRecvLen = recvfrom(g_iSocketServer, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);

if (iRecvLen > 0)
{
ucRecvBuf[iRecvLen] = '\0';
DBG_PRINTF("netprint.c get msg: %s\n", ucRecvBuf);

/* 解析数据:
* setclient : 设置接收打印信息的客户端
* dbglevel=0,1,2... : 修改打印级别
* stdout=0 : 关闭stdout打印
* stdout=1 : 打开stdout打印
* netprint=0 : 关闭netprint打印
* netprint=1 : 打开netprint打印
*/
if (strcmp(ucRecvBuf, "setclient") == 0)
{
g_tSocketClientAddr = tSocketClientAddr;
g_iHaveConnected = 1;
}
else if (strncmp(ucRecvBuf, "dbglevel=", 9) == 0)
{
SetDbgLevel(ucRecvBuf);
}
else
{
SetDbgChanel(ucRecvBuf);
}
}

}
return NULL;
}

static int NetDbgInit(void)
{
/* socket初始化 */
int iRet;

g_iSocketServer = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == g_iSocketServer)
{
printf("socket error!\n");
return -1;
}

g_tSocketServerAddr.sin_family = AF_INET;
g_tSocketServerAddr.sin_port = htons(SERVER_PORT); /* host to net, short */
g_tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
memset(g_tSocketServerAddr.sin_zero, 0, 8);

iRet = bind(g_iSocketServer, (const struct sockaddr *)&g_tSocketServerAddr, sizeof(struct sockaddr));
if (-1 == iRet)
{
printf("bind error!\n");
return -1;
}

g_pcNetPrintBuf = malloc(PRINT_BUF_SIZE);
if (NULL == g_pcNetPrintBuf)
{
close(g_iSocketServer);
return -1;
}

/* 创建netprint发送线程: 它用来发送打印信息给客户端 */
pthread_create(&g_tSendTreadID, NULL, NetDbgSendTreadFunction, NULL);

/* 创建netprint接收线否: 用来接收控制信息,比如修改打印级别,打开/关闭打印 */
pthread_create(&g_tRecvTreadID, NULL, NetDbgRecvTreadFunction, NULL);

return 0;
}

static int NetDbgExit(void)
{
/* 关闭socket,... */
close(g_iSocketServer);
free(g_pcNetPrintBuf);
}

static int NetDbgPrint(char strData)
{
/
把数据放入环形缓冲区 */
int i;

for (i = 0; i < strlen(strData); i++)
{
if (0 != PutData(strData[i]))
break;
}

/* 如果已经有客户端连接了, 就把数据通过网络发送给客户端 /
/
唤醒netprint的发送线程 */
pthread_mutex_lock(&g_tNetDbgSendMutex);
pthread_cond_signal(&g_tNetDbgSendConVar);
pthread_mutex_unlock(&g_tNetDbgSendMutex);

return i;

}

static T_DebugOpr g_tNetDbgOpr = {
.name = "netprint",
.isCanUse = 1,
.DebugInit = NetDbgInit,
.DebugExit = NetDbgExit,
.DebugPrint = NetDbgPrint,
};

int NetPrintInit(void)
{
return RegisterDebugOpr(&g_tNetDbgOpr);
}

netprintclien.c(工程目录下)

include <sys/types.h> /* See NOTES */

include <sys/socket.h>

include <string.h>

include <sys/socket.h>

include <netinet/in.h>

include <arpa/inet.h>

include <unistd.h>

include <stdio.h>

/* socket
* connect
* send/recv
*/

define SERVER_PORT 5678

/*
* ./netprint_client <server_ip> dbglevel=<0-9>
* ./netprint_client <server_ip> stdout=0|1
* ./netprint_client <server_ip> netprint=0|1
* ./netprint_client <server_ip> show // setclient,并且接收打印信息
*/

int main(int argc, char **argv)
{
int iSocketClient;
struct sockaddr_in tSocketServerAddr;

int iRet;
unsigned char ucRecvBuf[1000];
int iSendLen;
int iRecvLen;
int iAddrLen;

if (argc != 3)
{
printf("Usage:\n");
printf("%s <server_ip> dbglevel=<0-9>\n", argv[0]);
printf("%s <server_ip> stdout=0|1\n", argv[0]);
printf("%s <server_ip> netprint=0|1\n", argv[0]);
printf("%s <server_ip> show\n", argv[0]);
return -1;
}

iSocketClient = socket(AF_INET, SOCK_DGRAM, 0);

tSocketServerAddr.sin_family = AF_INET;
tSocketServerAddr.sin_port = htons(SERVER_PORT); /* host to net, short */
//tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))
{
printf("invalid server_ip\n");
return -1;
}
memset(tSocketServerAddr.sin_zero, 0, 8);

if (strcmp(argv[2], "show") == 0)
{
/* 发送数据 */
iAddrLen = sizeof(struct sockaddr);
iSendLen = sendto(iSocketClient, "setclient", 9, 0,
(const struct sockaddr *)&tSocketServerAddr, iAddrLen);

while (1)
{
/* 循环: 从网络读数据, 打印出来 */
iAddrLen = sizeof(struct sockaddr);
iRecvLen = recvfrom(iSocketClient, ucRecvBuf, 999, 0, (struct sockaddr )&tSocketServerAddr, &iAddrLen);
if (iRecvLen > 0)
{
ucRecvBuf[iRecvLen] = '\0';
printf("%s\n", ucRecvBuf);
}
}
}
else
{
/
发送数据 */
iAddrLen = sizeof(struct sockaddr);
iSendLen = sendto(iSocketClient, argv[2], strlen(argv[2]), 0,
(const struct sockaddr *)&tSocketServerAddr, iAddrLen);
}

return 0;
}

draw模块(draw目录)

Makefile

obj-y += draw.o

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;

/* 在lcd上第一个字符在文件中的位置 */
static unsigned char g_pucLcdFirstPosAtFile;
/
lcd上下一页的第一个字符在文件中的位置 */
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 GetDispResolution(int *piXres, int *piYres)
{
if (g_ptDispOpr)
{
*piXres = g_ptDispOpr->iXres;
*piYres = g_ptDispOpr->iYres;
return 0;
}
else
{
return -1;
}
}

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)
{
/
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;
}

main.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 <input_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];

int bList = 0;

T_InputEvent tInputEvent;

acHzkFile[0] = '\0';
acFreetypeFile[0] = '\0';
acTextFile[0] = '\0';

strcpy(acDisplay, "fb");

iError = DebugInit();
if (iError)
{
DBG_PRINTF("DebugInit error!\n");
return -1;
}

InitDebugChanel();

/* getopt得到输入的命令 */
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':
{
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:
{
DBG_PRINTF("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);
DBG_PRINTF("Usage: %s -l\n", argv[0]);
return -1;
break;
}
}
}

if (!bList && (optind >= argc))
{
DBG_PRINTF("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);
DBG_PRINTF("Usage: %s -l\n", argv[0]);
return -1;
}

iError = DisplayInit();
if (iError)
{
DBG_PRINTF("DisplayInit error!\n");
return -1;
}

iError = FontsInit();
if (iError)
{
DBG_PRINTF("FontsInit error!\n");
return -1;
}

iError = EncodingInit();
if (iError)
{
DBG_PRINTF("EncodingInit error!\n");
return -1;
}

iError = InputInit();
if (iError)
{
DBG_PRINTF("InputInit error!\n");
return -1;
}

if (bList)
{
DBG_PRINTF("supported display:\n");
ShowDispOpr();

DBG_PRINTF("supported font:\n");
ShowFontOpr();

DBG_PRINTF("supported encoding:\n");
ShowEncodingOpr();

DBG_PRINTF("supported input:\n");
ShowInputOpr();

DBG_PRINTF("supported debug chanel:\n");
ShowDebugOpr();

return 0;
}

strncpy(acTextFile, argv[optind], 128);
acTextFile[127] = '\0';

iError = OpenTextFile(acTextFile);
if (iError)
{
DBG_PRINTF("OpenTextFile error!\n");
return -1;
}

iError = SetTextDetail(acHzkFile, acFreetypeFile, dwFontSize);
if (iError)
{
DBG_PRINTF("SetTextDetail error!\n");
return -1;
}

DBG_PRINTF("%s %s %d\n", FILE, FUNCTION, LINE);

iError = SelectAndInitDisplay(acDisplay);
if (iError)
{
DBG_PRINTF("SelectAndInitDisplay error!\n");
return -1;
}

iError = AllInputDevicesInit();
if (iError)
{
DBG_PRINTF("Error AllInputDevicesInit\n");
return -1;
}

DBG_PRINTF("%s %s %d\n", FILE, FUNCTION, LINE);
iError = ShowNextPage();
DBG_PRINTF("%s %s %d\n", FILE, FUNCTION, LINE);
if (iError)
{
DBG_PRINTF("Error to show first page\n");
return -1;
}

DBG_PRINTF("Enter 'n' to show next page, 'u' to show previous page, 'q' to exit: ");

while (1)
{

if (0 == GetInputEvent(&tInputEvent))
{
if (tInputEvent.iVal == INPUT_VALUE_DOWN)
{
ShowNextPage();
}
else if (tInputEvent.iVal == INPUT_VALUE_UP)
{
ShowPrePage();
}
else if (tInputEvent.iVal == INPUT_VALUE_EXIT)
{
return 0;
}
}
}
return 0;
}

5.测试代码

./show_file -s 24 -d fb -f ./simsun.ttc ./dazhuzai.txt

posted @ 2020-02-27 20:53  人民广场的二道贩子  阅读(821)  评论(0)    收藏  举报