s3c2440 上txt 小说阅读器

 

文件结构

Makefile:

 1 CROSSCOMPILE := arm-linux-
 2 CFLAGS     := -Wall -O2 -c
 3 LDFLAGS := -lm -lfreetype
 4 CC     := $(CROSSCOMPILE)gcc
 5 LD     := $(CROSSCOMPILE)ld
 6 
 7 OBJS := main.o \
 8             font/font_manager.o      \
 9             font/font_gbk.o           \
10             font/font_asc.o            \
11             display/display_manager.o   \
12             display/lcd_fb.o             \
13             draw/draw.o
14 
15 all: $(OBJS)
16     $(CC) $(LDFLAGS) -o txt $^
17 
18 clean:
19     rm -f txt
20     rm -f $(OBJS)
21 
22 %.o:%.c
23     $(CC) $(CFLAGS) -o $@ $<

main.c

 1 #include <stdio.h>
 2 #include "font/font_manager.h"
 3 #include "display/display_manager.h"
 4 #include "draw/draw.h"
 5 
 6 int main(int argc,char **argv)
 7 {
 8     //命令操作
 9     char cmd;
10     //第一个参数 要显示的TXT 文件
11     char *file = argv[1];
12     
13     if(-1 == font_init())
14     {
15         printf("font manager init error \r\n");
16         return -1;
17     }
18     printf("font init ok \r\n");
19     
20     if(-1 == display_init())
21     {
22         printf("display manager init error \r\n");
23         return -1;
24     }
25     printf("display init ok \r\n");
26     
27     if(-1 == open_txt(file))
28     {
29         printf("cat't open %s txt \r\n", file);
30         return -1;
31     }
32     printf("read file : %s ok \r\n", file);
33     show_page();
34     
35     while(1)
36     {
37         cmd = getchar();
38         if('n' == cmd)
39         {
40             show_page_next();
41         }
42         if('p' == cmd)
43         {
44             show_page_pre();
45         }
46         if('q' == cmd)
47         {
48             return 0;    
49         }
50     }
51     return 0;
52 }

 

HZK16 这个就不发了,网上自己找吧。

display/display_manager.h

 1 #ifndef __DISPLAY_MANAGER__
 2 #define __DISPLAY_MANAGER__
 3 
 4 #include <stdio.h>
 5 #include <string.h>
 6 
 7 typedef struct display{
 8     char *name;
 9     int width;
10     int height;
11     int (*display_init)(void);
12     int (*display_px)(int color, int x, int y);
13     struct display *next;
14 } T_display, *PT_display;
15 
16 int display_init(void);
17 int display_register(PT_display new_display);
18 PT_display display_select(char *name);
19 
20 int init_lcd_fb();
21 
22 #endif

 

display/display_manager.c

 1 #include "display_manager.h"
 2 
 3 static PT_display head_pt_display;
 4 
 5 PT_display display_select(char *name)
 6 {
 7     PT_display temp_pt_display = head_pt_display;
 8     while(temp_pt_display)
 9     {
10         if(0 == strcmp(name, temp_pt_display->name))
11         {
12             temp_pt_display->display_init();
13             return temp_pt_display;
14         }
15         else
16         {
17             temp_pt_display = temp_pt_display->next;
18         }
19     }
20     return NULL;
21 }
22 
23 int display_init(void)
24 {
25     if(-1 == init_lcd_fb())
26     {
27         printf("lcd fb init error \n");
28         return -1;
29     }
30     return 0;
31 }
32 
33 int display_register(PT_display new_display)
34 {
35     PT_display temp_pt_display = head_pt_display;
36     new_display->next = NULL;
37     if(! head_pt_display)
38     {
39         head_pt_display = new_display;
40     }
41     else
42     {
43         while(temp_pt_display->next)
44         {
45             temp_pt_display = temp_pt_display->next;
46         }
47         temp_pt_display = new_display;
48     }
49     return 0;
50 }

display/lcd_fb.c

 1 #include "display_manager.h"
 2 
 3 #include <sys/types.h>
 4 #include <sys/stat.h>
 5 #include <fcntl.h>
 6 
 7 #include <linux/fb.h>
 8 
 9 #include <sys/ioctl.h>
