文件结构

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. 从零构建JavaScript的对象系统

    一.正统的类与继承 类是对象的定义,而对象是类的实例(Instance).类不可直接使用,要想使用就必须在内存上生成该类的副本,这个副本就是对象. 以Java为例: public class Grou ...

  2. Thinkphp控制器,1.多层控制器2.多级控制器

    1.多层控制器 ThinkPHP的控制器支持多层和多级,多层指的是控制器可以分层,例如除了默认的Controller控制器层(我们可以称之为访问控制器),还可以添加事件控制器(层),例如: ├─Con ...

  3. js 时间函数封装

    html代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  4. .NET中MemCached使用介绍

    阅读目录 1.MemCached是什么? 2.Window中MemCached安装 3.MemCached命令 4.简单示例 MemCached是什么 MemCached是一个自由开源,高性能,分布式 ...

  5. sqlserver锁表、解锁、查看销表 (转载)

    sqlserver中怎么锁表.解锁.查看销表呢,下面我以三个不同的实例给各位朋友详细介绍一下有需要的朋友可参考一下. 更多详细内容请查看:http://www.111cn.net/database/O ...

  6. Windows 64位 RabbitMQ 安装配置

    1:下载Erlang,地址:http://www.erlang.org/download/otp_win64_19.0.exe ,双击安装即可(首先装) 2:下载RabbitMQ,RabbitMQ 3 ...

  7. how-to-install-siege-on-centos-7

    https://www.joedog.org/siege-home/ https://roastahost.com/how-to-install-siege-on-centos-7/ (Works!) ...

  8. 汽车ABS系统-第一周作业

    ABS系统也成防抱死系统(Anti-lock Braking System),由罗伯特·博世有限公司所开发的一种在摩托车和汽车中使用,它会根据各车轮角速度信号,计算得到车速.车轮角减速度.车轮滑移率: ...

  9. Leetcode: Line Reflection

    Given n points on a 2D plane, find if there is such a line parallel to y-axis that reflect the given ...

  10. 使用IIS发布WCF服务

    上一篇是Windows服务为宿主的WCF服务,现在用IIS为宿主发布WCF服务. 第一步:肯定是新建一个WCF服务啦[是WCF服务应用程序],然后在解决方案上再次添加一个新项目[我们选择WCF服务库, ...