UCGUI字体研究

UCGUI 字体研究

ucgui是一个被广泛使用的嵌入式界面库,其中内置的字体功能非常强大,你可以为你自己的单片机程序界面制作想要的字体。如何制作自己的字体呢, 可以仔细阅读这篇文章,了解一下 ucgui 字体方面的知识。

一、字体基础知识

计算机的字体,分为点阵字体和矢量字体,本文仅研究点阵字体。
实际上,点阵字体跟图片很像,都是一个个像素点绘出来的。比如中国的“中”字,我们在12x12像素中,对它进行绘制时,像素是这样的:

0000010000000000
0000010000000000
0000010000000000
0111111111000000
0100010001000000
0100010001000000
0100010001000000
0111111111000000
0100010001000000
0000010000000000
0000010000000000
0000010000000000

通过这个像素表,隐约能看到“中”字的样子。
转换成十六进制是一个这样的数组:

0x04,0x00
0x04,0x00
0x04,0x00
0x7f,0xc0
0x44,0x40
0x44,0x40
0x44,0x40
0x7f,0xc0
0x44,0x40
0x04,0x00
0x04,0x00
0x04,0x00

由于这样不太直观,不能一眼看出来这个字符的字形是什么。所以 ucgui 定义了 256 个宏,从 0x00~0xFF,用 “_” 代表为0的 bit, 用 “X” 代表为1的bit;比如 “_xxx__xx” = 01110011 = 0x73.
该宏定义放在 gui.h 大家可以查看一下:

#define	________	0x0
#define	_______X	0x1
#define	______X_	0x2
#define	______XX	0x3
#define	_____X__	0x4
#define	_____X_X	0x5
#define	_____XX_	0x6
#define	_____XXX	0x7
#define	____X___	0x8
#define	____X__X	0x9
#define	____X_X_	0xa
#define	____X_XX	0xb
#define	____XX__	0xc
#define	____XX_X	0xd
#define	____XXX_	0xe
#define	____XXXX	0xf
#define	___X____	0x10
#define	___X___X	0x11
#define	___X__X_	0x12
#define	___X__XX	0x13
#define	___X_X__	0x14
#define	___X_X_X	0x15
#define	___X_XX_	0x16
#define	___X_XXX	0x17
#define	___XX___	0x18
#define	___XX__X	0x19

(剩余部分略)

那么,“中”字就可以很直观的看出来:

/* char: 中   code:0xD6D0 */
static GUI_CONST_STORAGE unsigned char acD6D0[24] = { 
    _____X__,________,
    _____X__,________,
    _____X__,________,
    _XXXXXXX,XX______,
    _X___X__,_X______,
    _X___X__,_X______,
    _X___X__,_X______,
    _XXXXXXX,XX______,
    _X___X__,_X______,
    _____X__,________,
    _____X__,________,
    _____X__,________
};

二、GUI_FONT 的数据结构

GUI_FONT 是一个字体对外公布的接口。还有3个内部的数据结构,所以总的数据结构是4个:

1、GUI_FONT 整个字体的结构描述
2、GUI_FONT_PROP 字符信息块的结构
3、GUI_CHARINFO 字符映射的总表
4、字符的图元数据

他们在内存中的组织形式如下:

UCGUI FONT 内存描述

三、GB2312和GBK

通过一、二小节内容,我们基本认识了GUI FONT,那么,如何显示汉字呢?
其实,就是 GUI_FONT_PROP 的起始和结束字符的了,把他们设置为汉字的内码即可。
比如 “中”字,在GB2312里面是 D6D0 那么 GUI_FONT_PROP应该是这样:

static GUI_CONST_STORAGE GUI_FONT_PROP Prop1 = {
  0xD6D0, /*start :中*/
  0xD6D0, /*end   :中,  len=1*/
  &Cinfo[ 0 ],
  (void*)0
};

通常一个汉字占2个字节,一个英文占1个字节(ansi编码时,本文不讨论Unicode和UTF8)。
那么如何区分一段文字中的汉字和英文呢?
比如:中a国b人c
他的编码是:D6 D0 61 B9 FA 62 C8 CB 63
中 = D6 D0
a = 61
国 = B9 FA
b = 62
人 = C8 CB
c = 63
我们通过判断每一个字符,如果该字符>127那么就认为是2个byte组成的中文,否则就是1个byte的英文。
代码如下:

j:=0;
  i:=1;
  while (i<=len) do
  begin
    outStr:='';
    c:=Byte(s[i]);

    if c<128 then //英文
    begin
      outStr:=Char(c);
      //Memo2.Lines.Add(outStr);

      try
        Form1.StrToImg(outStr,w,h,cInfo[j]);
      except
        break;
      end;
      Inc(j);
    end else
    begin   //中文
      outStr:=Char(c)+s[i+1];
      //Memo2.Lines.Add(outStr);
      try
      Form1.StrToImg(outStr,w,h,cInfo[j]);
      except
        break;
      end;
      //cInfo[j].okwidth := w;   //中文下强制为w
      Inc(j);
      Inc(i);
    end;
    Inc(i);
    Form1.progress:=100*i div len;
    Application.ProcessMessages;
  end;
那么,GB2312和GBK又有什么关系呢?
可以这么理解,GB2312<=GBK。GBK包含了GB2312的所有字符。其他的都一样。

四、GB2312字符简介

GB 2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号。这种表示方式也称为区位码。
每个汉字及符号以两个字节来表示。第一个字节称为“高位字节”,第二个字节称为“低位字节”。
第一字节是区号,第二字节叫位号。
高位字节,使用了 0xA1~0xF7 即 01–87区,即:高位字节= 区号+0xA0
低位字节,使用了0xA1~0xFE 即 01–94区,即:低位字节=位号+0xA0

例如,“啊” = 0xB0A1
换算成区位:
区 = 0xB0 - 0xA0 = 16
位 = 0xA1 - 0xA0 = 1
即 16 区 1 位。

gb2312表全

五、如何生成ucgui字体

使用ucgui字体生成器,可以自动生成想要的字体:
ucgui字体生成器

六、ucgui抗锯齿字体

UCGUI是支持抗锯齿字体的,实际上就是把字体灰度化了,ucgui支持4级和16级灰度抗锯齿。
4级灰度叫 GUI_FONTTYPE_AA2_XXXX, 16级灰度叫 GUI_FONTTYPE_AA4_XXXX

选择4级或是16级灰度
点击 AA2(4级灰度)或者 AA4(16级灰度),再按开始转换,即可生成带灰度的字体。

七、把图片转换成字体

虽然 UCGUI 支持图片,如果把图片用来做一些小的 icon 的话,就不如当成字体使用灵活了,当成字体使用的话,可以随时修改 icon 的颜色,因为如果仅仅当成图片使用的话,一种颜色又得换一张图片,就有点太耗存储了。(当然也视情况而定,图片小而个数多时,把图片转字体更灵活;图片大而个数少时,还是当成图片使用;毕竟图片还有压缩模式可以节约ROM。)

在这里插入图片描述

八、以上工具均已开源,需要的可自行下载

[1] GB2312码表
https://download.csdn.net/download/coscka/11446816

[2] UCGUI GB2312字体生成器源码
https://download.csdn.net/download/coscka/11302846

  • 0
    点赞
  • 1
    评论
  • 5
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值