当前位置:首页 > > 充电吧
[导读]VxWorks汉字显示解决方案3162412793@qq.com技术交流QQ群: 691976956一. VxWorks操作系统图形显示方案VxWorks作为嵌入式实时操作系统的龙头老大,在国内应用已

VxWorks汉字显示解决方案

3162412793@qq.com

技术交流QQ群: 691976956


一. VxWorks操作系统图形显示方案

VxWorks作为嵌入式实时操作系统的龙头老大,在国内应用已非常广泛,其中包括工业控制、医疗设备、家庭视听、车载电子等许多需要本地显示的行业。作为国内的显示应用,汉字显示是必不可少的,而vxWorks原厂商没有直接提供完备的汉字显示解决方案,本文就这个热点论题,通过对VxWorks显示组件的分析,具体给出一种汉字显示的方案。

VxWorks的汉字显示首先需要一种图形解决方案,只有工作在图形模式下才可能显示汉字。vxWorks有三种显示的方案可供选择:

1. WindML + Zinc:

WindML是wind river mutli-media library 的简称,其中包含UGL(universal graphics library)。该组件直接控制显示硬件,主要提供显示模式设置、标准输入输出控制、点线面作图等函数,编程接口很类似于Torbo C,Borland C里的图形库。Zinc基于WindML,提供了类Windows风格的接口,有各种控件被封装于内,编程接口很类似于windows编程。

2.WindML + Jworks:

Jworks 提供Java的支持,在VxWorks上启动Java 虚拟机来解释Java语言,图形开发编程接口是Java语言,Java虚拟机的图形实现基于WindML。

3.web server + WindML + Jworks + browser:

web server 使显示编程接口成为编写网页,可以通过远程的browser来访问而使设备具有远程显示接口,也可以在本机做browser使设备具有本机显示接口,该browser的实现需要WindML或Jworks的支持。

上述方案内,纯web server的方案不需要本地汉字显示,只要在网页上放国标码或unicode码等,由远程的browser去实现显示;其它方案基本上都需要WindML的支持,这是因为VxWorks系统里所有底层的显示操作都是通过WindML实现。

二.汉字显示方案

实现本地汉字显示的方案一定会涉及到WindML,只是不同的方案对WindML的依赖程度有所不同,一般有如下几种:

1.利用WindML对双字节编码的支持,实现对汉字的点阵存储、点阵获取、点阵显示的全过程,并使用WindML的双字节显示函数实现汉字码到汉字显示。这种方法使用了系统机制,是最根本的解决方法,并使使用WindML的其它上层组件很方便的实现汉字显示。

2.自己开发点阵存储、点阵获取、点阵显示,改造WindML的双字节或单字节显示函数,使其能判断汉字码,一旦判断出汉字码,则使用自己开发的点阵获取、点阵显示等把汉字显示出来。该方法对点阵的操作更加灵活,适合非标准的点阵算法,或者当开发者已有成熟的点阵操作方法时,把该方法绑接到WindML上。

3.完全自己开发一套点阵存储、点阵获取、点阵显示、汉字显示函数,使用者使用特定的汉字显示函数把汉字显示出来。该方法具有最大的灵活性,甚至不理睬WindML的任何机制,直接在上层组件里实现,但这种方法使程序的中英文混合显示变得复杂,程序可移植性也比较差。

本文将就第一种显示方案和第一种汉字显示方案详细论述WindML的双字节编码机制,并利用该机制构建WindML汉字显示框架,并论述Zinc如何使用该框架。这些机制和思路其实是任何方案都需要考虑的,对绕开WindML的方案也具有指导和借鉴意义。

三. WindML的点阵参数

先来讨论一下WindML点阵的各种参数:

1.每个字模都有一个占据的空间,该空间对于点阵字库里的每个字是一样大的,所有字符点阵的大小都不应该超过该空间,如果超过,显示时超出部分将被截掉。相关参数有:

maxAdvance:最大宽度(横向)大小,点为单位。

maxAscent,maxDescent:maxAscent + maxDescend 是最大长度(即纵向)大小,两数的交界决定了一个baseline,maxAscent是baseline以上的长度,maxDescent是baseline以下的部分。Baseline对于定位具体字符点阵的打点起始位置非常重要,另外如果有一行来自同一个字符集的字符串,则这些字符的baseline是在一条线上的。maxAscent + maxDescent 有时被称为字符表高度height,注意要与下面所述的字符高度区别开来。

