s3c2440 上txt 小说阅读器

s3c2440 上txt 小说阅读器

s3c2440 上txt 小说阅读器

文件结构

s3c2440 上txt 小说阅读器

Makefile:

 CROSSCOMPILE := arm-linux-
CFLAGS := -Wall -O2 -c
LDFLAGS := -lm -lfreetype
CC := $(CROSSCOMPILE)gcc
LD := $(CROSSCOMPILE)ld OBJS := main.o \
font/font_manager.o \
font/font_gbk.o \
font/font_asc.o \
display/display_manager.o \
display/lcd_fb.o \
draw/draw.o all: $(OBJS)
$(CC) $(LDFLAGS) -o txt $^ clean:
rm -f txt
rm -f $(OBJS) %.o:%.c
$(CC) $(CFLAGS) -o $@ $<

main.c

 #include <stdio.h>
#include "font/font_manager.h"
#include "display/display_manager.h"
#include "draw/draw.h" int main(int argc,char **argv)
{
//命令操作
char cmd;
//第一个参数 要显示的TXT 文件
char *file = argv[]; if(- == font_init())
{
printf("font manager init error \r\n");
return -;
}
printf("font init ok \r\n"); if(- == display_init())
{
printf("display manager init error \r\n");
return -;
}
printf("display init ok \r\n"); if(- == open_txt(file))
{
printf("cat't open %s txt \r\n", file);
return -;
}
printf("read file : %s ok \r\n", file);
show_page(); while()
{
cmd = getchar();
if('n' == cmd)
{
show_page_next();
}
if('p' == cmd)
{
show_page_pre();
}
if('q' == cmd)
{
return ;
}
}
return ;
}

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

display/display_manager.h

 #ifndef __DISPLAY_MANAGER__
#define __DISPLAY_MANAGER__ #include <stdio.h>
#include <string.h> typedef struct display{
char *name;
int width;
int height;
int (*display_init)(void);
int (*display_px)(int color, int x, int y);
struct display *next;
} T_display, *PT_display; int display_init(void);
int display_register(PT_display new_display);
PT_display display_select(char *name); int init_lcd_fb(); #endif

display/display_manager.c

 #include "display_manager.h"

 static PT_display head_pt_display;

 PT_display display_select(char *name)
{
PT_display temp_pt_display = head_pt_display;
while(temp_pt_display)
{
if( == strcmp(name, temp_pt_display->name))
{
temp_pt_display->display_init();
return temp_pt_display;
}
else
{
temp_pt_display = temp_pt_display->next;
}
}
return NULL;
} int display_init(void)
{
if(- == init_lcd_fb())
{
printf("lcd fb init error \n");
return -;
}
return ;
} int display_register(PT_display new_display)
{
PT_display temp_pt_display = head_pt_display;
new_display->next = NULL;
if(! head_pt_display)
{
head_pt_display = new_display;
}
else
{
while(temp_pt_display->next)
{
temp_pt_display = temp_pt_display->next;
}
temp_pt_display = new_display;
}
return ;
}

display/lcd_fb.c

 #include "display_manager.h"

 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> #include <linux/fb.h> #include <sys/ioctl.h> #include <unistd.h> #include <string.h> #include <sys/mman.h> static int lcd_fb_display_init(void);
