路上撿來的取字模軟體

2019-07-21 09:02发布

本帖最后由 sammy902583 于 2018-7-28 15:51 编辑

缘起
因为坊间的取字模软件, 大多不能支持多国语言, 而且设置的选项也不合个人的需求, 所以想用Qt写一套可以完整支持世界所有字符的取字模软件, 并且可以支持TTF取模, 还有多种输出选项, 方便给各种单片机的应用程序用.
另外对于emWin方面, 因为原厂提供的FontCvt虽然功能强大, 但是对于要选择特定几个字符方面, 不符合中文的使用习惯(英文语系通常是一个范围, 但是中文则只是特定几个字元), 所以做出可以支持emWin字库的输出.
理念基本上就是把想要的字符取成bitmap的方式, 输出成各种字库.
可以有小字库和大字库两种输出种类:
  • 小字库: 输出选定的少数几个字符, 如果您的UI只有显示几个特定的字符, 不需要包含所有字符的数据, 可以用小字库, 同主程序编译在binary里面. 可以达到不用占太大功能又可以有想要的数据.
  • 大字库: 依据编码不同输出对应编码的所有字符, 这个会占据许多储存空间, 所以采用这种方式的话, 可能需要搭配外部储存来放字形数据, 不过大字库可以提供所有字符的图形数据, 显示各种文字数据.

与其他取字模软件不同的地方:
  • 基本上内定的编码方式是unicode, 可以指到unicode定义的各种文字. 实际在C code里面使用时也可以用 L”文字” 这种方式让compiler帮我们转成unicode方便使用.
  • 字符的宽度不是固定的, 依据TTF输出的数据, 输出的数据同样会带出各个字符的长宽.
  • 支持反锯齿, 每个Pixel可以是有灰度的, 不一定是只能由0或1而言, 对于彩 {MOD}液晶, 可以提供更好的显示效果.

设置字形可以提供选用的字形有3种:
  • TTF字形: 可以是Windows系统提供的字形, 或者是自定义的TTF.  自定义TTF不需要安装到Windows, 只要把网络上搜集的TTF字库案放在某个路径, 然后在设定选单里面设定这个路径, 这些路径就会和系统提供的字形一样, 出现在字形选单里面.
  • 倚天字形: 使用前同样要把倚天中文系统的字形放到某个目录, 然后在设定选单里面设定这个路径, 然后就可以使用了.
  • ST点阵字形: ST sample code里面的字形.

输出输出格式可以支持的输出格式基本上主要有3种:
  • 简单C code: 小字库输出, 自创的格式, 基本上就是C的字库. 后面会有详细的说明.
  • emWin C code: 小字库输出, 格式参考emWin说明. 需要搭配emWin使用, 虽然emWin有自己的取字模软件, 可是它的理念是选”范围”, 如果我们只要某几个字符, 就显得难用了, 因为你要针对每个字符找到内码, 然后翻页选到那个字符.
  • Binary字库: 大字库输出, 基于易木雨工作室的字库输出, 改变为也能支持各种自定义项目的字库. 后面会有详细的说明.

自定义项目扫描方式:
  • 由左而右, 由上而下: 首先以(横向)第0行为开头, 取第一个pixel, 第二个pixel …. 到最后一个, 然后换第二行...到最后一行
  • 由上而下,由左而右: 首先以(纵向)第0列为开头, 取第一个pixel, 第二个pixel …. 到最后一个, 然后换第二列...到最后一列
  • Nokia 5110扫描方式: 基本上以前一种扫描方式 ”由上而下,由左而右” 为基础, 以每8个pixel为单位, 由下而上取pixel, (第一组为Pixel 7,6,5,4,3,2,1,0; 第二组为15,14,13,12,11,10,9,8...以此类推), 这种方式采用了同Nokia 5110的取点方式, 所以输出的binary可以直接写入Nokia 5110的memory不需要任何转换. 只是这种取点方式必须限制高度是8的倍数, 如果原始字符不是8的倍数, 程序会自动补到8的倍数.

