• 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 
    ");
    16         return -1;
    17     }
    18     printf("font init ok 
    ");
    19     
    20     if(-1 == display_init())
    21     {
    22         printf("display manager init error 
    ");
    23         return -1;
    24     }
    25     printf("display init ok 
    ");
    26     
    27     if(-1 == open_txt(file))
    28     {
    29         printf("cat't open %s txt 
    ", file);
    30         return -1;
    31     }
    32     printf("read file : %s ok 
    ", 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 
    ");
    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 
    ");
    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 
    ");
    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 
    ");
    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 
    ");
     22         return -1; 
     23     }
     24     if(-1 == fstat(txt_fd, &txt_stat))
     25     {
     26         close(txt_fd);
     27         printf("cat't get txt stat 
    ");
     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 
    ");
     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 
    ", 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         //处理 
     换行
    134         if('
    ' == **pos)
    135         {
    136             (*pos)++;
    137             continue;
    138         }
    139         if('
    ' == **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('	' == **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 
    ");
    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 
    ");
    16         return -1;
    17     }
    18     if(-1 == asc_init())
    19     {
    20         printf("asc font init error 
    ");
    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 
    ");
    43         return -1;
    44     }
    45     if(-1 == fstat(hzk_fd, &hzk_stat))
    46     {
    47         printf("cat't get HZK16 size
    ");
    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
    ");
    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 }
  • 相关阅读:
    构建之法阅读笔记03
    构建之法阅读笔记02
    构建之法读书笔记01
    梦断代码读书笔记03
    背包九讲问题
    C-01背包问题
    C-最长回文子串(2)
    C-最长回文子串(1)
    C语言顺序栈实现
    带头结点头部插入创建链表
  • 原文地址:https://www.cnblogs.com/ningci/p/5606357.html
Copyright © 2020-2023  润新知