static int lcd_fb_display_px(int color, int x, int y); static int fb_fd;
static unsigned char *fb_mem;
static int px_width;
static int line_width;
static int screen_width;
static struct fb_var_screeninfo var; static T_display lcd_disp = {
.name = "lcd_fb",
.display_init = lcd_fb_display_init,
.display_px = lcd_fb_display_px,
}; int init_lcd_fb()
{
return display_register(&lcd_disp);
} static int lcd_fb_display_init(void)
{
//如果使用 mmap 打开方式 必须是 读定方式
fb_fd = open("/dev/fb0", O_RDWR);
if(- == fb_fd)
{
printf("cat't open /dev/fb0 \n");
return -;
}
//获取屏幕参数
if(- == ioctl(fb_fd, FBIOGET_VSCREENINFO, &var))
{
close(fb_fd);
printf("cat't ioctl /dev/fb0 \n");
return -;
}
//计算参数
px_width = var.bits_per_pixel / ;
line_width = var.xres * px_width;
screen_width = var.yres * line_width; fb_mem = (unsigned char *)mmap(NULL, screen_width, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, );
if(fb_mem == (void *)-)
{
close(fb_fd);
printf("cat't mmap /dev/fb0 \n");
return -;
}
//清屏
memset(fb_mem, , screen_width); //设置参数
lcd_disp.width = var.xres;
lcd_disp.height = var.yres; return ;
} static int lcd_fb_display_px(int color, int x, int y)
{
unsigned char *pen8;
unsigned short *pen16; unsigned char r,g,b; pen8 = (unsigned char *)(fb_mem + y*line_width + x*px_width);
pen16 = (unsigned short *)pen8; //合并为 565 格式 16bbp
r = (color>>) & 0xff;
g = (color>>) & 0xff;
b = (color>>) & 0xff;
*pen16 = (r>>)<< | (g>>)<< | (b>>); return ;
}

draw/draw.h

 #include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> #include <unistd.h> #include "../display/display_manager.h"
#include "../font/font_manager.h" //定义一个用来实现 上下 翻页的链表
typedef struct t_draw_page{
int p;
int pos; //相对于 基地址的 位置
struct t_draw_page *pre;
struct t_draw_page *next;
} T_draw_page, *PT_draw_page; int open_txt(char *file);
int show_page_pre();
int show_page_next();
int show_page();
int draw_page(unsigned char **pos); int draw_font(int color, PT_fontMap pt_font);
void draw_screen(int color);

draw/draw.c

 #include "draw.h"