连续放置画素: 当取样的一行不满一个byte, 则下一行的的第一个pixel会接着放在上一行的同一个byte直到结束, 概念等同于bit stream. 如果不开启此功能, 下一行的第一个pixel则也会切换到下一个byte, 前一个byte后面就会有不会被使用到的数据, 可能会比较浪费储存空间.
输出字符的位图: C source专用选项, 输出的source会包含供参考的位图.
输出字符表: C source专用选项, 输出每个字符的信息供参考.
改变非ASCII字符到标号128之后: C source专用选项, 当要取样的字符不是英文字符, 程序会改变对应的内码到128之后, 这样把字符的内码改成byte为单位, 就可以剩下一些code size. 只是如此一来在指定显示字符的时候, 必须先查看对应出来的新内码供显示函式使用.
开启反锯齿: 开启之后可以提供有灰度的取样方式, 后面带有另外一个选项可以选择一个pixel要占多少bit, 基本上各种输出方式都可以支持反锯齿, 只是emWin不支持8 bit, 程序会降成4 bit. 基本上我觉得2 bit的显示效果就不错了, 如果您要求更好的显示效果可以用到4 bit, 8bit其实实际上根本不会用到那么多, 储存空间基本上都浪费掉了.
外观提供语言和风格的选择. 都是Qt提供的基本功能, 只是外观的表现, 或许您可以看成是演示的作用吧, 完全不会影响程序的主要功能.
输出格式说明简单C source采用的结构请参考Sample Code的Font.h.各个结构体/数据的对应如下struct Font →  struct CHARACTER_MAP    →  byte bit map资料
使用时, 以extern struct Font XXX的方式, 引入每个Font C source的struct Font来使用. (字符产生器, 会以C source的档名为依据取struct Font的名称, 所以每次重新产生C source时, 名称不会变更.)struct Font会指到character map, 当要找找某个字符时, 先到这个表格里面找对应的code, 里面会有这个字符的宽度, 高度信息, 还有link到最重要的bit map数据.bit map数据则是依照 扫描方式 / 取样bit数 / 是否连续放置画素, 而会有不同变化. 基本上每个Pixel是MSB → LSB排列.
emWin C source请参考emWin的说明, 基本上输出格式仿照emWin的格式.和简单C source一样, 程序会自动以C source的档名为依据Font的名称.输出的风格基本上同emWin的FontCvt, 但是加入个人认为不错的一些信息在里面.Binary字库Binary字库是简单C source的延伸, 承袭简单C source的的特性, 采用的结构请参考CharacterToolRespTest演示程序里面的mainwindow.h
Binary字库的资料Layout如下:FontRespFileHeaderChacacterInfoStruct[wCharacterCount]FontBitmap[0][...]FontBitmap[1][...]…
运用时可以先检查File Header取得字库的各项信息:
  • Signature: ASCII Signature
    • $BGGB: 表示是GB编码的字库
    • $BGB5: 表示是Big 5编码的字库
    • $BGEN: 表示是英文编码的字库
    • $BGJI: 表示是Jis编码的字库
  • cScanByte: 扫描方式
    • ‘H’ 表示 ‘由左而右, 由上而下’
    • ‘V’ 表示 ‘由上而下,由左而右’
    • ‘N’ 表示Nokia 5510扫描方式
  • cCompactEnable: ‘C’ 表示开启 ‘连续放置画素’
  • bBitCount: 输出的位数
  • wCharacterCount: 包含的字符数目
  • wMaxWidth / wMaxHeight: 最大的字符尺寸

接在FileHeader之后的是ChacacterInfoStruct array, 包含字库内每个字符的信息, 包含长度/宽度/还有最重要的bit map的offset, 和简单C source的struct CHARACTER_MAP地位相同.
使用时, 先去读ChacacterInfoStruct取得特定字符的信息, 因为这前面的资料都是固定的, 所以可以从字符的index得到确切的offset. 从ChacacterInfoStruct里面的数据可以得到该字符的长度/宽度/bitmap的offset, 而确切的数据大小可以从字符大小和扫描方式等数据推算得知. 而字符的bitmap同简单C source.
Binary字库各编码的字符排列方式基本上以易木雨工作室的排序为基础做了一些变更, 易木雨工作室的字库没有包含英文字符, 所以我把这部分加进去了, 放在字库最前面 0x60 个字符, 对应ASCII的 0x20 ~ 0x7F. 扣去前面的 0x60 , 排序方式就等同于易木雨工作室了.详细的过程可以参考CharacterToolRespTest的mainwindo.c函式void MainWindow::UpdatePreview().  我懒得多写了.
GBK第一个字节减去 0x81,则是正确的区位,每个区的大小要根据每个字所占用的字节×190(0x7f-0x40+0xff-0x80)即可。如果第二个字节小于 0x7f 则减去 0x40,如果第二个字节大于等于 0x80 则减去 0x41。
BIG5第一个字节减去 0xa1,则是正确的区位,每个区的大小要根据每个字所占用的字节×157(0x7f-0x40+0xff-0xa1)即可。如果第二个字节小于 0x7f 则减去 0x40,如果第二个字节大于等于 0xa1 则减去 0x62。
JIS第一个字节如果小于 0xA0 则减去 0x81,如果是大于等于 0xE0 小于 0xEF 则减去 0xCE,这个就可以得到正确的区码,每个区的大小要根据每个字所占用的字节×189(0xFD-0x40)即可。如果第二个字节小于 0xFC 则减去 0x40。这个SJIS 的定位就完成了。
主画面简叙


Screen.jpg


请运行主程序: CharacterTool.exe
先设置字元...输出等...
然后在右下可以输入要取样的字元, 输入完之后, 可以到左上选择要预览字元. (对于大字库, 这边的字元只是预览用而已.)
中间有一些控制, 可以微调字元的位置.

然后可以按运行产生字形档.


CharacterToolRespTest.exe 是大字库的测试程序

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。