【物联网智能网关-08】TinyGUI和WPF汉字显示技术比较

简介: TinyGUI是我在2010上半年的时候,基于.NET Micro Framework系统开发的一个轻量级图形库,虽然TinyGUI运行需要的资源少,运行快,但是不支持汉字显示(如需显示汉字还是必须借助WPF本身的功能,这显然背离了TinyGUI占用资源少的设计初衷了)。

TinyGUI是我在2010上半年的时候,基于.NET Micro Framework系统开发的一个轻量级图形库,虽然TinyGUI运行需要的资源少,运行快,但是不支持汉字显示(如需显示汉字还是必须借助WPF本身的功能,这显然背离了TinyGUI占用资源少的设计初衷了)。另外物联网组态系统YFHMI,考虑到性能和资源问题,也是要选择TinyGUI库的,而汉字显示功能又必不可少,这一切都促使了TinyGUI支持汉字显示功能的实现。

关于TinyGUI相关的内容,我从2010年开始,陆陆续续已经写了四篇博文,分别是《Cortex-M3打造轻量级TinyGUI》、《TinyGUI绘图示例》、《TinyGUI位图显示》和《TinyGUI库支持模拟器》,有兴趣的网友可以看一看,这里就不全部介绍了,本文仅介绍汉字显示部分。

一个GB2312字库大概含7、8千汉字字符,最常用的16*16点阵的这种字库,大概需要300K的RAM空间。如果同时支持几种字体,RAM的需求量会非常大,这对小型嵌入式系统来说是非常不可取的,

.NET Micro Framwork系统正是基于这种考虑,推出了Tinyfnt字库,可以任意定制字库(相关介绍,请参见我写的博文《.Net Micro Framework研究—中文显示》、《Tinyfnt字体研究》和《中文显示(WPF方式)》)。

最初,我很自然的打算就是让TinyGUI借助Tinyfnt字库,进行汉字显示。没有想到事隔5年重新又深入研究tinyfnt字体结构,方明白tinyfnt的字体点阵内容原来就是一个单色大位图,并且每个字符的宽度是不确定的,在位图中存放的位置是紧凑格式,你很难根据一个简单的算法,计算出第n个字符是位图上的那一个区域。此外WPF的实现相关代码太多和琐碎,你难以从现有的代码中进行提取和剥离,换句话说,你想用TinyGUI显示汉字,TinyCLR还得需要集成WPF绝大数代码。

由于我以前在DOS系统下有过汉字显示相关的开发经验,所以又想利用这类技术进行汉字显示(其实目前的很多嵌入式系统,都是采用类似的技术进行汉字显示的,不过有些汉字点阵信息被预先转换为C语言格式的数组了),我当时做的毕业设计,就是在这个这个技术的基础上,实现了图书管理系统(基于DOS平台,BC3.2开发,可以参见我的博文《99年毕业设计获优的程序-图书管理程序》)。

不过很不幸的是,UCDOS下的汉字库是用区位码进行定位的,而.NET Micro Framework上的应用程序传入的字符串是UTF8编码的(底层C++代码需要自行对UTF8进行解码为Unicode代码),而区位码和Unicode编码是没有相关性的,没有一个简单统一的公式,进行二者的换算,如果非要进行转换,那只有查表这一个途径了,这将大大增加对RAM的需求量。另外UCDOS下的汉字库本身只含汉字信息,ASCII相关字符点阵信息,还需要另外的字库。

这里补充说明一下:在C++开发层面,ARM编辑器对字符串有两种编码格式,一种就是内码(针对汉字来说高低字节分别减去0xA0,就是区位码了),另外一种就是Unicode编码。比如如下的代码:

char *s1="abc叶帆科技";

wchar_t *s2=L"abc叶帆科技";

BYTE *p1=(BYTE *)s1,*p2=(BYTE *)s2;

for(int i=0;i<11;i++)

{

   debug_printf("%02X",*p1++);

}

debug_printf("\r\n");

for(int i=0;i<14;i++)

{

   debug_printf("%02X",*p2++);

}

debug_printf("\r\n");

其输出信息为:

