文件结构

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

s3c2440 上txt 小说阅读器的更多相关文章

  1. PC免费的小说阅读器,可提取章节

    最近自己做了个小说阅读器,就是下面这个东西啦,目前仅支持Window系统: 个人喜欢在电脑.平板上等大屏幕设备上阅读小说或电子书籍.原因其一是屏幕足够大,可以选择更舒服的字体大小:其二是觉得小屏幕看字 ...

  2. 开发微信小程序——古龙小说阅读器

    概述 由于面试的关系接触了一下微信小程序,花了2晚上开发了一个带书签功能的古龙小说阅读器,并且已经提交审核等待发布.这篇博文记录了我的开发过程和对微信小程序的看法,供以后开发时参考,相信对其他人也有用 ...

  3. 从零开发一款txt小说下载器

    在日常开发中,列表是一个非常常用的一个东西,可以用listview和recyclerview实现.当然,由于recyclerview更为实用且强大,它也是更好的方案. 而我以前为了方便,习惯直接拿网上 ...

  4. android优化中国风应用、完整NBA客户端、动态积分效果、文件传输、小说阅读器等源码

    Android精选源码 android拖拽下拉关闭效果源码 一款优雅的中国风Android App源码 EasySignSeekBar一个漂亮而强大的自定义view15 android仿蘑菇街,蜜芽宝 ...

  5. Android 上的代码阅读器 CoderBrowserHD 修改支持 go 语言代码

    我在Android上的代码阅读器用的是 https://github.com/zerob13/CoderBrowserHD 改造的版本,改造后的版本我放在 https://github.com/ghj ...

  6. 读取本地HTML的小说阅读器应用源码项目

    该源码是一个不错的读取本地HTML的小说阅读器,读取本地HTML的小说阅读器,并且源码也比较简单的,非常适合我们的新手朋友拿来学习,有兴趣的朋友研究下. 源码下载: http://code.662p. ...

  7. 基于Core Text实现的TXT电子书阅读器

    本篇文章的项目地址基于Core Text实现的TXT电子书阅读器. 最近花了一点时间学习了iOS的底层文字处理的框架Core Text.在网上也参考很多资料,具体的资料在文章最后列了出来,有兴趣的可参 ...

  8. 如何在使用摩托罗拉上的RSS阅读器应用进行一次订阅

    订阅一个CSDN的RSS为例. 1.打开RSS阅读器. 2.设置->新增订阅->手动新增 订阅URL:输入http://articles.csdn.net/api/rss.php?tid= ...

  9. Vue小说阅读器(仿追书神器)

    一个vue阅读器项目,目前已升级到2.0,阅读器支持横向分页并滑动翻页(没有动画,需要动画的可以自己设置,增加transitionDuration即可) 技术栈 vue全家桶+mint-ui gith ...

随机推荐

  1. jQuery文本段落展开和折叠效果

    <!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/h ...

  2. Office 365 Licence使用情况统计

    负责采购的同事需要知道目前公司使用了多少License,但是通过O365控制台界面似乎无法直接导出License使用量的信息,于是让我帮忙从后台统计一下. $mail_text = Read-Host ...

  3. 简单的行为控制管理方法,自动登录,session定时验证码过期

    代码很简单 实现的方式很多,用cookies 用static 变量 file文件缓存 等等 比如 //简单行为管理,如果请求此方法次数多于5次,就显示验证码 吧当前方法的name传进来,有效时间是5分 ...

  4. android删除无用资源文件的python脚本

    随着android项目的进行,如果没有及时删除无用的资源时安装包会越来越大,是时候整理一下废弃资源缩小压缩包了,少年! 其实判断一个资源(drawable,layout)是否没有被使用很简单,文件名( ...

  5. ubuntu-vnc

    Centos 中文gnome: 全新以最小化包安装了64位的CentOS6.3系统,作为本地的Web服务器使用,现记录全过程: 1.先安装X Window yum groupinstall " ...

  6. SQLSERVER2012 Audit (审核)功能

    数据库表结构和数据有时会被无意或者恶意,或者需要追踪最近的数据结构变更记录,以往必须通过日志查询,SQL Server2008开始提供了 审核(Audit )功能,SQL2012有所升级,利用它可以实 ...

  7. cookie、session与token

    一.详述概念 1.Cookie机制 cookie机制是采用在客户端保持状态的方案(cookie的作用就是为了解决HTTP协议无状态的缺陷所作的努力).cookie的使用是由浏览器按照一定的原则在后台自 ...

  8. linq操作文件方法

    备忘 string directory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); List<File ...

  9. markdown命令语法

    markDown作为一款很好用的文档编写工具,具体的用法如下: # Markdown syntax---**粗体***斜体****粗体加斜体*** > 引用>> 二级引用 # 一级标 ...

  10. JavaScript:异步 setTimeout

    setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式. function showDate(){ var date=new Date(); console.log(date); } ...