Linux电子书项目之电子书的实现及框架优化(3)

时间:2022-01-08 16:12:14

一、整体思路

采用分层的思想,面向对象的编程思想。

Linux电子书项目之电子书的实现及框架优化(3)

1、怎样在LCD上显示一个文件

Linux电子书项目之电子书的实现及框架优化(3)

2、如何组织代码

分层的结构

main--draw--XXX_manager--fb.c等

Linux电子书项目之电子书的实现及框架优化(3)

二、分层编写-底层实现

1、显示部分代码编写

[cpp]  view plain  copy
  1. show_file\display\fb.c  
  2. show_file\display\disp_manager.c  
  3. show_file\include\config.h  
  4. show_file\include\disp_manager.h  
  5. show_file\draw\draw.c  

先写fb.c 一面向对象编程思想

设置构造一个结构体

结构体需要有哪些成员呢:

显示部分,一定有一个显示函数,FB要显示就要初始化,所以有一个fb初始化函数,换页的时候我们要进行清屏操作,要有一个清屏函数,所以要有3个函数。

(1)    fb初始化

(2)    显示函数

(3)    清屏函数

只有函数还不全,还需要一些属性,如定义一个名字“fb”,X坐标,Y坐标,多少位表示一个像素等属性。

disp_manager.h中结构体设计如下

[cpp]  view plain  copy
  1. typedef struct DispOpr {  
  2.     char *name;  
  3.     int iXres;  
  4.     int iYres;  
  5.     int iBpp;  
  6.     int (*DeviceInit)(void);  
  7.     int (*ShowPixel)(int iPenX, int iPenY, unsigned int dwColor);  
  8.     int (*CleanScreen)(unsigned int dwBackColor);  
  9.     struct DispOpr *ptNext;  
  10. }T_DispOpr, *PT_DispOpr;  
fb.c初始化结构体,并写出对应的函数。
[cpp]  view plain  copy
  1. static T_DispOpr g_tFBOpr = {  
  2.     .name        = "fb",  
  3.     .DeviceInit  = FBDeviceInit,  
  4.     .ShowPixel   = FBShowPixel,  
  5.     .CleanScreen = FBCleanScreen,  
  6. };  

结构体用到这些函数 ,所以事先声明一下,都是static所以只能在本文件中使用,外面想用只能通过上一层。

[cpp]  view plain  copy
  1. static int FBDeviceInit(void);  
  2. static int FBShowPixel(int iX, int iY, unsigned int dwColor);  
  3. static int FBCleanScreen(unsigned int dwBackColor);  

在哪注册?

[cpp]  view plain  copy
  1. int FBInit(void)  
  2. {  
  3.     return RegisterDispOpr(&g_tFBOpr);  
  4. }  

这里就不能写成static了。

注册就是把结构体加入链表中,链表比数组更灵活,大小随意。

一开始链表头是空的,所以让指针指向这个结构体。在注册就让next指向新结构体。

实现三个函数:

注意这里是应用程序所以是一些open,read等函数。

如:g_fd = open(FB_DEVICE_NAME, O_RDWR);

这里不应该把设备名字定死,所以写一个config文件

[cpp]  view plain  copy
  1. #ifndef _CONFIG_H  
  2. #define _CONFIG_H  
  3.   
  4. #include <stdio.h>  
  5.   
  6. #define FB_DEVICE_NAME "/dev/fb0"  
  7.   
  8. #define COLOR_BACKGROUND   0xE7DBB5  /* 泛黄的纸 */  
  9. #define COLOR_FOREGROUND   0x514438  /* 褐色字体 */  
  10.   
  11. #define DBG_PRINTF(...)    
  12. //#define DBG_PRINTF printf  
  13.   
  14. #endif /* _CONFIG_H */  

DBG_PRINTF:这个宏可以控制打印开关。

显示做好了,但是我们显示内容在哪呢?需要设置显示字体,得到显示的点阵。如显示ASCII还是ABK,还是freetype。同理写出这部分代码。

代码:

fb.c:重点是结构

