title: 电子书框架
date: 2019/3/4 16:48:50
toc: true
电子书框架
代码仓库
代码仓库 https://gitee.com/layty/project_for_linux/tree/master/03-ebook/01-showfile_by_cmd
框架
这里的分层还是基本按照老师来的,稍微调整了一下
-
字体管理这里应该分成字体引擎和字体数据
-
绘图这里提取出绘制文本框,后续可以加入绘制几何图形,绘制bmp等
-
文件编码处理,这里稍微调整下数据结构,编码文件提供识别接口与读取code,编码允许强制指定无BOM,app可以调用的时候可以使用函数获得BOM,也允许直接指定,根据不同接口可以指定或者不指定BOM长度
// 具体使用参见 code_type=0,bom_len=0 使用自动识别的方式 // 识别不了使用utf-8 int OpenFile(char* file_path, char * code_type,unsigned int bom_len) { struct stat tStat; g_readfile.fd=open(file_path, O_RDONLY); if (0 > g_readfile.fd) { DBG_PRINTF("can't open text file %s ", file_path); return -1; } if(fstat(g_readfile.fd, &tStat)) { DBG_PRINTF("can't get fstat "); return -1; } g_readfile.rawbuf = (unsigned char *)mmap(NULL , tStat.st_size, PROT_READ, MAP_SHARED, g_readfile.fd, 0); if (g_readfile.rawbuf == (unsigned char *)-1) { DBG_PRINTF("can't mmap for text file "); return -1; } g_readfile.end = g_readfile.rawbuf + tStat.st_size; if(code_type!=NULL) { g_readfile.encode_engine=FindEncodeByName(code_type); if (g_readfile.encode_engine!=NULL) { g_readfile.bom_len=bom_len; g_readfile.read_offset=&g_readfile.rawbuf[g_readfile.bom_len]; } else return -1; } else { g_readfile.encode_engine=FindEncodeByBuff(g_readfile.rawbuf,tStat.st_size<3?tStat.st_size:3); if(g_readfile.encode_engine!=NULL) { g_readfile.bom_len=g_readfile.encode_engine->head_len; g_readfile.read_offset=&g_readfile.rawbuf[g_readfile.bom_len]; } else { g_readfile.bom_len=0; g_readfile.read_offset=0; g_readfile.encode_engine=FindEncodeByName("UTF-8"); } } DBG_PRINTF("file encode is %s ",g_readfile.encode_engine->name); return g_readfile.fd; }
-
ebook模块,负责页面管理统筹,文件读取
优化
-
老师的代码中,文本的输入边界就是lcd的大小,这里我定义了文本框的边界
static struct { unsigned int x1; unsigned int y1; unsigned int x2; unsigned int y2; unsigned int color; }txt_info={ .color =0xF0F0F0 };
-
关于页码,老师使用链表管理页面,但是这样的话页码跳转就需要遍历链表,我这里使用一个大数组管理页面
typedef struct pageinfo { int page_now; //当前的页码,从0开始计数 int page_end; //解析了多少页了,0表示没有解析过,当=1的时候已经能够显示2页了 int page_book; //解析总共会有多少页 unsigned char * page_raw[MAX_PAGE_NUM]; //这里不使用链表结构,能够更快速的实现页码的跳转 1000页显示 }T_pageinfo;
坐标体系
在电子书这里,最复杂的结构其实就是位图的描述,这里摘录关键代码如下
- 坐标体系有LCD和笛卡尔两个坐标
- 位图的边界有字体的边界和数据有效区的边界
换行坐标计算
// 换行 tmp=now-last
// txt_info.x1 是x边界,差值就是 当前减去之前计算的坐标
// 新坐标就是(x边界,y+一个字体的高度)
tmpx=txt_info.x1-g_bmp_info.now_penx;
tmpy=g_bmp_info.fontsize;
// x=x+x差值
// y=y+y差值
g_bmp_info.now_penx=g_bmp_info.now_penx+tmpx;
g_bmp_info.now_peny=g_bmp_info.now_peny+tmpy;
g_bmp_info.xleft=g_bmp_info.xleft+tmpx;;
g_bmp_info.ytop=g_bmp_info.ytop+tmpy;;
g_bmp_info.xright=g_bmp_info.xright+tmpx;;
g_bmp_info.ydown=g_bmp_info.ydown+tmpy;;
g_bmp_info.next_penx=g_bmp_info.next_penx+tmpx;
g_bmp_info.next_peny=g_bmp_info.next_peny+tmpy;
坐标系转换
/*
笛卡尔的原点
now_penx now_peny
位图有效数据的边界
font_map_info->xleft font_map_info->ytop
font_map_info->xright font_map_info->ydown
字体的边界,也就是下一个原点
font_map_info->next_penx
font_map_info->next_peny
*/
// calc bmp size
font_map_info->xleft=now_penx+g_ft_slot->bitmap_left;
font_map_info->ytop=now_peny- g_ft_slot->bitmap_top;
font_map_info->xright = font_map_info->xleft + g_ft_slot->bitmap.width;
font_map_info->ydown = font_map_info->ytop + g_ft_slot->bitmap.rows;
font_map_info->bpp = 1;
font_map_info->pitch = g_ft_slot->bitmap.pitch;
font_map_info->raw_buf = g_ft_slot->bitmap.buffer;
// next pen
font_map_info->next_penx = now_penx + g_ft_slot->advance.x / 64;
font_map_info->next_peny = now_peny+g_ft_slot->advance.y / 64;
tips
当没有定义的时候去工具链搜索
grep "xxx" -nR