迅维网

查看: 2624|回复: 0
打印 上一主题 下一主题

【emWin实战教程V2.0】第28章 矢量字体(支持汉字全字库,Unicode编码)

[复制链接]
跳转到指定楼层
1#
发表于 2017-2-7 12:43:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式 来自: 山东青岛 来自 山东青岛

马上注册,获取阅读精华内容及下载权限

您需要 登录 才可以下载或查看,没有帐号?注册

x

转最新版本教程
本期教程跟大家讲解矢量字体的相关知识,矢量字体最大的好处就是可以任意放大或者缩小字体,而且字体的显示效果不失真。矢量字体也有缺点,即非常消耗内存。但是本教程配套开发板的STM32F429是支持外接SDRAM,这样就有大容量的空间供矢量字体使用了。
28.1 初学者重要提示
28.2 矢量字体介绍
28.3 STemWin对矢量字体的支持
28.4 矢量字体库的移植方法
28.5 矢量字体库的使用方法
28.6 实验例程说明(RTOS)
28.7 实验例程说明(裸机)
28.8 总结
28.1  初学者重要提示

1、使用STM32F429+大容量的SDRAM来实现矢量字体具有一定的实战意义,可用于实际项目。
2、实验中发现了以下三个问题,给大家分享下:
    (1)、不是所有电脑端的矢量字体都可以显示,测试发现有些无法正常显示,估计是emWin库不支持。
    (2)、不能显示太大的字体,测试发现130点阵之后就无法显示了,不知道是不是动态内存和系统堆空间分配小了,以后换了超大容量SDRAM再测试。
    (3)、显示比较大的字体,STM32F429的图形性能完全跟的上,但CPU的计算性能有些吃紧,表现在800*480界面显示满屏字符的时候,整体拖动窗口反应不够流畅。
3、矢量字体也是用的Unicode编码,这点要特别注意。
4、矢量字体所有API函数在emWin手册中都有讲解,下图是中文版手册里面API函数的位置

                               
登录/注册后看高清大图


下图是英文版手册里面API函数的位置:

                               
登录/注册后看高清大图
28.2矢量字体介绍

    下面的内容来中文版wiki百科,讲的非常好,特此转载过来:https://zh.wikipedia.org/wiki/%E ... F%E5%AD%97%E4%BD%93

    目前主流的矢量字体格式有3种:Type1,TrueType和OpenType,这三种格式都是与平台无关的。
        Type1全称PostScript Type1,是1985年由Adobe公司提出的一套矢量字体标准,由于这个标准是基于PostScriptDescription Language(PDL),而PDL又是高端打印机首选的打印描述语言,所以Type1迅速流行起来。但是Type1是非开放字体,Adobe对使用Type1的公司征收高额的使用费。
    TrueType是1991年由Apple公司与Microsoft公司联合提出另一套矢量字标准。
   
     Type1使用三次贝塞尔曲线来描述字形,TrueType则使用二次贝塞尔曲线来描述字形。所以Type1的字体比TrueType字体更加精确美观。一个误解是,Type1字体比TrueType字体占用空间多。这是因为同样描述一个圆形,二次贝塞尔曲线只需要8个关键点和7段二次曲线;而三次贝塞尔曲线则需要12个关键点和11段三次曲线。然而实际情况是一般来说 Type1比TrueType要小10%左右。这是因为对于稍微复杂的字形,为了保持平滑,TrueType必须使用更多的关键点。由于现代大部分打印机都是使用PDL作为打印描述语言,所以Type1字体打印的时候不会产生形变,速度快;而TrueType则需要翻译成PDL,由于曲线方程的变化,还会产生一定的形变,不如Type1美观。
    这么说来,Type1应该比TrueType更具有优势,为什么如今的计算机上TrueType反而比Type1使用更广泛呢?这是因为第一:Type1由于字体方程的复杂,所以在屏幕上渲染的时候,花费的时间多,解决方案是大部分Type1字体嵌入了点阵字体,这样渲染快,但是边缘不光滑,比较难看。很多ps文档和ps转换的pdf文档都是这样,在计算机上浏览的时候字体很难看,但是打印出来很美观。TrueType则渲染比较快,可以平滑的显示在屏幕上,看上去很美观。
    第二个原因是Type1的高额使用费,使得Type1没有被所有的操作系统所支持。Windows家族只有OS/2和windows2000及之后的版本从操作系统级别开始支持Type1。由于这个问题,Adobe只好在其所有的产品中嵌入Adobe Type Manager(ATM)作为渲染引擎。