int txt_fd;
struct stat txt_stat;
unsigned char *txt_mem; #define TXT_COLOR 0xff0000
#define BACKGROUND_COLOR 0xE7DBB5 PT_display disp;
PT_font gbk_font;
PT_font asc_font;
unsigned char *pos; //当前文件指针位置
PT_draw_page pt_head_draw_page; //读取文件后使用 内存映射 缺点是大文件时死机,实际上也没有几百M 的文件
int open_txt(char *file)
{
txt_fd = open(file, O_RDONLY);
if(- == txt_fd)
{
printf("cat't get txt stat \n");
return -;
}
if(- == fstat(txt_fd, &txt_stat))
{
close(txt_fd);
printf("cat't get txt stat \n");
return -;
}
txt_mem = (unsigned char *)mmap(NULL, txt_stat.st_size, PROT_READ, MAP_SHARED, txt_fd, );
if(txt_mem == (void *)-)
{
close(txt_fd);
printf("cat't mmap txt \n");
return -;
} //打开文件成功后 初始化 lcd
disp = display_select("lcd_fb"); //初始化字库
asc_font = font_select("asc");
gbk_font = font_select("gbk"); //当前文件指针位置
pos = txt_mem; printf("lcd width : %d height : %d \r\n", disp->width, disp->height);
return ;
} void draw_screen(int color)
{
int x,y;
for(x=; x< disp->width; x++)
{
for(y=; y< disp->height; y++)
{
disp->display_px(color, x, y);
}
}
} //渲染一个字模
int draw_font(int color, PT_fontMap pt_font)
{
int i,j,k,x,y;
unsigned char *buffer = pt_font->buffer;
x = pt_font->x;
y = pt_font->y; //循环字模 y
for(i=; i<pt_font->height; i++)
{
//循环字模 x
for(j=; j<pt_font->width/;j++)
{
//循环字模 1 字节的数据
for(k=; k>=; k--)
{
if(*buffer & (<<k))
{
disp->display_px(color, x+-k + j*, y+i);
}
else
{
disp->display_px(BACKGROUND_COLOR, x+-k + j*, y+i);
}
}
//移动下 1 字节数据
buffer++;
}
}
//移动下一个字符显示位置 这里会比较 x y 当显示满屏幕时 退出 返回 -1
pt_font->x += pt_font->width;
if(pt_font->x >= disp->width)
{
pt_font->x = ;
pt_font->y += pt_font->height;
}
//width 已满 height 已满
if(pt_font->y >= disp->height)
{
return -;
}
return ;
} //渲染一页
int draw_page(unsigned char **pos)
{
T_fontMap font = {
.x = , /* 字要显示的位置x */
.y = , /* 字要显示的位置y */
.width = , /* 字高度 */
.height = , /* 字大小 */
};
//绘一个背景颜色
//draw_screen(0xE7DBB5);
draw_screen(BACKGROUND_COLOR);
//如何实别是 asc 码 还是 gbk 码
//asc 小于 128
//gbk 要减去 0xa1
//递归读取文字绘制在屏幕上,当屏幕满时退出
while()
{
//显示到文本最后了
if((*pos - txt_stat.st_size) >= txt_mem )
{
return -;
} //处理 \r\n 换行
if('\r' == **pos)
{
(*pos)++;
continue;
}
if('\n' == **pos)
{
//换行 y + 上一个字符的高度 这里有一点问题,如果 上一行 和下一行
//显示的文字高度不同? 不过这不是HTML TXT 每行都一样
(*pos)++;
font.x = ;
font.y += font.height;
//换行时还要检查屏幕是否满
if(font.y >= disp->height)
{
return -;
}
continue;
}
if('\t' == **pos)
{
//换行 y + 上一个字符的高度 这里有一点问题,如果 上一行 和下一行
//显示的文字高度不同? 不过这不是HTML TXT 每行都一样
(*pos)++;
font.x += font.width;
continue;
} if(0x80 > **pos)
{
asc_font->font_getMap(*pos, &font); //asc 码每次移动1个
(*pos)++;
}
else if((0xa0 < **pos) && (0xa0 < *(*pos+)))
{
gbk_font->font_getMap(*pos, &font); //gbk 码每次移动2个
(*pos) += ;
}
//1 屏幕显示完毕
if(- == draw_font(TXT_COLOR, &font))
{
return -;
}
}
return ;
} //显示一页
int show_page()
{
//首次初始化头链表
pt_head_draw_page = malloc(sizeof(T_draw_page));
//默认时等于 文件开头
draw_page(&pos);
pt_head_draw_page->pos = ;
pt_head_draw_page->pre = NULL;
pt_head_draw_page->next = NULL;
return ;
} int show_page_pre()
{
PT_draw_page now_draw_page = pt_head_draw_page->pre;
if(NULL == now_draw_page)
{
printf("no pre page \r\n");
return -;
} //重新定义指针
pos = txt_mem + now_draw_page->pos;
draw_page(&pos); pt_head_draw_page = now_draw_page; return ;
} int show_page_next()
{
//首次初始化头链表
PT_draw_page now_draw_page = pt_head_draw_page;
if(! now_draw_page->next)
{
now_draw_page = malloc(sizeof(T_draw_page));
//先记录下来当前位置在渲染
now_draw_page->pos = pos - txt_mem;
//默认时等于 文件开头
draw_page(&pos);
now_draw_page->pre = pt_head_draw_page;
now_draw_page->next = NULL; //当前链表位置 等于 新生成的
pt_head_draw_page = now_draw_page;
}
else
{
//如果当前节点有下节点 直接赋值
pt_head_draw_page = pt_head_draw_page->next;
pos = txt_mem + now_draw_page->pos;
draw_page(&pos);
}
return ;
}

font/font_manager.h

 #ifndef __FONT_MANAGER__
#define __FONT_MANAGER__
#include <stdio.h>
#include <string.h> /* 定义一个存放 字模数据,字模显示位置等信息的struct */
typedef struct{
int x; /* 字要显示的位置x */
int y; /* 字要显示的位置y */
int width; /* 字高度 */
int height; /* 字大小 */
unsigned char *buffer; /* 字模的数据 */
} T_fontMap, *PT_fontMap; /* 定义一个用来管理字体的 struct */
typedef struct Font{
char *name;
int (*font_init)(void);
int (*font_getMap)(unsigned char *str, PT_fontMap pfontMap);
struct Font *next;
} T_font, *PT_font; /* 所有字体初始化 */
int font_init(); /* 字体注册 */
int font_register(PT_font); /* 获取一个字体 */
PT_font font_select(char *name); /* gbk 字体初始化 */
int gbk_init();
/* asc 字体初始化 */
int asc_init(); #endif