2.每个字符点阵也有一个范围大小,该大小与每个字符有关,该大小一般不会填满整个字模空间。相关参数有:

width:宽度。

height:高度。

ascent:点阵打点开始位置在baseline之上的偏移,如果是负数,则点阵在baseline之下开始打点。

ascent和height决定了点阵从字模的多少行开始打点,要打多少行。而列的打点起始位置,固定是0,即字模的最左边,所以只有width描述打点的宽度。

3. 字符横向和纵向都要有额外空间,以防止字符粘接重叠。相关参数有:

leading:行间距。

4. 对字符的一些变换选项,字符读取的标志等。相关参数有:

pixelSize:平均行、列大小。

weight:行、列加粗属性。

italic:斜体属性。

spacing:字符行间距属性。

charSet:字符集标志。

faceName:字符集名称。

familyName:字符集的家族名称。

scalable:字符放大缩小比例。

WindML显示字符时,以maxAscent + maxDescend作为字符高度(不加leading),以width作为字符宽度(不以maxAdvance,不判断spacing),根据字符ascent和字符height取出字符点阵数据,进行weight、italic、scalable等运算(很多运算需要用户开发),然后输出到屏幕。

四.WindML的点阵存储结构和操作方法

WindML双字节编码显示的参数和实现思路集中体现在点阵存储文件的结构上,该文件的框架如下(这些文件在WIND_BASE/target/src/ugl/fonts/bmf目录下):

UGL_LOCAL const unsigned char UGL_FAR_DATA page0Data[]= 
{  …
/* 0x0023 ('#') */
0,  /* page*/
0x23, /*index*/
0, /*size (MSB)*/
20, /*size (LSB)*/
8, /*width*/
16, /*height*/
14, /*ascent*/
0x00,0x00,0x00,0x00,0x44,0x44,0x44,0xfe,0x44,0x44,0x44,0xfe,0x44,0x44,0x44,0x00, /*data*/
/*0x0024 and other characters*/
  …
  …
  /*end*/
  0,0,0,0
 }/*西文扩展为双字节编码的点阵表*/
 /*上表解析:
 page + index 就是该字符的ASCII编码,不过扩为了双字节;
 size (MSB) + size (LSB) 是该字符的点阵信息大小,注意实际描述体的长度是2(2字节page,index)+ 该大小 + 1 (从0开始编大小,所以从1数要加1),而ascent之后的真正点阵数据的大小是 该大小减4 ;
 width + height 是该点阵资料的宽度和长度;
 ascent是点阵处在baseline以上的偏移位置,baseline的位置要看整个字符表描述结构的定义;
 data 是按行扫描得到的点阵资料,是列递增把行显示效果排成一个连续空间后,按字节来描述每位的打点状态;如果行宽不是8位的整数倍,不会把位补0去凑8位整数倍。
   字符点阵描述数据依次往下排列,直到以4个0标示结束。
 */

UGL_LOCAL const unsigned char UGL_FAR_DATA page1Data[]=
{ 0x81, /*page*/
0x40, /*index*/
0, /*size*/
36, /*size*/
16, /*width*/
16, /*height*/
14, /*ascent*/
0x00, 0x08, 0xff, 0xfc, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x10, 0x1f, 0xf8, 0x00, 0x10, 
0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x02, 0x20, 0x01, 0x40, 0x00, 0x80,
/*other characters*/
… …
/*end*/
0,0,0,0 
 }/*国标码对应的点阵表*/
 /*上表解析:
 数据含义与西文表类似,注意字码是双字节国标码
 */
UGL_LOCAL const unsigned char * const pageArray[] =
    {
     page0Data,
     page1Data,
     UGL_NULL
    };/*总的点阵资料表*/
 /*上表解析:
 把分类的点阵资料表汇集成一张表,总表以UGL_NULL结束,注意各个分表是以0,0,0,0结束;
 可以把汉字表按GB2312编码的page分类,构建多个汉字分表,然后把分表指针填入该表,当然也可以做成一个汉字大表,把指针放在该表,甚至也可以把中西文点阵做成中西文混合大表,然后把该表指针放在该数组里。
 */
