• 电子书框架



    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
    
  • 相关阅读:
    无尽的冒险
    推荐一款好用的markdown编辑器,还可以引入vue主题
    你是微光
    Echarts 空心饼图示例
    vue + element-ui 制作tab切换(切换vue组件,踩坑总结)
    vue + element-ui 制作tab切换(适用于单页切换不同标记显示不同内容)
    Element UI 封装Table --> 实现动态创建表头和单元格数据(单元格内可动态增加非纯文本的内容)
    Element UI 封装Table --> 实现动态创建表头和单元格数据(无需写死表头和单元格数据)
    vue 部署到生产出现语法错误和css警告(Resource interpreted as Stylesheet but transferred with MIME type text/html: "www.aaa.com/cal/static/css/app.c06.css". vendor.4b6.js:1 Uncaught SyntaxError: Unexpected token '<')
    使用vue-cookies插件操作cookie
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/10555336.html
Copyright © 2020-2023  润新知