您现在所在的是:

嵌入式系统

回帖:0个,阅读:632 [上一页] [1] [下一页]
884
yefanqiu
文章数:33
年度积分:50
历史总积分:884
注册时间:2004/8/19
发站内信
发表于:2012/8/15 21:57:22
#0楼
 
TinyGUI是我在2010上半年的时候,基于.NET Micro Framework系统开发的一个轻量级图形库,虽然TinyGUI运行需要的资源少,运行快,但是不支持汉字显示(如需显示汉字还是必须借助WPF本身的功能,这显然背离了TinyGUI占用资源少的设计初衷了)。另外物联网组态系统YFHMI,考虑到性能和资源问题,也是要选择TinyGUI库的,而汉字显示功能又必不可少,这一切都促使了TinyGUI支持汉字显示功能的实现。
关于TinyGUI相关的内容,我从2010年开始,陆陆续续已经写了四篇博文,分别是《[/URL]为Cortex-M3打造轻量级TinyGUI》、《[/URL]TinyGUI绘图示例》、《[/URL]TinyGUI位图显示》和《[/URL]让TinyGUI库支持模拟器》,有兴趣的网友可以看一看,这里就不全部介绍了,本文仅介绍汉字显示部分。
一个GB2312字库大概含7、8千汉字字符,最常用的16*16点阵的这种字库,大概需要300K的RAM空间。如果同时支持几种字体,RAM的需求量会非常大,这对小型嵌入式系统来说是非常不可取的,
.NET Micro Framwork系统正是基于这种考虑,推出了Tinyfnt字库,可以任意定制字库(相关介绍,请参见我写的博文《[/URL].Net Micro Framework研究—中文显示》、《[/URL]Tinyfnt字体研究》和《[/URL]中文显示(WPF方式)》)。
最初,我很自然的打算就是让TinyGUI借助Tinyfnt字库,进行汉字显示。没有想到事隔5年重新又深入研究tinyfnt字体结构,方明白tinyfnt的字体点阵内容原来就是一个单色大位图,并且每个字符的宽度是不确定的,在位图中存放的位置是紧凑格式,你很难根据一个简单的算法,计算出第n个字符是位图上的那一个区域。此外WPF的实现相关代码太多和琐碎,你难以从现有的代码中进行提取和剥离,换句话说,你想用TinyGUI显示汉字,TinyCLR还得需要集成WPF绝大数代码。
由于我以前在DOS系统下有过汉字显示相关的开发经验,所以又想利用这类技术进行汉字显示(其实目前的很多嵌入式系统,都是采用类似的技术进行汉字显示的,不过有些汉字点阵信息被预先转换为C语言格式的数组了),我当时做的毕业设计,就是在这个这个技术的基础上,实现了图书管理系统(基于DOS平台,BC3.2开发,可以参见我的博文《[/URL]99年毕业设计获优的程序-图书管理程序》)。
不过很不幸的是,UCDOS下的汉字库是用区位码进行定位的,而.NET Micro Framework上的应用程序传入的字符串是UTF8编码的(底层C++代码需要自行对UTF8进行解码为Unicode代码),而区位码和Unicode编码是没有相关性的,没有一个简单统一的公式,进行二者的换算,如果非要进行转换,那只有查表这一个途径了,这将大大增加对RAM的需求量。另外UCDOS下的汉字库本身只含汉字信息,ASCII相关字符点阵信息,还需要另外的字库。
这里补充说明一下:在C++开发层面,ARM编辑器对字符串有两种编码格式,一种就是内码(针对汉字来说高低字节分别减去0xA0,就是区位码了),另外一种就是Unicode编码。比如如下的代码:
[/URL]图
char*s1="abc叶帆科技";
wchar_t*s2=L"abc叶帆科技";
BYTE*p1=(BYTE *)s1,*p2=(BYTE *)s2;
for(inti=0;i<11;i++)
{
  debug_printf("%02X",*p1++);
}
debug_printf("\r\n");
for(inti=0;i<14;i++)
{
  debug_printf("%02X",*p2++);
}
debug_printf("\r\n");
[/URL]图
其输出信息为:
图
目前大部分嵌入式系统为了实现简单,都是基于内码进行汉字显示的,这就有一个问题,产品如需支持多语言环境,比如同时显示繁体和简体就很实现。但是采用Unicode编码的字符集,就没有这类问题。
所以我最终决定还是自己做一个支持Unicode编码的点阵字库生成程序,生成的字库不仅支持汉字,也支持ASCII,且ASCII字符的宽度仅是汉字的一半,这样就非常有利于文字显示排版。而且和.NET Micro Framework的Tinyfnt字库一样,用户可以自定义字库的内容(这样如果需要显示的汉字不多,字库就会很小)。
另外考虑到UCDOS字库专门为点阵字库而做,其显示效果要比我们直接从矢量字库转换的点阵字库要漂亮的多,所以程序又添加了一个功能,如果字体名称选择了宋体、黑体、楷体和仿宋则会自动出现一个UCDOS选项,勾选这个选项,则点阵信息直接从UCDOS字库中提取。
下面就从字库大小、显示效果、加载方式和显示效率等四个方面和WPF汉字显示进行比较。
1字库大小比较
字符集:GB2312 + ASCII,字符数:7587

