说说嵌入式显示汉字

说说嵌入式显示汉字

矢量字库 点阵字库 GB18030 GBK BIG5 CodePage

2021.05.09 屋脊雀工作室 (草稿)


前言

LCD是嵌入式常见设备,如何在LCD上显示汉字和英文?

矢量字体和点阵字体有何不同?

同一个字符为何有多种编码?GB2312、GB18030指什么?他们之间有关系吗?

嵌入式设备如何支持多国语言?

从哪里获取字库?需要付费吗?

以上问题,本文一一道来!


如何在LCD上显示字符

在LCD上如何显示字符呢?这里我们讨论的是逻辑问题,不是LCD控制器驱动。

首先,我们要对LCD有一个概念:LCD也就是一个点一个点组成的一片点而已。本质上和1个LED一样。

1个单色LED,能显示亮灭。

将很对LED排成一行,就可以实现流水灯。

将多行LED组成一片,是啥?是LED点阵。

多块点阵,就能组成图文屏。

如果是三色LED组成的图文屏,就能显示视频动画。

无论是COG LCD,OLED LCD,还是TFT LCD,实际上都是一个点一个点组成的矩阵,和LED组成的图文屏一样。

当然,制造工艺不一样,控制显示内容技术也不一样,我们不讨论制造技术,控制技术后续会有单独课程讨论

显然,要在图文屏上显示字符,只需将对应的LED点点亮。

不同的字符应该点亮那些LED呢?

我们先逆向想,下图LED点阵上显示的汉字,如何将位置信息保存到代码中,以便下次使用?

这是一个16x16的LED点阵。

每个LED的状态仅仅是亮或灭,那么就可以使用1个bit表示其状态,1表示亮,0表示灭。

1个byte,8个bit,两个byte就可以表示一行LED的状态。

上图这个德字第一行就可以这样表示:0001 0000 0100 0000;也就是0x10,0x40;

按照此方法取得“德”字得完整显示信息:

0001 0000 0100 0000 0x10 0x40

0001 0000 0100 0000 0x10 0x40

0010 1111 1111 1110 0x2f 0xfe

0100 0000 0100 0000 0x40 0x40

1001 0111 1111 1100 0x97 0xfc

0001 0100 1010 0100 0x14 0xa4

0010 0100 1010 0100 0x24 0xa4

0110 0111 1111 1100 0x67 0xfc

1010 0000 0000 0000 0xa0 0x00

0010 1111 1111 1110 0x2f 0xfe

0010 0000 0100 0000 0x20 0x40

0010 0000 0010 0100 0x20 0x24

0010 0101 0010 0010 0x25 0x22

0010 0101 0000 1010 0x25 0x05

0010 1001 0000 1000 0x29 0x08

0010 0000 1111 1000 0x20 0xf8

 

用1个数组保存到� �码中,如下:

de_dot[32]={

0x10, 0x40, 0x10, 0x40,0x2f, 0xfe, 0x40, 0x40,

0x97, 0xfc, 0x14, 0xa4,0x24, 0xa4,0x67, 0xfc,

0xa0, 0x00,0x2f, 0xfe,0x20, 0x40,0x20, 0x24,

0x25, 0x22, 0x25, 0x05, 0x29, 0x08, 0x20, 0xf8};

得到了这个数组,在代码中按照取模的方式将其还原到LED点阵上,就能显示德字。

玩过8段数码管的朋友应该很熟悉,为了在数码管上显示数字,我们会在代码中定义0~9数字的显示掩码(数码管每个段亮灭的信息)。

点阵上显示汉字,无非就是LED更多了。

总结

要在LCD上显示字符,需要先知道如何描绘字符的信息,按照取模方式,将这写信息还原到LCD上,就能描绘出字符。


点阵字库

那什么是点阵字库呢?

上一节中得到的“德”字的描绘信息数组就是点阵字库

这个德字描绘出的效果,就是点阵字体描绘信息保存的形式,就是点阵字库

点阵字体也叫位图字体,其中每个字形都以一组二维像素信息表示。这种文字显示方式于较早前的电脑系统(例如未有图形接口时的 DOS 操作系统)被普遍采用。由于位图的缘故,点阵字体很难进行缩放,特定的点阵字体只能清晰地显示在相应的字号下,否则文字只被强行放大而失真字形,产生成马赛克式的锯齿边缘。但对于字号 8-14px 的尺寸较小的汉字字体(即现今操作系统大多采用的默认字号)现今亦仍然被使用于荧幕显示上,能够提供更高的显示效果;不过现今该种点阵字体主要只作为“辅助”的部分,当使用者设定的字体尺寸并没有拥有位图像时,字体便会以向量图象方式显示;而当打印时,印有字体无论大小亦会使用向量字型打印。