font/font_manager.c

 #include "font_manager.h"

 /* 静态变量 全局变量 未初始化时内容为 0 局部变量未初始化时内容为垃圾值 */
static PT_font tfont_head; /* 工作流程:font_init() 中调用 gbk asc 的初始化方法, gbk_init 中调用
* font_register 注册到链表中 在对每个进行 init 操作
*/ /* 所有字体初始化 */
int font_init()
{
if(- == gbk_init())
{
printf("gbk font init error \n");
return -;
}
if(- == asc_init())
{
printf("asc font init error \n");
return -;
}
return ;
} /* 字体注册 */
int font_register(PT_font new_font)
{
PT_font temp_font = tfont_head;
//设置链表下一个为 NULL
new_font->next = NULL;
//注册时初始化字体
if(- == new_font->font_init())
{
return -;
}
//没有时添加第一个
if(! tfont_head)
{
tfont_head = new_font;
}
else
{
//判断是否有 下个节点
while(temp_font->next)
{
temp_font = temp_font->next;
}
temp_font->next = new_font;
}
return ;
} PT_font font_select(char *name)
{
PT_font temp_pt_font = tfont_head;
while(temp_pt_font)
{
if( == strcmp(name, temp_pt_font->name))
{
return temp_pt_font;
}
else
{
temp_pt_font = temp_pt_font->next;
}
}
return NULL;
}

font/font_gbk.c

 #include "font_manager.h"

 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #include <stdio.h> static int hzk_fd;
static struct stat hzk_stat;
static unsigned char *hzk_mem; static int gbk_font_init(void);
static int gbk_font_getMap(unsigned char *str,PT_fontMap pfontMap); //语法只适用于 初始化时,不适用在 函数内部。
static T_font tfont_gbk = {
.name = "gbk",
.font_init = gbk_font_init,
.font_getMap = gbk_font_getMap,
}; int gbk_init()
{
return font_register(&tfont_gbk);
} /**
* 打开字库
* 内存映射
*/
static int gbk_font_init(void)
{
hzk_fd = open("HZK16", O_RDONLY);
if(- == hzk_fd)
{
printf("cat't open HZK16 \n");
return -;
}
if(- == fstat(hzk_fd, &hzk_stat))
{
printf("cat't get HZK16 size\n");
return -;
}
hzk_mem = (unsigned char *)mmap(NULL, hzk_stat.st_size, PROT_READ, MAP_SHARED, hzk_fd, );
if(hzk_mem == (void *)-)
{
printf("cat't mmap HZK16\n");
return -;
}
return ;
} static int gbk_font_getMap(unsigned char *str, PT_fontMap pfontMap)
{
//编码规则
//GBK 字库 区码 -0xA0 位码 -0xA0 , 每个区中有 94个字符
//每个汉字使用16bit * 16bit 表示
//高位在左侧显示
//16bit 16行
pfontMap->buffer = hzk_mem +((*str - 0xa1)* + (*(str+) - 0xa1))*;
pfontMap->width = ;
pfontMap->height = ;
return ;
}

font_asc.c

 #include "font_manager.h"

 static int asc_font_init(void);
static int asc_font_getMap(unsigned char *str, PT_fontMap pfontMap); static T_font tfont_asc = {
.name = "asc",
.font_init = asc_font_init,
.font_getMap = asc_font_getMap,
}; #define FONTDATAMAX 4096
static const unsigned char fontdata_8x16[FONTDATAMAX] = {
//..... 内容太多 .... 去 linux 内核里面找吧
}; int asc_init()
{
return font_register(&tfont_asc);
} static int asc_font_init(void)
{
return ;
} static int asc_font_getMap(unsigned char *str, PT_fontMap pfontMap)
{
unsigned char *asc_base = (unsigned char *)fontdata_8x16;
//编码规则
//8bit 16行
pfontMap->buffer = asc_base + *str * ;
pfontMap->width = ;
pfontMap->height = ;
return ;
}
上一篇:SNS团队Beta阶段第七次站立会议(2017.5.28)


下一篇:《Spring1之第七次站立会议》