[cpp]  view plain  copy
  1. #include <config.h>  
  2. #include <disp_manager.h>  
  3. #include <sys/types.h>  
  4. #include <sys/stat.h>  
  5. #include <fcntl.h>  
  6. #include <sys/ioctl.h>  
  7. #include <sys/mman.h>  
  8. #include <linux/fb.h>  
  9. #include <string.h>  
  10.   
  11. static int FBDeviceInit(void);  
  12. static int FBShowPixel(int iX, int iY, unsigned int dwColor);  
  13. static int FBCleanScreen(unsigned int dwBackColor);  
  14.   
  15.   
  16. static int g_fd;  
  17.   
  18. static struct fb_var_screeninfo g_tFBVar;  //可变参数  
  19. static struct fb_fix_screeninfo g_tFBFix;    //固定参数  
  20. static unsigned char *g_pucFBMem;          //内存映射  
  21. static unsigned int g_dwScreenSize;        //FB屏幕大小  
  22.   
  23. static unsigned int g_dwLineWidth;         //一行宽度:一行的像素*像素位数/8字节      
  24. static unsigned int g_dwPixelWidth;        //每个像素占据多少字节:BPP/8=2字节(一个像素占据2字节)  
  25.   
  26. static T_DispOpr g_tFBOpr = {  
  27.     .name        = "fb",  
  28.     .DeviceInit  = FBDeviceInit,  
  29.     .ShowPixel   = FBShowPixel,  
  30.     .CleanScreen = FBCleanScreen,  
  31. };  
  32.   
  33. static int FBDeviceInit(void)  
  34. {  
  35.     int ret;  
  36.       
  37.     g_fd = open(FB_DEVICE_NAME, O_RDWR);  
  38.     if (0 > g_fd)  
  39.     {  
  40.         DBG_PRINTF("can't open %s\n", FB_DEVICE_NAME);  
  41.     }  
  42.   
  43.     ret = ioctl(g_fd, FBIOGET_VSCREENINFO, &g_tFBVar);  
  44.     if (ret < 0)  
  45.     {  
  46.         DBG_PRINTF("can't get fb's var\n");  
  47.         return -1;  
  48.     }  
  49.   
  50.     ret = ioctl(g_fd, FBIOGET_FSCREENINFO, &g_tFBFix);  
  51.     if (ret < 0)  
  52.     {  
  53.         DBG_PRINTF("can't get fb's fix\n");  
  54.         return -1;  
  55.     }  
  56.       
  57.     g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8;  
  58.     g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0);  
  59.     if (0 > g_pucFBMem)    
  60.     {  
  61.         DBG_PRINTF("can't mmap\n");  
  62.         return -1;  
  63.     }  
  64.   
  65.     g_tFBOpr.iXres       = g_tFBVar.xres;  
  66.     g_tFBOpr.iYres       = g_tFBVar.yres;  
  67.     g_tFBOpr.iBpp        = g_tFBVar.bits_per_pixel;  //设置坐标和多少位表示一个像素  
  68.   
  69.     g_dwLineWidth  = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;  
  70.     g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;  
  71.       
  72.     return 0;  
  73. }  
  74.   
  75. //RRGGBB  16: 24转成565  
  76. static int FBShowPixel(int iX, int iY, unsigned int dwColor)  
  77. {  
  78.     unsigned char *pucFB;  
  79.     unsigned short *pwFB16bpp;  
  80.     unsigned int *pdwFB32bpp;  
  81.     unsigned short wColor16bpp; /* 565 */  
  82.     int iRed;  
  83.     int iGreen;  
  84.     int iBlue;  
  85.   
  86.     if ((iX >= g_tFBVar.xres) || (iY >= g_tFBVar.yres))  
  87.     {  
  88.         DBG_PRINTF("out of region\n");  
  89.         return -1;  
  90.     }  
  91.   
  92.     pucFB      = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX;  
  93.     pwFB16bpp  = (unsigned short *)pucFB;  
  94.     pdwFB32bpp = (unsigned int *)pucFB;  
  95.       
  96.     switch (g_tFBVar.bits_per_pixel)  
  97.     {  
  98.         case 8:  
  99.         {  
  100.             *pucFB = (unsigned char)dwColor;  
  101.             break;  
  102.         }  
  103.         case 16:  
  104.         {  
  105.             iRed   = (dwColor >> (16+3)) & 0x1f;  
  106.             iGreen = (dwColor >> (8+2)) & 0x3f;  
  107.             iBlue  = (dwColor >> 3) & 0x1f;  
  108.             wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;  
  109.             *pwFB16bpp  = wColor16bpp;  
  110.             break;  
  111.         }  
  112.         case 32:  
  113.         {  
  114.             *pdwFB32bpp = dwColor;  
  115.             break;  
  116.         }  
  117.         default :  
  118.         {  
  119.             DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);  
  120.             return -1;  
  121.         }  
  122.     }  
  123.   
  124.     return 0;  
  125. }  
  126.   
  127. static int FBCleanScreen(unsigned int dwBackColor)  
  128. {  
  129.     unsigned char *pucFB;  
  130.     unsigned short *pwFB16bpp;  
  131.     unsigned int *pdwFB32bpp;  
  132.     unsigned short wColor16bpp; /* 565 */  
  133.     int iRed;  
  134.     int iGreen;  
  135.     int iBlue;  
  136.     int i = 0;  
  137.   
  138.     pucFB      = g_pucFBMem;  
  139.     pwFB16bpp  = (unsigned short *)pucFB;  
  140.     pdwFB32bpp = (unsigned int *)pucFB;  
  141.   
  142.     switch (g_tFBVar.bits_per_pixel)  
  143.     {  
  144.         case 8:  
  145.         {  
  146.             memset(g_pucFBMem, dwBackColor, g_dwScreenSize);  
  147.             break;  
  148.         }  
  149.         case 16:  
  150.         {  
  151.             iRed   = (dwBackColor >> (16+3)) & 0x1f;  
  152.             iGreen = (dwBackColor >> (8+2)) & 0x3f;  
  153.             iBlue  = (dwBackColor >> 3) & 0x1f;  
  154.             wColor16bpp = (iRed << 11) | (iGreen << 5) | iBlue;  
  155.             while (i < g_dwScreenSize)  
  156.             {  
  157.                 *pwFB16bpp  = wColor16bpp;  
  158.                 pwFB16bpp++;  
  159.                 i += 2;  
  160.             }  
  161.             break;  
  162.         }  
  163.         case 32:  
  164.         {  
  165.             while (i < g_dwScreenSize)  
  166.             {  
  167.                 *pdwFB32bpp = dwBackColor;  
  168.                 pdwFB32bpp++;  
  169.                 i += 4;  
  170.             }  
  171.             break;  
  172.         }  
  173.         default :  
  174.         {  
  175.             DBG_PRINTF("can't support %d bpp\n", g_tFBVar.bits_per_pixel);  
  176.             return -1;  
  177.         }  
  178.     }  
  179.   
  180.     return 0;  
  181. }  
  182.   
  183. int FBInit(void)  
  184. {  
  185.     return RegisterDispOpr(&g_tFBOpr);  
  186. }  
