电子书框架


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

框架

mark

这里的分层还是基本按照老师来的,稍微调整了一下

  • 字体管理这里应该分成字体引擎和字体数据

  • 绘图这里提取出绘制文本框,后续可以加入绘制几何图形,绘制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模块,负责页面管理统筹,文件读取

优化

  1. 老师的代码中,文本的输入边界就是lcd的大小,这里我定义了文本框的边界

    static struct
    {
    	unsigned int x1;
    	unsigned int y1;
    	unsigned int x2;
    	unsigned int y2;
    	unsigned int color;
    }txt_info={
    .color =0xF0F0F0
    };
    
  2. 关于页码,老师使用链表管理页面,但是这样的话页码跳转就需要遍历链表,我这里使用一个大数组管理页面

    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;

mark

tips

当没有定义的时候去工具链搜索

grep "xxx"  -nR
原文地址:https://www.cnblogs.com/zongzi10010/p/10555336.html