点阵字库有多种形式:

  1. 直接将信息用数组保存到代码中。(显示的内容较少时通常会这样做)
  2. 将点阵信息描绘到一张bmp图片,使用时根据信息文件(FNT)从图片中取信息。(很多游戏使用的就是这种贴图字体,也叫bmpfont)
  3. 将一堆点阵信息数组打包为1个bin文件,使用算法定位字符位置。(点阵较多,按照编码规范整合在一起)
  4. 按照电脑字体规范整合的字体。(比如windows的ttf字体,bdf字体)

特点

  1. 取模方式

    取模方式指的是单个bit位置信息组合成字节时使用的方式。

    前面我们对德字取位置信息时:使用横向取模,并且高位在前。此外还有很多不同的取模方式,常见的方式如下:

  2. 尺寸

    汉字通常有这些尺寸:12x12,16x16,24x24。在cog屏128*64像素的屏上,一般用12x12的汉字点阵,可以显示5行。

    ASC码的点阵通常和汉字高度一样,宽度是一半,比如,12x12的汉字配12x6的ASC码,16x16的汉字� �配16x8的ASC码。


矢量字体

矢量字体概念

矢量字体(Vector font)中每一个字形是通过数学曲线来描述的,它包含了字形边界上的关键点,连线的导数信息等,字体的渲染引擎通过读取这些数学矢量,然后进行一定的数学运算来进行渲染。这类字体的优点是字体实际尺寸可以任意缩放而不变形、变色。矢量字体主要包括 Type1 、 TrueType、OpenType等几类。

Freetype

FreeType库是一个完全免费(开源)的、高质量的且可移植的字体引擎,它提供统一的接口来访问多种字体格式文件,包括TrueType, OpenType, Type1, CID, CFF, Windows FON/FNT, X11 PCF等。

 

  1. 矢量字体使用Freetype进行渲染后,最后得到的也是bitmap,毕竟,LCD就是一个一个点组成的。
  2. 理论上矢量字体可以无限放大而不失真。
  3. 但是,矢量字体渲染为较小字号的字,某些字(笔画多)可能失真非常严重。

字符编码

字符编码是指一种映射规则,根据这个映射规则可以将某个字符映射成其他形式的数据以便在计算机中存储和传输。

计算机保存数据的最小单元是bit。8个bit组成1个Byte。

在计算机中,只有数值,1个byte的数值就是0~256。

那么计算机如何记录世界各种事务呢?比如字符?这就需要定义映射关系。

比如在计算机中保存1个0x41,它是一个值时,就是65;它是字符时,就是A;它是颜色时,就是。。。

 