OpenType则是Type1与TrueType之争的最终产物。1995年,Adobe公司和Microsoft公司开始联手开发一种兼容Type1和TrueType,并且真正支持Unicode的字体,后来在发布的时候,正式命名为OpenType。OpenType可以嵌入Type1和TrueType,这样就兼有了二者的特点,无论是在屏幕上察看还是打印,质量都非常优秀。可以说OpenType是一个三赢的结局,无论是Adobe、Microsoft还是最终用户,都从OpenType中得到了好处。Windows家族从Windows 2000开始,正式支持OpenType。打开系统的字体目录(一般是C:\Windows\Fonts\或C:\Winnt\Fonts),可以看到:一个红色A的图标的是点阵字体,两个重叠的T的图标是TrueType字体,一个O的图标就是OpenType字体。
    下面是XP系统中字体的部分截图,其中矢量字体扩展名ttf,点阵字体的扩展名是fon。

                               
登录/注册后看高清大图
OpenType则是Type1与TrueType之争的最终产物。1995年,Adobe公司和Microsoft公司开始联手开发一种兼容Type1和TrueType,并且真正支持Unicode的字体,后来在发布的时候,正式命名为OpenType。OpenType可以嵌入Type1和TrueType,这样就兼有了二者的特点,无论是在屏幕上察看还是打印,质量都非常优秀。可以说OpenType是一个三赢的结局,无论是Adobe、Microsoft还是最终用户,都从OpenType中得到了好处。Windows家族从Windows 2000开始,正式支持OpenType。打开系统的字体目录(一般是C:\Windows\Fonts\或C:\Winnt\Fonts),可以看到:一个红色A的图标的是点阵字体,两个重叠的T的图标是TrueType字体,一个O的图标就是OpenType字体。
    下面是XP系统中字体的部分截图,其中矢量字体扩展名ttf,点阵字体的扩展名是fon。

                               
登录/注册后看高清大图
Win7系统中已经变成如下这种样子:

                               
登录/注册后看高清大图
除了malloc和free要用到堆空间,部分C标准库的其它函数也要用到堆空间,所以一定要及时初始化SDRAM,防止用到堆空间的时候,SDRAM还没有初始化,将导致系统崩溃。当前是将SDRAM的初始化放在了bsp.c文件的bsp_Init函数开始的地方,之前执行的程序都没有用到C标准库,所以可以放在这里。
    讲解完这些,还有一点知识要补充的,矢量汉字库是非常大的,稍小点的都得10MB,大点的得20MB,教程配套板子的SDRAM只有16MB,有点捉襟见肘,所以要重新划分下,当前是把前3MB的空间给LCD的显存使用,相关代码不用做任何修改,因为默认的800*480分辨率,RGB565格式的三缓冲大小800*480*2*3 大概是2.19MB(乘以2是因为RGB565格式需要2字节来表示一个像素),小于3MB。中间的12MB用于emWin动态内存,最后1MB用于系统堆空间,这里有两个地方要修改一下,一个是bsp_fmc_sdram.h文件,修改emWin动态内存的起始地址
复制代码
/*
**********************************************************************************************************
                                          emWin使用
**********************************************************************************************************
*/
/* emWin动态内存首地址 */
#define SDRAM_APP_BUF  (EXT_SDRAM_ADDR + 3 * 1024 * 1024)
另一个是GUIConf.c文件,将emWin的动态内存大小设置为12MB,即下面置红的字体。
复制代码
//
// Define the available number of bytes available for the GUI
//
#define EX_SRAM   1/*1 used extern sram, 0 used internal sram */
#if EX_SRAM
#define GUI_NUMBYTES  (1024*1024*12)
#else
#define GUI_NUMBYTES  (100*1024)
#endif
/* Define the average block size */
#define GUI_BLOCKSIZE 0x80

修改完毕这几个地方后,就没有问题了,使用的时候选取了仿宋体,大小是10MB,系统上电后将其加载到emWin的动态内存里面,也就是SDRAM里面。
[table=98%]
第4步:修改系统堆(heap)大小,这一步非常关键。因为矢量库要用到函数malloc和free,而这种函数是从系统堆空间里面申请内存的,鉴于矢量库非常的消耗动态内存,这里将16MB SDRAM的最后1MB空间给系统堆使用,IAR中设置堆使用外部空间比MDK要麻烦些,需要修改本章节配套例程路径\Project\EWARMv7里面的文件stm32f4xx_flash.icf,内容如下(红色字体部分是新添加的或者被修改的):
复制代码
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__   = 0x081FFFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x2002FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x0400;
define symbol __ICFEDIT_size_heap__   = 0x100000;
/**** End of ICF editor section. ###ICF###*/
define symbol __region_RAM1_start__ = 0x10000000;
define symbol __region_RAM1_end__   = 0x1000FFFF;
define symbol __region_RAM2_start__ = 0xC0F00000;
define symbol __region_RAM2_end__   = 0xC0FFFFFF;
define memory mem with size = 4G;
define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];
define region RAM1_region  = mem:[from __region_RAM1_start__   to __region_RAM1_end__];
define region RAM2_region  = mem:[from __region_RAM2_start__   to __region_RAM2_end__];
define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };
initialize by copy { readwrite };
do not initialize  { section .noinit };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in ROM_region   { readonly };
place in RAM_region   { readwrite, block CSTACK};
place in RAM1_region  { section .sram };
place in RAM2_region  { section .sram, block HEAP };
[table=98%]
define symbol __ICFEDIT_size_heap__   = 0x100000;
    重新设置堆空间大小是1MB。