disp_manager.c:重点是链表操作
[cpp]  view plain  copy
  1. #include <config.h>  
  2. #include <disp_manager.h>  
  3. #include <string.h>  
  4.   
  5. static PT_DispOpr g_ptDispOprHead;  
  6.   
  7. int RegisterDispOpr(PT_DispOpr ptDispOpr)  
  8. {  
  9.     PT_DispOpr ptTmp;  
  10.   
  11.     if (!g_ptDispOprHead)  
  12.     {  
  13.         g_ptDispOprHead   = ptDispOpr;  
  14.         ptDispOpr->ptNext = NULL;  
  15.     }  
  16.     else  
  17.     {  
  18.         ptTmp = g_ptDispOprHead;  
  19.         while (ptTmp->ptNext)  
  20.         {  
  21.             ptTmp = ptTmp->ptNext;  
  22.         }  
  23.         ptTmp->ptNext      = ptDispOpr;  
  24.         ptDispOpr->ptNext = NULL;  
  25.     }  
  26.   
  27.     return 0;  
  28. }  
  29.   
  30.   
  31. void ShowDispOpr(void)  
  32. {  
  33.     int i = 0;  
  34.     PT_DispOpr ptTmp = g_ptDispOprHead;  
  35.   
  36.     while (ptTmp)  
  37.     {  
  38.         printf("%02d %s\n", i++, ptTmp->name);  
  39.         ptTmp = ptTmp->ptNext;  
  40.     }  
  41. }  
  42.   
  43. PT_DispOpr GetDispOpr(char *pcName)  
  44. {  
  45.     PT_DispOpr ptTmp = g_ptDispOprHead;  
  46.       
  47.     while (ptTmp)  
  48.     {  
  49.         if (strcmp(ptTmp->name, pcName) == 0)  
  50.         {  
  51.             return ptTmp;  
  52.         }  
  53.         ptTmp = ptTmp->ptNext;  
  54.     }  
  55.     return NULL;  
  56. }  
  57.   
  58. int DisplayInit(void)  
  59. {  
  60.     int iError;  
  61.       
  62.     iError = FBInit();  
  63.   
  64.     return iError;  
  65. }  

