电子书总结

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

1.框架

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

2.各个模块的具体分析

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;
}

猜你喜欢

转载自www.cnblogs.com/huangdengtao/p/12362149.html
今日推荐