目前大部分嵌入式系统为了实现简单,都是基于内码进行汉字显示的,这就有一个问题,产品如需支持多语言环境,比如同时显示繁体和简体就很实现。但是采用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标准汉字显示程序如下:

    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);

从以上代码可以看出,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);

第二种方式的相关代码如下:

    UInt32song12 = Graphics.LoadFont(0x01480000,0x3397C);

    UInt32song16 = Graphics.LoadFont(0x01480000 +0x3397C, 0x4CE40);

    UInt32song24 = 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);

不过在运行该代码之前,需要用YFAccessFlash工具把相关字体部署到【UserData】NandFlash区,如下图所示:


4显示效率

我们进行两种方式的比较,一种是小字库字体显示的速度比较,另一种是全字库字体显示的速度比较。

相关测试代码如下:

Graphics.Clear(Color.Black);

    UInt32font16yf = Graphics.LoadFont(Resources.GetBytes(Resources.BinaryResources.Song16yf));

    Fontfont16mf = Resources.GetFont(Resources.FontResources.song16mf);

    Microsoft.SPOT.Presentation.Media.Color c = Microsoft.SPOT.Presentation.Media.Color.White;

    Bitmapbmp = new Bitmap(320,240);

 

    DateTimet = DateTime.Now;

    for (int i = 0; i < 1000; i++)

    {

        bmp.DrawText("叶帆科技ABC", font16mf, c, 10, 10);

        bmp.Flush(10, 10, 96, 16);

    }

    TimeSpants = DateTime.Now - t;

    Debug.Print("time=" + (ts.Seconds * 1000 +ts.Milliseconds).ToString()+"ms");

 

    t = DateTime.Now;

    for (int i = 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");

 

    显示性能比较表:

类型

精简字库

全字库(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)、编程显示汉字

     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);

     UInt32fzst48 = Graphics.LoadFont(Resources.GetBytes(Resources.BinaryResources.fzst48));

     Graphics.DrawString(10, 184, "叶帆科技ABC", Color.White,fzst48);

显示效果图如下:

除了为TinyGUI增加了直接显示汉字的功能外,还添加了触摸屏事件的支持,下一篇博文将介绍TinyGUI触摸屏功能的相关内容,敬请期待。

 

注意:为了正常运行本实例,物联网智能网关固件版本需要升级到V1.7.16以上,(如果你当前TinyCLR版本低于V1.7.15以下,TinyBooter也需要同步升级)。

固件下载地址:http://www.sky-walker.com.cn/MFRelease/firmware/MFv42_YF_Wisteria207.rar

 ---------------------------------------------------------------   

源码下载:http://www.sky-walker.com.cn/MFRelease/Sample/TinyGUITestHZ.rar

MF简介:http://blog.csdn.net/yefanqiu/article/details/5711770

MF资料:http://www.sky-walker.com.cn/News.asp?Id=25