10 
11 #include <unistd.h>
12 
13 #include <string.h>
14 
15 #include <sys/mman.h>
16 
17 static int lcd_fb_display_init(void);
18 static int lcd_fb_display_px(int color, int x, int y);
19 
20 static int fb_fd;
21 static unsigned char *fb_mem;
22 static int px_width;
23 static int line_width;
24 static int screen_width;
25 static struct fb_var_screeninfo var;
26 
27 static T_display lcd_disp = {
28     .name         = "lcd_fb",
29     .display_init = lcd_fb_display_init,
30     .display_px   = lcd_fb_display_px,
31 };
32 
33 int init_lcd_fb()
34 {
35     return display_register(&lcd_disp);
36 }
37 
38 static int lcd_fb_display_init(void)
39 {
40     //如果使用 mmap 打开方式 必须是 读定方式
41     fb_fd = open("/dev/fb0", O_RDWR);
42     if(-1 == fb_fd)
43     {
44         printf("cat't open /dev/fb0 \n");
45         return -1;
46     }
47     //获取屏幕参数
48     if(-1 == ioctl(fb_fd, FBIOGET_VSCREENINFO, &var))
49     {
50         close(fb_fd);
51         printf("cat't ioctl /dev/fb0 \n");
52         return -1;
53     }
54     //计算参数
55     px_width = var.bits_per_pixel / 8;
56     line_width = var.xres * px_width;
57     screen_width = var.yres * line_width;
58     
59     fb_mem = (unsigned char *)mmap(NULL, screen_width, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
60     if(fb_mem == (void *)-1)
61     {
62         close(fb_fd);
63         printf("cat't mmap /dev/fb0 \n");
64         return -1;
65     }
66     //清屏
67     memset(fb_mem, 0 , screen_width);
68     
69     //设置参数
70     lcd_disp.width  = var.xres;
71     lcd_disp.height = var.yres;
72     
73     return 0;
74 }
75 
76 static int lcd_fb_display_px(int color, int x, int y)
77 {
78     unsigned char  *pen8;
79     unsigned short *pen16;
80     
81     unsigned char r,g,b;
82     
83     pen8 = (unsigned char *)(fb_mem + y*line_width + x*px_width);
84     pen16 = (unsigned short *)pen8;
85     
86     //合并为 565 格式 16bbp
87     r = (color>>16) & 0xff;
88     g = (color>>8) & 0xff;
89     b = (color>>0) & 0xff;
90     *pen16 = (r>>3)<<11 | (g>>2)<<5 | (b>>3);
91     
92     return 0;
93 }

draw/draw.h

 1 #include <stdio.h>
 2 #include <sys/mman.h>
 3 #include <sys/types.h>
 4 #include <sys/stat.h>
 5 #include <fcntl.h>
 6 
 7 #include <unistd.h>
 8 
 9 #include "../display/display_manager.h"
10 #include "../font/font_manager.h"
11 
12 //定义一个用来实现 上下 翻页的链表
13 typedef struct t_draw_page{
14     int p;
15     int pos; //相对于 基地址的 位置
16     struct t_draw_page *pre;
17     struct t_draw_page *next;
18 } T_draw_page, *PT_draw_page;
19 
20 int open_txt(char *file);
21 int show_page_pre();
22 int show_page_next();
23 int show_page();
24 int draw_page(unsigned char **pos);
25 
26 int draw_font(int color, PT_fontMap pt_font);
27 void draw_screen(int color);

draw/draw.c

  1 #include "draw.h"
  2 int txt_fd;
  3 struct stat txt_stat;
  4 unsigned char *txt_mem;
  5 
  6 #define TXT_COLOR 0xff0000
  7 #define BACKGROUND_COLOR 0xE7DBB5
  8 
  9 PT_display disp;
 10 PT_font gbk_font;
 11 PT_font asc_font;
 12 unsigned char *pos; //当前文件指针位置
 13 PT_draw_page pt_head_draw_page;
 14 
 15 //读取文件后使用 内存映射 缺点是大文件时死机,实际上也没有几百M 的文件
 16 int open_txt(char *file)
 17 {
 18     txt_fd = open(file, O_RDONLY);
 19     if(-1 == txt_fd)
 20     {
 21         printf("cat't get txt stat \n");
 22         return -1; 
 23     }
 24     if(-1 == fstat(txt_fd, &txt_stat))
 25     {
 26         close(txt_fd);
 27         printf("cat't get txt stat \n");
 28         return -1; 
 29     }
 30     txt_mem = (unsigned char *)mmap(NULL, txt_stat.st_size, PROT_READ, MAP_SHARED, txt_fd, 0);
 31     if(txt_mem == (void *)-1)
 32     {
 33         close(txt_fd);
 34         printf("cat't mmap txt \n");
 35         return -1; 
 36     }
 37     
 38     //打开文件成功后 初始化 lcd
 39     disp = display_select("lcd_fb");
 40     
 41     //初始化字库
 42     asc_font = font_select("asc");
 43     gbk_font = font_select("gbk");
 44     
 45     //当前文件指针位置
 46     pos = txt_mem; 
 47     
 48     printf("lcd width : %d height : %d \r\n", disp->width, disp->height);
 49     return 0;
 50 }
 51 
 52 void draw_screen(int color)
 53 {
 54     int x,y;
 55     for(x=0; x< disp->width; x++)
 56     {
 57         for(y=0; y< disp->height; y++)
 58         {
 59             disp->display_px(color, x, y);
 60         }
 61     }
 62 }
 63 
 64 //渲染一个字模
 65 int draw_font(int color, PT_fontMap pt_font)
 66 {
 67     int i,j,k,x,y;
 68     unsigned char *buffer = pt_font->buffer;
 69     x = pt_font->x;
 70     y = pt_font->y;
 71     
 72     //循环字模 y
 73     for(i=0; i<pt_font->height; i++)
 74     {
 75         //循环字模 x
 76         for(j=0; j<pt_font->width/8;j++)
 77         {
 78             //循环字模 1 字节的数据
 79             for(k=7; k>=0; k--)
 80             {
 81                 if(*buffer & (1<<k))
 82                 {
 83                     disp->display_px(color, x+7-k + j*8, y+i);
 84                 }
 85                 else
 86                 {
 87                     disp->display_px(BACKGROUND_COLOR, x+7-k + j*8, y+i);
 88                 }
 89             }
 90             //移动下 1 字节数据
 91             buffer++;
 92         }
 93     }
 94     //移动下一个字符显示位置 这里会比较 x y 当显示满屏幕时 退出 返回 -1
 95     pt_font->x += pt_font->width;
 96     if(pt_font->x >= disp->width)
 97     {
 98         pt_font->x = 0;
 99         pt_font->y += pt_font->height; 
100     }
101     //width 已满 height 已满
102     if(pt_font->y >= disp->height)
103     {
104         return -1;
105     }
106     return 0;
107 }
108 
109 //渲染一页
110 int draw_page(unsigned char **pos)
111 {
112     T_fontMap font = {
113         .x = 0,       /* 字要显示的位置x */
114         .y = 0,       /* 字要显示的位置y */
115         .width = 0,   /* 字高度 */
116         .height = 0,  /* 字大小 */
117     };
118     //绘一个背景颜色
119     //draw_screen(0xE7DBB5);
120     draw_screen(BACKGROUND_COLOR);
121     //如何实别是 asc 码 还是 gbk 码
122     //asc 小于 128
123     //gbk 要减去 0xa1
124     //递归读取文字绘制在屏幕上,当屏幕满时退出
125     while(1)
126     {
127         //显示到文本最后了
128         if((*pos - txt_stat.st_size) >= txt_mem )
129         {
130             return -1;
131         }
132         
133         //处理 \r\n 换行
134         if('\r' == **pos)
135         {
136             (*pos)++;
137             continue;
138         }
139         if('\n' == **pos)
140         {
141             //换行 y + 上一个字符的高度 这里有一点问题,如果 上一行 和下一行
142             //显示的文字高度不同? 不过这不是HTML TXT 每行都一样
143             (*pos)++;
144             font.x = 0;
145             font.y += font.height;
146             //换行时还要检查屏幕是否满
147             if(font.y >= disp->height)
148             {
149                 return -1;
150             }
151             continue;
152         }
153         if('\t' == **pos)
154         {
155             //换行 y + 上一个字符的高度 这里有一点问题,如果 上一行 和下一行
156             //显示的文字高度不同? 不过这不是HTML TXT 每行都一样
157             (*pos)++;
158             font.x += font.width;
159             continue;
160         }
161         
162         if(0x80 > **pos)
163         {
164             asc_font->font_getMap(*pos, &font);
165             
166             //asc 码每次移动1个
167             (*pos)++;
168         }
169         else if((0xa0 < **pos)  && (0xa0 < *(*pos+1)))
170         {
171             gbk_font->font_getMap(*pos, &font);
172             
173             //gbk 码每次移动2个
174             (*pos) += 2;
175         }
176         //1 屏幕显示完毕
177         if(-1 == draw_font(TXT_COLOR, &font))
178         {
179             return -1;
180         }
181     }
182     return 0;
183 }
184 
185 //显示一页
186 int show_page()
187 {
188     //首次初始化头链表
189     pt_head_draw_page = malloc(sizeof(T_draw_page));
190     //默认时等于 文件开头    
191     draw_page(&pos);
192     pt_head_draw_page->pos = 0;
193     pt_head_draw_page->pre = NULL;
194     pt_head_draw_page->next = NULL;
195     return 0;
196 }
197 
198 int show_page_pre()
199 {
200     PT_draw_page now_draw_page = pt_head_draw_page->pre;
201     if(NULL == now_draw_page)
202     {
203         printf("no pre page \r\n");
204         return -1;
205     }
206     
207     //重新定义指针
208     pos = txt_mem + now_draw_page->pos;
209     draw_page(&pos);
210     
211     pt_head_draw_page = now_draw_page;
212     
213     return 0;
214 }
215 
216 int show_page_next()
217 {    
218     //首次初始化头链表
219     PT_draw_page now_draw_page = pt_head_draw_page;
220     if(! now_draw_page->next)
221     {
222         now_draw_page = malloc(sizeof(T_draw_page));
223         //先记录下来当前位置在渲染
224         now_draw_page->pos = pos - txt_mem;
225         //默认时等于 文件开头    
226         draw_page(&pos);
227         now_draw_page->pre = pt_head_draw_page;
228         now_draw_page->next = NULL;
229         
230         //当前链表位置 等于 新生成的
231         pt_head_draw_page = now_draw_page;
232     }
233     else
234     {
235         //如果当前节点有下节点 直接赋值
236         pt_head_draw_page = pt_head_draw_page->next;
237         pos = txt_mem + now_draw_page->pos;
238         draw_page(&pos);
239     }
240     return 0;
241 }

 

font/font_manager.h

 1 #ifndef __FONT_MANAGER__
 2 #define __FONT_MANAGER__
 3 #include <stdio.h>
 4 #include <string.h>
 5 
 6 /* 定义一个存放 字模数据,字模显示位置等信息的struct */
 7 typedef struct{
 8     int x;       /* 字要显示的位置x */
 9     int y;       /* 字要显示的位置y */
10     int width;   /* 字高度 */
11     int height;  /* 字大小 */
12     unsigned char *buffer; /* 字模的数据 */
13 } T_fontMap, *PT_fontMap;
14 
15 /* 定义一个用来管理字体的 struct */
16 typedef struct Font{
17     char *name;
18     int (*font_init)(void);
19     int (*font_getMap)(unsigned char *str, PT_fontMap pfontMap);
20     struct Font *next;
21 } T_font, *PT_font;
22 
23 /* 所有字体初始化 */
24 int font_init();
25 
26 /* 字体注册 */
27 int font_register(PT_font);
28 
29 /* 获取一个字体 */
30 PT_font font_select(char *name);
31 
32 /* gbk 字体初始化 */
33 int gbk_init();
34 /* asc 字体初始化 */
35 int asc_init();
36 
37 #endif

font/font_manager.c

 1 #include "font_manager.h"
 2 
 3 /* 静态变量 全局变量 未初始化时内容为 0 局部变量未初始化时内容为垃圾值 */
 4 static PT_font tfont_head;
 5 
 6 /* 工作流程:font_init() 中调用  gbk  asc 的初始化方法, gbk_init 中调用 
 7  * font_register 注册到链表中 在对每个进行 init 操作 
 8  */
 9  
10 /* 所有字体初始化 */
11 int font_init()
12 {
13     if(-1 == gbk_init())
14     {
15         printf("gbk font init error \n");
16         return -1;
17     }
18     if(-1 == asc_init())
19     {
20         printf("asc font init error \n");
21         return -1;
22     }
23     return 0;
24 }    
25 
26 /* 字体注册 */
27 int font_register(PT_font new_font)
28 {
29     PT_font temp_font = tfont_head;
30     //设置链表下一个为 NULL
31     new_font->next = NULL;
32     //注册时初始化字体
33     if(-1 == new_font->font_init())
34     {
35         return -1;
36     }
37     //没有时添加第一个
38     if(! tfont_head)
39     {
40         tfont_head = new_font;
41     }
42     else
43     {
44         //判断是否有 下个节点
45         while(temp_font->next)
46         {        
47             temp_font = temp_font->next;
48         }
49         temp_font->next = new_font;
50     }
51     return 0;
52 }
53 
54 PT_font font_select(char *name)
55 {
56     PT_font temp_pt_font = tfont_head;
57     while(temp_pt_font)
58     {
59         if(0 == strcmp(name, temp_pt_font->name))
60         {
61             return temp_pt_font;
62         }
63         else
64         {
65             temp_pt_font = temp_pt_font->next;
66         }
67     }
68     return NULL;
69 }

font/font_gbk.c

 1 #include "font_manager.h"
 2 
 3 #include <sys/types.h>
 4 #include <sys/stat.h>
 5 #include <fcntl.h>
 6 
 7 #include <sys/mman.h>
 8 
 9 #include <unistd.h>
10 
11 #include <stdio.h>
12 
13 
14 static int hzk_fd;
15 static struct stat hzk_stat;
16 static unsigned char *hzk_mem;
17 
18 static int gbk_font_init(void);
19 static int gbk_font_getMap(unsigned char *str,PT_fontMap pfontMap);
20 
21 //语法只适用于 初始化时,不适用在 函数内部。
22 static T_font tfont_gbk  = {
23     .name = "gbk",
24     .font_init = gbk_font_init,
25     .font_getMap = gbk_font_getMap,
26 };
27 
28 int gbk_init()
29 {
30     return font_register(&tfont_gbk);
31 }
32 
33 /**
34  * 打开字库
35  * 内存映射
36  */
37 static int gbk_font_init(void)
38 {
39     hzk_fd = open("HZK16", O_RDONLY);
40     if(-1 == hzk_fd)
41     {
42         printf("cat't open HZK16 \n");
43         return -1;
44     }
45     if(-1 == fstat(hzk_fd, &hzk_stat))
46     {
47         printf("cat't get HZK16 size\n");
48         return -1;
49     }
50     hzk_mem = (unsigned char *)mmap(NULL, hzk_stat.st_size, PROT_READ, MAP_SHARED, hzk_fd, 0);
51     if(hzk_mem == (void *)-1)
52     {
53         printf("cat't mmap HZK16\n");
54         return -1;
55     }
56     return 0;
57 }
58 
59 static int gbk_font_getMap(unsigned char *str, PT_fontMap pfontMap)
60 {
61     //编码规则
62     //GBK 字库 区码 -0xA0  位码 -0xA0 , 每个区中有 94个字符
63     //每个汉字使用16bit * 16bit 表示
64     //高位在左侧显示
65     //16bit 16行
66     pfontMap->buffer = hzk_mem +((*str - 0xa1)*94 + (*(str+1) - 0xa1))*32;
67     pfontMap->width      = 16;
68     pfontMap->height     = 16;
69     return 0;
70 }



font_asc.c

 1 #include "font_manager.h"
 2 
 3 static int asc_font_init(void);
 4 static int asc_font_getMap(unsigned char *str, PT_fontMap pfontMap);
 5 
 6 static T_font tfont_asc = {
 7     .name = "asc",
 8     .font_init = asc_font_init,
 9     .font_getMap = asc_font_getMap,
10 };
11 
12 #define FONTDATAMAX 4096
13 static const unsigned char fontdata_8x16[FONTDATAMAX] = {
14     //..... 内容太多 .... 去 linux 内核里面找吧
15 };
16 
17 int asc_init()
18 {
19     return font_register(&tfont_asc);
20 }
21 
22 static int asc_font_init(void)
23 {
24     return 0;
25 }
26 
27 static int asc_font_getMap(unsigned char *str, PT_fontMap pfontMap)
28 {
29     unsigned char *asc_base = (unsigned char *)fontdata_8x16;
30     //编码规则
31     //8bit 16行
32     pfontMap->buffer = asc_base + *str * 16;
33     pfontMap->width  = 8;
34     pfontMap->height = 16;
35     return 0;
36 }

 

posted @ 2016-06-22 10:59  宁次  阅读(575)  评论(0编辑  收藏  举报