在计算机中,所有的数据在存储和运算时都要使用二进制数表示(因为计算机用高电平低电平分别表示1和0),例如,像a、b、c、d这样的52个字母(包括大写)以及0、1等数字还有一些常用的符号(例如*、#、@等)在计算机中存储时也要使用二进制数来表示,而具体用哪些二进制数字表示哪个符号,当然每个人都可以约定自己的一套(这就叫编码),而大家如果要想互相通信而不造成混乱,那么大家就必须使用相同的编码规则,于是美国有关的标准化组织就出台了ASCII编码,统一规定了上述常用符号用哪些二进制数来表示

ASC码

ASCII ((American Standard Code for Information Interchange): 美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显� ��现代英语和其他西欧语言。它是最通用的信息交换标准,并等同于国际标准ISO/IEC 646。ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符 。

Codepage

欧美很多国家的语言在ASC码中没有定义,各个国家(或组织)就使用1个字节剩下的127个值映射他们需要的字符。

国家很多,定义很多,如何决定使用哪种映射呢?

IBM、微软等系统就增加了CodePage的概念:每种映射分配一个编号。这些系统的代码页编号是不完全一样的。

IBM定义的代码叫做OEM。微软定义的代码叫ANSI

  • 437 —最初的IBM PC代码页,实现了扩展ASCII字符集
  • 737 — 希腊语
  • 850 —“多语言(Latin-1)” (西欧语言)
  • 852 —“斯拉夫(Latin-2)” (中欧及东欧语言)
  • 855 — 西里尔(Cyril)字母
  • 857 — 土耳其语
  • 858 —带欧元符号的“多语言”
  • 860 — 葡萄牙语
  • 861 — 冰岛语
  • 863 — 法语加拿大英语
  • 865 — 北欧
  • 866 — 西里尔(Cyril)字母
  • 869 — 希腊语

代码页819实现了拉丁语(Latin-1)(ISO/IEC 8859-1),用于IBM AS/400小型机。

中日韩语言代码页

既是OEM代码页,也是Windows代码页。

  • 932 —日 文(shift_jis)
  • 936 —简体中文(GBK)
  • 949 —韩文
  • 950 —繁体中文(大五码)

ANSI代码页

  • 874 —泰文字母
  • 1250 —东欧拉丁字母
  • 1251 — 古斯拉夫语
  • 1252 —西欧拉丁字母ISO-8859-1.
  • 1253 — 希腊语
  • 1254 — 土耳其语
  • 1255 — 希伯来语
  • 1256 — 阿拉伯语
  • 1257 — 巴尔
  • 1258 — 越南
  • 1254 — 土耳其语

汉字编码

汉字字符数量很多,仅仅使用高位127个值不能表示。

因此国家标准组织定义了《信息交换用汉字编码字符集》。有三个版本:

GB2312编码:1981年5月1日发布的简体中文汉字编码国家标准。GB2312对汉字采用双字节编码,收录7445个图形字符,其中包括6763个汉字。

GBK编码:1995年12月发布的汉字编码国家标准,是对GB2312编码的扩充,对汉字采用双字节编码。GBK字符集共收录21003个汉字,包含国家标准GB13000-1中的全部中日韩汉字,和BIG5编码中的所有汉字。

GB18030编码:2000年3月17日发布的汉字编码国家标准,是对GBK编码的扩充,覆盖中文、日文、朝鲜语和中国少数民族文字,其中收录27484个汉字。GB18030字符集采用单字节、双字节和四字节三种方式对字符编码。兼容GBK和GB2312字符集。

GB18030很多码位都是空的,通常使用的GB18030字库,26000多个字符。最新的� �本是《GB 18030-2005.pdf》

 

汉字编码使用分区概念,如下面分区,其中的双字节二区就是符合GB2312标准的双字节区。

 

繁体汉字编码

Big5,又称为大五码五大码,是使用繁体中文(正体中文)社区中最常用的电脑汉字字符集标准,共收录13,060个汉字。

BIG5编码:台湾地区繁体中文标准字符集,采用双字节编码,共收录13053个中文字,1984年实施。

Big5码对应的汉字与编码可在台湾国立大学网站找到:

https://www.csie.ntu.edu.tw/~r92030/project/big5/

unicode编码

国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换。

汉字在Unicode中的编码范围可在下面网页查到:

https://www.qqxiuzi.cn/zh/hanzi-unicode-bianma.php

参考

编码发展历史 https://www.cnblogs.com/gavin-num1/p/5170247.html

Unicode、GB2312、GBK和GB18030中的汉字

http://www.fmddlmyy.cn/text24.html


如何获得字库

在介绍如何获得字库之前,先说明版权问题

  1. 版权说的是字体,也就是一个字符描绘出来的效果。一个字体的形成方式通常是矢量字体或者点阵字库。
  2. 使用工具将一种字体的矢量字库转换为点阵字库,他们仍然是同一种字体,那么版权是一样的,依然属于矢量字体拥有者。

获取矢量字体

在你的电脑中就有很多字体。

windows下的C:\Windows\Fonts下保存有你电脑安装的字体,这种字体通常是ttf标准。

这些字体一般都不是开源的,也就是不能免费商用到嵌入式设备上。

开源的字体有:

思源字体,可以免费商用。

文泉驿字体,也是开源免费商用,但是只能用于GPL授权的设备。跟linux一样的授权模式。

文泉驿有点阵字体

文泉驿的志愿者为开源用户准备了多种字体选择;这些字体既有手工优化、清晰锐利的点阵汉字,又有柔和圆润、无限放缩的矢量字体;既有适合普通中英文混版(网页浏览、文档 排版)的非等宽字体,还有适合在编程环境下(如控制台、程序编辑器等)中文英文对齐的等宽字体。请大家根据自己的需要和喜好来选择安装适当的文泉驿字体。

获取点阵字体

我们更关心的是如何获取点阵字体。

前面说过,点阵字体有很多存在方式,那么我们就有很多获取方式。

  1. 从很早之前的电脑汉卡上获取点阵字库。

    这种方式比较难找,在github上可以找到一些外文的点阵字库,汉字的没找到。

  2. 从DOS系统获取汉字点阵

    这种点阵我用过的有HZ1616,HZ1212。这种字体的版权不是很清楚属于谁。不过这种字库因为很早,所以基本都是GB2312规范的,不包含生僻字

    https://www.docin.com/p-313989274.html

    https://bbs.pku.edu.cn/v2/post-read.php?bid=1074&threadid=15267346

  3. 从电脑字体中找点阵字体

    电脑字体常见的是TTF规范,这个规范比代表它只有矢量字体,很多电脑字体中会包含矢量字体和点阵字体。点阵字体一般是小号字。小号字用矢量字体渲染,效果不好,所有某种字体通常会带小号的点阵字体

  4. 用取模工具取点阵信息

    如果使用的字符很少,可以用《zimo3》等工具取模。

  5. 用点阵生成工具批量生成

    比如易木雨软件工作室做的《字库制作软件.rar》,可以批量将矢量字库转为点阵字库。

  6. 从开源模块中找外文点阵

    比如tslib触摸库中就含有英文点阵

  7. 有一个叫高通的公司,卖点阵字库芯片。

    有一个较北京中易的公司,有一套很好的点阵字库。这套点阵字库由于性能好,流传广,工作经验丰富的工程师一般都接触过;不过大部分公司可能都没有获得授权

    还有其他很多做字体的公司也有点阵字库,比如方正。

  8. 自己用编辑工具一个一个画,然后用你的脑子将其转为数组

自己造字体

FontForge:https://fontforge.org/en-US/

FontForge is a free and open source font editor brought to you by a community of fellow type lovers. You can donate to support the project financially. Get involved. Anyone can help! You don't have to be a programmer. If you want to help but don't know where then join the developer list and introduce yourself.

这工具,能用来查看电脑字体,比如查看某些字体是否含有点阵字体,还可以将字体导出,还可以修改字体,能查看字体是否包含某些字。

当然,也能自己造字体,看好你额!


工程实践

经验记录

要不要用大字库?

GB2312规范的字库,1212尺寸的192K,1616尺寸的256K,2424尺寸的575K;

GB18030规范的字库,1212尺寸的683K,1616尺寸的749K。

如果用这些字库,一般cpu内部是放不下的,需要外挂Flash。

要不要上矢量字体

用FreeType进行矢量字体渲染,代码量有180K;

在RT1052平台,400M主频测试,矢量字库直接放到QSPI FLASH,取1个汉字字符,需要700us。

没优化前的FreeType,需要几十K RAM。

矢量字库是unicode排列的,GBK转unicode只能用表,1个GB18030转UNICODE的表,80K。

矢量字体一般都有10多M。

编码转换

不同编码规范转换只能查表,没有公司。很多模块都有编码转换表。

  • libiconv

https://directory.fsf.org/wiki/Libiconv

https://www.gnu.org/software/libiconv/

  • Fatfs

例如fatfs中的cc936.c,源码文件708K,有两个表:oem2uni、uni2oem

OEMCP=OEM CodePage

  • ZINT

zint实现的转换功能是将utf8编码流转换为utf16双字节编码,再转换为GBK编码。

查找方法使用轮询,太慢!!!

3张表其实是按照unicode编码排好序的,可以用二分查找。

zint的表齐全,已经包含GBK 4字节编码。

如需要GBK排序的表,可以将ZINT的表重新排序即可。

编码应用

  1. window默认的是ANSI(GBK)编码。所以,在代码中嵌入的字符串编译后得到的是GBK编码。

    比如char str[]="中国",得到的就是GBK编码的4个字节:0xd6 0xd0 0xb9 0xfa

  2. 电脑文件默认是ANSI(GBK),可以修改为utf-8。

  3. 网络通信大部分都是utf-8格式,比如MQTT通信。可计算转为unicode,查表转为GBK。

  4. 手机短信SMS传输的好像也是unicode编码。

参考:http://www.wujique.com/2020/05/10/%e5%8d%95%e7%89%87%e6%9c%ba%e6%ba%90%e7%a0%81%e4%b8%ad%e6%96%87%e5%a4%9a%e5%b9%b3%e5%8f%b0%e4%b9%b1%e7%a0%81%e9%97%ae%e9%a2%98/

汉字字符集编码查询

https://www.qqxiuzi.cn/bianma/zifuji.php

千千秀字,它的首页https://www.qqxiuzi.cn/daohang.htm,里面有更多功能。

比如查询GB18030编码范围:

https://www.qqxiuzi.cn/zh/hanzi-gb18030-bianma.php


有偿支持

字库

提供矢量字体转点阵字体PC工具支持,得到的点阵整体效果比易木雨的要好。

支持GB18030(不含四字节编码区域,因为思源矢量字库也没有四字节汉字)、大五码、多国语言(是否支持要看源字体是否包含)。

工具思路:用python调用freetype模块,将所有的GB18030编码字符从矢量字体中获取渲染为点阵,写入字库文件。

1个星期工作量,有时间你可以自己写,需要的知识点全在本文了。

技术咨询

有偿咨询:QQ 584024595

门票:一包芙蓉王。

讨论到具体问题解决方案时,协商定价。


图片连接