const UGL_BMF_FONT_DESC uglBMFFont_Song_16 =
    {
    /* UGL_FONT_DESC structure */
{      { 16, 16},                                     /* pixelSize */
     {UGL_FONT_BOLD_OFF, UGL_FONT_BOLD_OFF }, /* weight */
     UGL_FONT_UPRIGHT,                               /* italic */
     UGL_FONT_PROPORTIONAL,                          /* spacing */
     UGL_FONT_UNICODE,                           /* char set */
     "Song 16x16 Dot",                         /* face name */
     "Song"                                      /* family name */
    },/*点阵名称等点阵属性表*/
    /* UGL_BMF_FONT_DESC structure */
 /*点阵表的属性和位置*/
       2,                     /* leading */
       14,                     /* maxAscent */
       2,                     /* maxDescent */
       14,                     /* maxAdvance */
     pageArray                /* glyph pages */
  
};/*点阵描述结构*/
/*上表解析:
 首先是定义属性表,然后是定义字模和间距,并定义总的点阵描述表指针。
*/

最后定义的const UGL_BMF_FONT_DESC uglBMFFont_Song_16 包含了该点阵的所有信息。只要能定位住该结构,则任何能在该点阵表内匹配出字码的字都可以显示出来。WindML选择不同的点阵就是选择不同的该结构去做点阵寻址,其实现的大体过程如下:

1.

WIND_BASE/target/src/ugl/config/uglBmfCfg.c文件描述了整个系统能使用的字符集,如:

extern const UGL_BMF_FONT_DESC uglBMFFont_Courier_12;
extern const uglBMFFont_Song_16; /*就是上面的例子*/
const UGL_BMF_FONT_DESC * uglBMFFontData[] =
    {
    &uglBMFFont_Courier_12,
    &uglBMFFont_Song_16, 
    NULL
    };
2.

通过如uglDriverFind (UGL_FONT_ENGINE_TYPE, 0, (UGL_UINT32 *)&fontDrvId);的调用定位点阵驱动,即控制对点阵表访问、打点等操作的函数;

通过如uglFontFindString(fontDrvId, "familyName=Song; pixelSize = 16", &systemFontDef);的调用定位点阵描述结构;

通过如fontSystem = uglFontCreate(fontDrvId, &systemFontDef));的调用绑接点阵和点阵驱动,并标识为fontSystem;

如此重复创建多个字符集的点阵标识。

3.

通过如uglFontSet(gc, fontSystem);的调用设置当前字符集;

通过如uglTextDrawW(gc, iX, iY, iLength, caString);的调用在iX, iY的位置显示caString里的字码。

可见,只要开发者根据上述的存储结构开发出对应的字符点阵,然后把点阵描述结构加入到uglBMFFontData,便可以使用系统的函数使用这些点阵了。在Dos/Windows、linux系统下有一些应用程序,可以把操作系统的点阵导出为C文件或数组,把这些导出的文件加以调整,就可以得到vxWorks系统支持的格式。

五.Zinc对汉字的支持

只要WindML的汉字支持做成功,则可以按如下方法使Zinc支持汉字:

WIND_BASE/target/src/zinc/generic/i_ugldsp.cpp 文件是WindML与Zinc的接口文件,在ZafScreenDisplay::ZafScreenDisplay 函数里使用上述的函数定义了Zinc要使用的字符集,把这些字符集改成汉字字符集,并且把Zinc配置成支持UNICODE的方式重新编译,则Zinc就自然支持汉字显示了。

六.注意事项和总结

在使用过程中,还要注意几个问题:

Tornado对汉字的编译,如果把汉字定义为如short ca[ ]={ '董' ,0x00} (把单个汉字定义在单引号),则编译生成的目标码是正序的国标码;如果定义为如”董”(双引号定义出的汉字字符串),则编译生成的目标码是反序的国标码。这样,就必须约定一种定义,以根据该约定产生的国标码来构建字符点阵表(需要改变表里面的字码顺序)。如果使用双引号定义汉字字符串,要注意该串数据是以一个字节0结束,使用uglTextDrawW要求是字为单位,所以,需要在该字符串结尾补一个0(”00”即可)。有些字库表的字码是UNICODE的编码,尤其是使用一些操作系统的点阵导出程序生成的字库表,UNICODE编码与国标码有一一对应关系,可以把这样的字库表转换过来或者在程序里适当位置把要显示的内容转为UNICODE再显示。

本文就嵌入式操作系统上使用汉字这一热门论题,论述了VxWorks上的图形实现方案、汉字开发方案,图形组件WindML对多字节码的支持特性,并在论述特性的同时,列举了宋体16点阵的框架,帮助汉字开发者理解点阵实现的细节;在论述WindML汉字操作函数之后,提出了在Zinc层实现汉字显示的方法和编程时的注意事项。这套方案已经成功的实现,并在上海大众的导航产品、南京电力的电力控制产品等项目上获得成功的应用。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