字库点阵
Tinyfnt实际大小
Tinyfnt(修正)
YFTF
备注
12*12
12*10:190k
228k
207k
宋体
16*16
16*14:283k
323k
308k
宋体
24*24
24*20:523k
627k
562k
宋体
注:(1)、windows字体中,所谓的字体大小的单位不是像素(px),而是点(pt):1px=3/4pt。比如12像素大小的字体,其实和9号字体相同。
(2)、windows字体转换为tinyfnt字体的时候,发现很难转换成正方形字体,比如9号字体转换为12像素的字体的时候,无论怎么调整宽度数,好像很难调整到12*12,默认的字体平均宽度是10,所以比较字体库大小的时候,才会出现一个修正大小的项。
从上表可以看出,如果点阵大小完全相同,tinyfnt字体库的大小是大于yftf字体库的大小的。原因是tinyfnt字体库不仅包含unicode编码和字体点阵信息,还包括了每一个字的左右偏移信息(因为tinyfnt字库,字体可以不等宽),所以理应比yftf字体库要大一些。
图
(从上图可以看出 tinyfnt的字体存储的比较紧凑)。
2字库显示效果
为了便于比较明显的比较出点阵字体效果差异,我们选择24*24的点阵字库进行比较,也包含了UCDOS的HZK24。
图
从比较的结果看,显然ucdos汉字库下提供字体更为漂亮(毕竟是专门为点阵字库而设计)。Yftf字库生成工具可以直接借用ucdos的点阵数据(生成的时候,记得勾选ucdos选项即可)。
3加载方式
(1)、WPF标准汉字显示程序如下:
[/URL]图
dc.DrawText("叶帆工作室[YFSoft]", Resources.GetFont(Resources.FontResources.z_12), c,5,25);
   dc.DrawText("叶帆工作室[YFSoft]", Resources.GetFont(Resources.FontResources.MS_16), c,5,45);
   dc.DrawText("叶帆工作室[YFSoft]", Resources.GetFont(Resources.FontResources.l_24), c,5,65);
[/URL]图
从以上代码可以看出,WPF的字体文件必须放在资源文件中,如果你用了一个16点阵的全字库,你的pe文件就会非常大,并且每次调试你都需要重新部署到设备中去,比较耗费时间。
(2)、TinyGUI字体库加载方式有两种,一种和WPF一样,把字体库文件放到资源文件中(字体比较少的字体库,比较适合放在资源文件中),另一种就是指定字体库在NandFlash中的地址和大小,这种方式只要部署一次就OK了,比较适合全字库方式。
第一种方式相关的代码如下:
UInt32 font24=Graphics.LoadFont(Resources.GetBytes(Resources.BinaryResources.Song24yf));
   Graphics.DrawString(10,10,"叶帆科技ABC", Color.Red, font24);
第二种方式的相关代码如下:
[/URL]图
UInt32 song12 = Graphics.LoadFont(0x01480000,0x3397C);
   UInt32 song16= Graphics.LoadFont(0x01480000+0x3397C,0x4CE40);
   UInt32 song24= Graphics.LoadFont(0x01480000+0x807BC,0x8C76C);
   Graphics.DrawString(10,60,"叶帆科技ABC", Color.Green, song12);
   Graphics.DrawString(10,80,"叶帆科技ABC", Color.Blue, song16);
   Graphics.DrawString(10,110,"叶帆科技ABC", Color.White, song24);