相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
相关文章
|
缓存 C# 虚拟化
WPF列表性能提高技术
WPF数据绑定系统不仅需要绑定功能,还需要能够处理大量数据而不会降低显示速度和消耗大量内存,WPF提供了相关的控件以提高性能,所有继承自`ItemsControl`的控件都支持该技术。
|
4月前
|
vr&ar C# 图形学
WPF与AR/VR的激情碰撞:解锁Windows Presentation Foundation应用新维度,探索增强现实与虚拟现实技术在现代UI设计中的无限可能与实战应用详解
【8月更文挑战第31天】增强现实(AR)与虚拟现实(VR)技术正迅速改变生活和工作方式,在游戏、教育及工业等领域展现出广泛应用前景。本文探讨如何在Windows Presentation Foundation(WPF)环境中实现AR/VR功能,通过具体示例代码展示整合过程。尽管WPF本身不直接支持AR/VR,但借助第三方库如Unity、Vuforia或OpenVR,可实现沉浸式体验。例如,通过Unity和Vuforia在WPF中创建AR应用,或利用OpenVR在WPF中集成VR功能,从而提升用户体验并拓展应用功能边界。
79 0
|
4月前
|
C# Windows 开发者
当WPF遇见OpenGL:一场关于如何在Windows Presentation Foundation中融入高性能跨平台图形处理技术的精彩碰撞——详解集成步骤与实战代码示例
【8月更文挑战第31天】本文详细介绍了如何在Windows Presentation Foundation (WPF) 中集成OpenGL,以实现高性能的跨平台图形处理。通过具体示例代码,展示了使用SharpGL库在WPF应用中创建并渲染OpenGL图形的过程,包括开发环境搭建、OpenGL渲染窗口创建及控件集成等关键步骤,帮助开发者更好地理解和应用OpenGL技术。
293 0
|
4月前
|
开发者 C# 容器
【独家揭秘】当WPF邂逅DirectX:看这两个技术如何联手打造令人惊艳的高性能图形渲染体验,从环境搭建到代码实践,一步步教你成为图形编程高手
【8月更文挑战第31天】本文通过代码示例详细介绍了如何在WPF应用中集成DirectX以实现高性能图形渲染。首先创建WPF项目并使用SharpDX作为桥梁,然后在XAML中定义承载DirectX内容的容器。接着,通过C#代码初始化DirectX环境,设置渲染逻辑,并在WPF窗口中绘制图形。此方法适用于从简单2D到复杂3D场景的各种图形处理需求,为WPF开发者提供了高性能图形渲染的技术支持和实践指导。
265 0
|
4月前
|
C# 开发者 Windows
WPF遇上Office:一场关于Word与Excel自动化操作的技术盛宴,从环境搭建到代码实战,看WPF如何玩转文档处理的那些事儿
【8月更文挑战第31天】Windows Presentation Foundation (WPF) 是 .NET Framework 的重要组件,以其强大的图形界面和灵活的数据绑定功能著称。本文通过具体示例代码,介绍如何在 WPF 应用中实现 Word 和 Excel 文档的自动化操作,包括文档的读取、编辑和保存等。首先创建 WPF 项目并设计用户界面,然后在 `MainWindow.xaml.cs` 中编写逻辑代码,利用 `Microsoft.Office.Interop` 命名空间实现 Office 文档的自动化处理。文章还提供了注意事项,帮助开发者避免常见问题。
272 0
|
4月前
|
C# UED 开发者
WPF打印功能实现秘籍:从页面到纸张,带你玩转WPF打印技术大揭秘!
【8月更文挑战第31天】在WPF应用开发中,打印功能至关重要,不仅能提升用户体验,还增强了应用的实用性。本文介绍WPF打印的基础概念与实现方法,涵盖页面元素打印、打印机设置及打印预览。通过具体案例,展示了如何利用`PrintDialog`和`PrintDocument`控件添加打印支持,并使用`PrinterSettings`类进行配置,最后通过`PrintPreviewWindow`实现打印预览功能。
421 0
|
存储 自然语言处理 C#
WPF技术之Binding
WPF(Windows Presentation Foundation)是微软推出的一种用于创建应用程序用户界面的框架。Binding(绑定)是WPF中的一个重要概念,它用于在界面元素和数据源之间建立关联。通过Binding,可以将界面元素(如文本框、标签、列表等)与数据源(如对象、集合、属性等)进行绑定,从而实现数据的双向传递和同步更新。
291 2
WPF技术之Binding
|
前端开发 C# 容器
WPF技术之Command
WPF Command是一种在MVVM(Model-View-ViewModel)模式中用于处理用户界面交互的机制。它可以将用户界面事件(如按钮点击、菜单项选择等)与应用程序逻辑(命令处理)解耦,同时提供了一种便捷的方式来管理和执行命令
316 2
|
C#
WPF技术之动画系列-上下运动
本例子展现动画小球上下循环运动
225 0
|
定位技术 C# UED
WPF技术之ScrollViewer控件
WPF ScrollViewer是WPF中常用的一个控件,它提供了滚动视图的功能,可用于显示超出容器可视区域的内容。ScrollViewer通常用于容纳大量内容的控件,以在有限的空间内显示这些内容,并允许用户通过滚动来查看隐藏的部分。
1282 0

热门文章

最新文章

相关产品

  • 物联网平台