2、字体部分编写

思路如上一样,分配、设置、注册结构体。

3、编码部分编写

思路如上一样,分配、设置、注册结构体。

三、分层编写-上层实现

1、draw.c

组织底层代码

2、main.c

解析命令-打开文本-显示文本-换页-返回上一页等

Linux电子书项目之电子书的实现及框架优化(3)

[cpp]  view plain  copy
  1. #include <unistd.h>  
  2. #include <stdlib.h>  
  3. #include <stdio.h>  
  4. #include <config.h>  
  5. #include <draw.h>  
  6. #include <encoding_manager.h>  
  7. #include <fonts_manager.h>  
  8. #include <disp_manager.h>  
  9. #include <string.h>  
  10.   
  11.   
  12. /* ./show_file [-s Size] [-f freetype_font_file] [-h HZK] <text_file> */  
  13. int main(int argc, char **argv)  
  14. {  
  15.     int iError;  
  16.     unsigned int dwFontSize = 16;  
  17.     char acHzkFile[128];  
  18.     char acFreetypeFile[128];  
  19.     char acTextFile[128];  
  20.   
  21.     char acDisplay[128];  
  22.   
  23.     char cOpr;  
  24.     int bList = 0;  
  25.   
  26.     acHzkFile[0]  = '\0';  
  27.     acFreetypeFile[0] = '\0';  
  28.     acTextFile[0] = '\0';  
  29.   
  30.     strcpy(acDisplay, "fb");  
  31.       
  32.     while ((iError = getopt(argc, argv, "ls:f:h:d:")) != -1)  
  33.     {  
  34.         switch(iError)  
  35.         {  
  36.             case 'l':  
  37.             {  
  38.                   bList = 1;  
  39.                   break;  
  40.             }  
  41.             case 's':  
  42.             {  
  43.                   dwFontSize = strtoul(optarg, NULL, 0);  
  44.                   break;  
  45.             }  
  46.             case 'f':  
  47.             {  
  48.                   strncpy(acFreetypeFile, optarg, 128);  
  49.                   acFreetypeFile[127] = '\0';  
  50.                   break;  
  51.             }             
  52.             case 'h':  
  53.             {  
  54.                     strncpy(acHzkFile, optarg, 128);  
  55.                     acHzkFile[127] = '\0';  
  56.                     break;  
  57.             }  
  58.             case 'd':  
  59.             {  
  60.                 strncpy(acDisplay, optarg, 128);  
  61.                 acDisplay[127] = '\0';  
  62.                 break;  
  63.             }  
  64.             default:  
  65.             {  
  66.                     printf("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);  
  67.                     printf("Usage: %s -l\n", argv[0]);  
  68.                     return -1;  
  69.                     break;  
  70.             }  
  71.         }  
  72.     }  
  73.   
  74.     if (!bList && (optind >= argc))  
  75.     {  
  76.         printf("Usage: %s [-s Size] [-d display] [-f font_file] [-h HZK] <text_file>\n", argv[0]);  
  77.         printf("Usage: %s -l\n", argv[0]);  
  78.         return -1;  
  79.     }  
  80.           
  81.     iError = DisplayInit();  
  82.     if (iError)  
  83.     {  
  84.         printf("DisplayInit error!\n");  
  85.         return -1;  
  86.     }  
  87.   
  88.     iError = FontsInit();  
  89.     if (iError)  
  90.     {  
  91.         printf("FontsInit error!\n");  
  92.         return -1;  
  93.     }  
  94.   
  95.     iError = EncodingInit();  
  96.     if (iError)  
  97.     {  
  98.         printf("EncodingInit error!\n");  
  99.         return -1;  
  100.     }  
  101.   
  102.     if (bList)  
  103.     {  
  104.         printf("supported display:\n");  
  105.         ShowDispOpr();  
  106.   
  107.         printf("supported font:\n");  
  108.         ShowFontOpr();  
  109.   
  110.         printf("supported encoding:\n");  
  111.         ShowEncodingOpr();  
  112.         return 0;  
  113.     }  
  114.   
  115.     strncpy(acTextFile, argv[optind], 128);  
  116.     acTextFile[127] = '\0';  
  117.           
  118.     iError = OpenTextFile(acTextFile);  
  119.     if (iError)  
  120.     {  
  121.         printf("OpenTextFile error!\n");  
  122.         return -1;  
  123.     }  
  124.   
  125.     iError = SetTextDetail(acHzkFile, acFreetypeFile, dwFontSize);  
  126.     if (iError)  
  127.     {  
  128.         printf("SetTextDetail error!\n");  
  129.         return -1;  
  130.     }  
  131.   
  132.     DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);  
  133.   
  134.     iError = SelectAndInitDisplay(acDisplay);  
  135.     if (iError)  
  136.     {  
  137.         printf("SelectAndInitDisplay error!\n");  
  138.         return -1;  
  139.     }  
  140.       
  141.     DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);  
  142.     iError = ShowNextPage();  
  143.     DBG_PRINTF("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);  
  144.     if (iError)  
  145.     {  
  146.         printf("Error to show first page\n");  
  147.         return -1;  
  148.     }  
  149.   
  150.     while (1)  
  151.     {  
  152.         printf("Enter 'n' to show next page, 'u' to show previous page, 'q' to exit: ");  
  153.   
  154.         do {  
  155.             cOpr = getchar();             
  156.         } while ((cOpr != 'n') && (cOpr != 'u') && (cOpr != 'q'));  
  157.   
  158.         if (cOpr == 'n')  
  159.         {  
  160.             ShowNextPage();  
  161.         }  
  162.         else if (cOpr == 'u')  
  163.         {  
  164.             ShowPrePage();            
  165.         }  
  166.         else   
  167.         {  
  168.             return 0;  
  169.         }             
  170.     }  
  171.     return 0;  
  172. }  
(1)解析命令参数

getopt(argc, argv, "ls:f:h:d:")

:需要带参数

-l 不需要带参数

strncpy(acTextFile, argv[optind], 128);得到文件名

(2)初始化显示、字体、编码--》注册相关结构体

[cpp]  view plain  copy
  1. iError = DisplayInit();  
  2. iError = FontsInit();  
  3. iError = EncodingInit();  
(3)打开文件

 OpenTextFile(acTextFile)
(4)打开字体文件

SetTextDetail(acHzkFile, acFreetypeFile, dwFontSize);

(5)根据名字选择初始化一个显示器

SelectAndInitDisplay(acDisplay);
(6)显示第一页或者下一页

ShowNextPage();

(7)等待命令参数,显示下一页,上一页等