[/URL]图
不过在运行该代码之前,需要用YFAccessFlash工具把相关字体部署到【UserData】NandFlash区,如下图所示:
图
4显示效率
我们进行两种方式的比较,一种是小字库字体显示的速度比较,另一种是全字库字体显示的速度比较。
相关测试代码如下:

[/URL]图
Graphics.Clear(Color.Black);
   UInt32 font16yf=Graphics.LoadFont(Resources.GetBytes(Resources.BinaryResources.Song16yf));
   Font font16mf=Resources.GetFont(Resources.FontResources.song16mf);
   Microsoft.SPOT.Presentation.Media.Color c=Microsoft.SPOT.Presentation.Media.Color.White;
   Bitmap bmp=newBitmap(320,240);

   DateTime t=DateTime.Now;
for(inti =0; i <1000; i++)
   {
       bmp.DrawText("叶帆科技ABC", font16mf, c,10,10);
       bmp.Flush(10,10,96,16);
   }
   TimeSpan ts= DateTime.Now -t;
   Debug.Print("time="+ (ts.Seconds *1000+ ts.Milliseconds).ToString()+"ms");

   t=DateTime.Now;
for(inti =0; i <1000; i++)
   {
       Graphics.DrawString(10,30,"叶帆科技ABC", Color.Red, font16yf);
   }
   ts= DateTime.Now -t;
   Debug.Print("time="+ (ts.Seconds *1000+ ts.Milliseconds).ToString() +"ms");
[/URL]图
   显示性能比较表:
类型
精简字库
全字库(GB2312)
备注
WPF
1886ms
1910ms
仅刷新字体区
TinyGUI
880ms
904ms
直接操作显存
   
精简字库:1886/880 = 2.14
全字库:1910/904 = 2.11
从上表可以很清楚的看出,TinyGUI显示汉字的性能是WPF方式的两倍以上。
5 TinyGUI汉字显示操作流程简介
图
(1)、使用YFTinyFont制作yftf字库文件
(2)、把字库写入NandFlash 【UserData】区或添加到资源中
(3)、编程显示汉字
[/URL]图
UInt32 hwcy48 =Graphics.LoadFont(Resources.GetBytes(Resources.BinaryResources.hwcy48));
    Graphics.DrawString(10,80,"叶帆科技ABC", Color.White, hwcy48);
    UInt32 hwhp48=Graphics.LoadFont(Resources.GetBytes(Resources.BinaryResources.hwhp48));
    Graphics.DrawString(10,132,"叶帆科技ABC", Color.White, hwhp48);
    UInt32 fzst48=Graphics.LoadFont(Resources.GetBytes(Resources.BinaryResources.fzst48));
    Graphics.DrawString(10,184,"叶帆科技ABC", Color.White, fzst48);
[/URL]图
显示效果图如下:
图
除了为TinyGUI增加了直接显示汉字的功能外,还添加了触摸屏事件的支持,下一篇博文将介绍TinyGUI触摸屏功能的相关内容,敬请期待。

注意:为了正常运行本实例,[/URL]物联网智能网关固件版本需要升级到V1.7.16以上,(如果你当前TinyCLR版本低于V1.7.15以下,TinyBooter也需要同步升级)。
固件下载地址:[/URL]http://www.sky-walker.com.cn/MFRelease/firmware/MFv42_YF_Wisteria207.rar
-------------------------------------------------------  
源码下载:[/URL]http://www.sky-walker.com.cn/MFRelease/Sample/TinyGUITestHZ.rar
MF简介:[/URL]http://blog.csdn.net/yefanqiu/article/details/5711770
MF资料:[/URL]http://www.sky-walker.com.cn/News.asp?Id=25
[/URL]图
var isLogined = false;
var cb_blogId = 15167;
var cb_entryId = 2631239;
var cb_blogApp = currentBlogApp;
var cb_blogUserGuid = "b547360b-63cf-dd11-9e4d-001cf0cd104b";
var cb_entryCreatedDate = '2012/8/10 9:14:00';
var enableGoogleAd = true;
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
标签:[/URL].Net Micro Framework,[/URL]TinyGUI,[/URL]WPF
[/URL]
此帖来自中华工控网工控博客
原文件地址:http://blog.gkong.com/more.asp?id=160264&Name=yefanqiu

关于我们 | 联系我们 | 广告服务 | 本站动态 | 友情链接 | 法律声明 | 非法和不良信息举报

工控网客服热线:0755-86369299
版权所有 工控网 Copyright©2024 Gkong.com, All Rights Reserved

46.8003