define symbol __region_RAM2_start__ =0xC0F00000;
define symbol__region_RAM2_end__  = 0xC0FFFFFF;
    添加的RAM2的起始地址和结束地址定义,
      __region_RAM2_start__:表示堆起始地址为0XC0F00000,即16MB SDRAM最后1MB空间的起始地址。
      __region_RAM2_end__ : 堆结束地址0XC0FFFFFF,即16MBSDRAM最后1MB空间的结束地址。
define regionRAM2_region  = mem:[from__region_RAM2_start__   to__region_RAM2_end__];

    设置新添加RAM2的区间范围。
place in RAM_region { readwrite, block CSTACK};
    表示将栈空间放到RAM区域,可读可写。
place in RAM2_region  { section .sram, block HEAP };
    表示将堆空间放到RAM2区域,可读可写。
[table=98%]
通过上面的设置就实现将16MB SDRAM的最后1MB空间给系统堆使用。除了malloc和free要用到堆空间,部分C标准库的其它函数也要用到堆空间,所以一定要及时初始化SDRAM,防止用到堆空间的时候,SDRAM还没有初始化,将导致系统崩溃。当前是将SDRAM的初始化放在了bsp.c文件的bsp_Init函数开始的地方,之前执行的程序都没有用到C标准库,所以可以放在这里。
    讲解完这些,还有一点知识要补充的,矢量汉字库是非常大的,稍小点的都得10MB,大点的得20MB,教程配套板子的SDRAM只有16MB,有点捉襟见肘,所以要重新划分下,当前是把前3MB的空间给LCD的显存使用,相关代码不用做任何修改,因为默认的800*480分辨率,RGB565格式的三缓冲大小800*480*2*3 大概是2.19MB(乘以2是因为RGB565格式需要2字节来表示一个像素),小于3MB。中间的12MB用于emWin动态内存,最后1MB用于系统堆空间,这里有两个地方要修改一下,一个是bsp_fmc_sdram.h,修改emWin动态内存的起始地址
复制代码
/*
**********************************************************************************************************
                                          emWin使用
**********************************************************************************************************
*/
/* emWin动态内存首地址 */
#define SDRAM_APP_BUF  (EXT_SDRAM_ADDR + 3 * 1024 * 1024
[table=98%]
另一个是GUIConf.c文件,将emWin的动态内存大小设置为12MB,即下面置红的字体。
复制代码
//
// Define the available number of bytes available for the GUI
//
#define EX_SRAM   1/*1 used extern sram, 0 used internal sram */
#if EX_SRAM
#define GUI_NUMBYTES  (1024*1024*12)
#else
#define GUI_NUMBYTES  (100*1024)
#endif
/* Define the average block size */
#define GUI_BLOCKSIZE 0x80

修改完毕这几个地方后,就没有问题了,使用的时候选取了仿宋体,大小是10MB,系统上电后将其加载到emWin的动态内存里面,也就是SDRAM里面
[table=98%]
28.5  矢量字体库的使用方法


    矢量字体的使用通过下面四步就可以实现:
第1步:定义16点阵大小,24点阵大小,32点阵大小,48点阵大小,72点阵大小和120点阵大小的格式字体。
复制代码
/*
*********************************************************************************************************
*                                      定义矢量字体
*********************************************************************************************************
*/
GUI_TTF_CS Cs0, Cs1, Cs2, Cs3, Cs4, Cs5;
GUI_TTF_DATA Data;
GUI_FONT Font16, Font24, Font32, Font48, Font72, Font120;
[/td][/tr]
[/table]
[/td][/tr]
[/table]
[/td][/tr]
[/table]
[/td][/tr]
[/table][/td][/tr]
[/table]

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表
附近
店铺
微信扫码查看附近店铺
维修
报价
扫码查看手机版报价
信号元
件查询
点位图 AI维修
助手



芯片搜索

快速回复