+ -
当前位置:首页 → 问答吧 → 关于字体的问题

关于字体的问题

时间:2009-09-23

来源:互联网

有一些关于字体的疑问:

1. 编码

UTF-8, UTF-16, UCS-2, UCS-4, GB2312, GBK, ISO10646, CP936...

2. 以上编码的操作, 如排序, 搜索

3. 字库文件如 bdf, pcf, spd, ttf, ttc, otf, spd, afm, pfa, pfb
对应的转换工具, 显示文件信息的工具, 字体编辑的工具

4. 知道文字的编码, 和字库文件, 怎么转换成点阵信息画到屏幕上.
转换时, 各种字库的效率如何..

头都大了..

作者: swordhui   发布时间: 2009-09-23

知道了3个工具:

1. bdf2pcf
2. pcf2bdf
3. otf2bdf, 这个可以转换ttf和otf. http://www.math.nmsu.edu/~mleisher/Software/otf2bdf/

知道了2个编辑工具
1. gbdfed
2. xmbdfed

功能完全相同, 只是一个依赖于gtk2, 一个依赖于openmotif

知道了:
UTF-8下, 所有的汉字都用3个字节表示... 简直是英语专用嘛

知道了:
微软现在用的是UTF-16.
为了用UTF-16, 字符串相关的API全部重定义了, 代价不可谓不大.

作者: swordhui   发布时间: 2009-09-23

.....楼主想要干什么?开发字体吗?

作者: pinkme005   发布时间: 2009-09-23

引用:
作者: swordhui
知道了3个工具:

1. bdf2pcf
2. pcf2bdf
3. otf2bdf, 这个可以转换ttf和otf. http://www.math.nmsu.edu/~mleisher/Software/otf2bdf/

知道了2个编辑工具
1. gbdfed
2. xmbdfed

功能完全相同, 只是一个依赖于gtk2, 一个依赖于openmotif

知道了:
UTF-8下, 所有的汉字都用3个字节表示... 简直是英语专用嘛

知道了:
微软现在用的是UTF-16.
为了用UTF-16, 字符串相关的API全部重定义了, 代价不可谓不大.
我以为 UTF-8 是用两个字节表示的?

作者: d00m3d   发布时间: 2009-09-23

引用:
作者: pinkme005
.....楼主想要干什么?开发字体吗?
不想开发字体, 想了解内部机制
这样出了问题容易定位
了解机制后, 可以保证部分代码能在嵌入式重用, 即使不用X.

作者: swordhui   发布时间: 2009-09-23

引用:
作者: d00m3d
我以为 UTF-8 是用两个字节表示的?
刚开始我也认为大部分常用汉字可以用2字节显示.. 但看了UTF-8的编码机制后, 彻底无语..

汉字在Unicode的位置是0x4e00开始的, 按xxxxyyyy yyzzzzzz的方式转成二进制, 则
代码:
xxxx=0100
yyyyyy=111000
zzzzzz=000000
转成UTF-8时, 要这样扩展:
代码:
1110xxxx 10yyyyyy 10zzzzzz
即0x4E00这个汉字, UTF-8的编码为:
代码:
11100100 10111000 10000000
即 E4 B8 80, 三个字节.
所有的汉字都如此

只有欧洲国家的有可能用2个字节表示.

由此看来UTF-8适合中英文混合表示的场景, 比如程序源码, HTML语言, 但不适合做汉字文章的存储, 这样会浪费1/3的存储空间... 这个浪费代价不小, 如果用压缩机制的话, 可以忽略.

如果想存储汉字文章, 最好用UTF-16, 几乎所有的常用字都2字节.

所以我们的Linux系统要既能处理UTF-8和UTF-16, 好在UTF-8太有个性了, 很容易自动识别一串编码到底是UTF-8还是UTF-16.

作者: swordhui   发布时间: 2009-09-23

知道了:

GB2312: 大陆最基本的编码体系, 支持英文, 常用汉字, 部分欧洲语系.
GBK: 兼容GB2312, 加入了大量生僻汉字, 加入了繁体字和日文/韩文用汉字.
GB18030: 兼容GBK, 又加入了蒙古文, 维吾尔文, 藏语等少数民族语言.....

GB18030比起unicode还是差很多, 毕竟世界上还有很多其他民族.

对我们来说, 电脑需要支持3种编码: GB18030, UTF-8, UTF-16.

GB18030的优势是: 专为汉语设计, 兼容ASCII, 在程序代码, HTML表示, 中文文章保存等都能达到最优性能. 但是.... 有很多中国外的语言不被支持.

GB18030应该逐渐用UTF-16/UTF-8替代.

你的Linux系统, Locale怎么设置?

我们真的需要UTF-16/UTF-8吗?

作者: swordhui   发布时间: 2009-09-23

知道了:
BIG5的设计比较失败..
有"许盖功"问题
还有一个鸡肋的设计: 自造字区, 这在编码设计上来说, 是完全错误的, 因为有岐义性.
比GB2312好的地方只有汉字多
比GB18030就不如了

作者: swordhui   发布时间: 2009-09-23

基本弄清楚了UTF-8/UTF-16之间的变换.

新的问题:
GB18030 和 UTF-16之间怎么转换呢? 有规律吗? 还是通过查表?

作者: swordhui   发布时间: 2009-09-23

再聊聊字库的问题.

字库应该支持一种或多种编码, 如ISO 8859-1, 8859-2, Unicode, GB18030等, 目前貌似所有的字库都只支持Unicode, 其他编码先转为unicode, 再访问字库.

字库的类型:
(1) bitmap固定宽度类型, 最早期的格式. 访问很简单, 读出位图信息画到屏幕就OK. 效率最高
(2) bitmap可变字符宽度类型, 字符宽度可以变的, 需要一张表, 表示每个字符的宽度.
(3) Adobe Type1 PostScript, 非点阵, 通过数学公式描述文字. 效率?!
(4) True Type, 是苹果和微软联合开发的, 对抗Type1. (他们居然也有合作的时候...) 怎么转为点阵? 效率?
(5) OpenType.. 这次是微软和Adobe合作... 目前最流行的方式.
(6) Speedo?
(7) CleanType.. 微软专门为液晶显示器优化的字体渲染方法

作者: swordhui   发布时间: 2009-09-23

引用:
作者: swordhui
知道了:
BIG5的设计比较失败..
有"许盖功"问题
还有一个鸡肋的设计: 自造字区, 这在编码设计上来说, 是完全错误的, 因为有岐义性.
比GB2312好的地方只有汉字多
比GB18030就不如了
是"许功盖"还是"许盖功"?

好像叫"许功盖"?

作者: d00m3d   发布时间: 2009-09-23

呵呵,楼主听说过黑箱么。
偶自知愚笨,当准备接受新信息时,自不敢强求,采蚕食策略,分而治之,逻辑上分,层次上分……
必要时,使用黑箱原则。

您说了那么多,真正和字体有关的到不多,和字符编码到较上劲。

其实,现在选编码,中文用户,应当在 UTF-8 GB18030 中选:
都是 UNICODE 字符集具体编码实现,
覆盖字符完全,
对正则表达式,都可以认为是随机乱序排列生成。

UTF-8 是针对当前 *nix-like 系统设计的,便于国际化,大势所趋,缺点是一个中文字符至少3字节,貌似部首排序,不排除将来有更合适中文的编码替代者。
GB18030 设计之初即是以中文为主,一个中文字符绝大部分2字节,貌似音序排列,但不利于国际化。

一个人一辈子能产生多少字节,采用压缩算法则几乎可忽略差异,所以,个人用户随意选择即可。
商业用户也许会考虑多些其它非技术因素。
对开发者,UTF-8 更是适用于绝大部分情况。

个人观点,最好不要刻意人为影响中文字体,如果可能字体应尽量回归传统,至少要繁体(正体)、简体并用,由时间决定存废。

作者: 聚焦深空   发布时间: 2009-09-24

引用:
作者: d00m3d
是"许功盖"还是"许盖功"?

好像叫"许功盖"?
"许功盖" 酱更符合平仄律

老兄来自台湾? 记得你曾说过"酱紫"

作者: swordhui   发布时间: 2009-09-24

引用:
作者: 聚焦深空
您说了那么多,真正和字体有关的到不多,和字符编码到较上劲。
主体叫"关于字体的问题", 确实有点小, 应该叫文字系统.


引用:
作者: 聚焦深空
其实,现在选编码,中文用户,应当在 UTF-8 GB18030 中选:
都是 UNICODE 字符集具体编码实现
我个人认为, 从现在开始应该逐步用UTF编码代替GB编码. 这个越早开始越好.
用简体或繁体到不重要.

麻烦的是磁盘中以中文命名的文件, 需要用一个工具搜索并替换成UTF-8, 以后就可以高枕无忧了.

GB编码的文档, 再存储时应该默认选UTF-16或UTF-8, 根据汉字和英文字母的比例决定.(编辑器应该可以根据比例自动选择)

作者: swordhui   发布时间: 2009-09-24

引用:
作者: swordhui
"许功盖" 酱更符合平仄律

老兄来自台湾? 记得你曾说过"酱紫"
非也,"酱紫"是台湾语吗?我还是几年前来 sir 的时候学的 :)

作者: d00m3d   发布时间: 2009-09-24

知道了:
X系统对字库文件, 采用了搜索和注册机制.
X启动时对知道目录进行搜索, 根据fonts.dir, fonts.scale 将字库注册到系统中, 包括字库支持的编码体系, 大小, 名称等等, 并分配一个长长的字体名. 长长的字体名可以通过fonts.alias变成短短的字体名...

示例1: 用X绘制GB2312编码的混合文字. (系统中必须有zh_CN.GB2312的locale, 参见LFS中GLIBC的编译安装)


代码:
// Written by Ch. Tronche (http://tronche.lri.fr:8000/)
// Copyright by the author. This is unmaintained, no-warranty free software.
// Please use freely. It is appreciated (but by no means mandatory) to
// acknowledge the author's contribution. Thank you.
// Started on Thu Jun 26 23:29:03 1997

//
// Xlib tutorial: 2nd program
// Make a window appear on the screen and draw a line inside.
// If you don't understand this program, go to
// http://tronche.lri.fr:8000/gui/x/xli...m-anatomy.html
//

// Modified by Zhang Lihui <[email protected]>, for GB2312 text drawing.

#include <X11/Xlib.h> // Every Xlib program must include this
#include <assert.h> // I include this to test return values the lazy way
#include <unistd.h> // So we got the profile for 10 seconds
#include <string.h>
#include <stdio.h>
#include <locale.h>

#define NIL (0) // A name for the void pointer

const char* g_csMsg="abc测试1245";

//font set, cover ASCII and GB2312.
const char* g_csFontName="-misc-fixed-*-*-*-*-15-*-*-*-*-*-*-*,\
 -*-fangsong ti-*-*-*-*-16-*-*-*-*-*-gb2312.1980-*";

main(int argc, char**argv)
{
 XFontStruct *pFontStruct;
 XFontSet fontSet;
 char **plistMissingChars=NULL;
 int n_listMissingChars=0;
 char *defreturn=NULL;

 if ( setlocale (LC_ALL,"zh_CN.GB2312") == NULL ) {
 (void) fprintf (stderr, "%s: cannot set locale.n",
 argv[0] );
 }

 // Open the display
 Display *dpy = XOpenDisplay(NIL);
 assert(dpy);

 // Get some colors
 int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
 int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));

 // Create the window
 Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
 200, 100, 0, blackColor, whiteColor);

 // We want to get MapNotify events
 XSelectInput(dpy, w, StructureNotifyMask);

 // "Map" the window (that is, make it appear on the screen)
 XMapWindow(dpy, w);

 //Create Font Set.
 fontSet=XCreateFontSet(dpy, g_csFontName, &plistMissingChars,
 &n_listMissingChars,
 &defreturn);

 if(fontSet==NULL)
 {
 printf("[Error] Create font set failed.\n");
 }
 else
 {
 if(n_listMissingChars!=0)
 printf("[Error] missing chars=%d\n", n_listMissingChars);
 else
 printf("Font set create OK\n");
 }

 // Create a "Graphics Context"
 GC gc = XCreateGC(dpy, w, 0, NIL);

 // Tell the GC we draw using the white color
 XSetForeground(dpy, gc, blackColor);

 // Wait for the MapNotify event
 for(;;) {
 XEvent e;
 XNextEvent(dpy, &e);
 if (e.type == MapNotify)
 break;
 }

 // Draw the line
 XDrawLine(dpy, w, gc, 10, 60, 180, 20);

 // Draw GB2312 message.
 XmbDrawString(dpy, w, fontSet, gc, 10, 20, g_csMsg,
 strlen(g_csMsg));


 // Send the "DrawLine" request to the server
 XFlush(dpy);

 // Wait for 10 seconds
 sleep(10);

}
Makefile如下:

代码:
all: prog2
 @echo "Done."

prog2: prog-2.cc
 g++ -pipe -o $@ $^ -lX11

clean:
 rm prog2


测试对Unicode的支持.
先定义一个Unicode串.

代码:
//Unicode, "一丁12fgh"
const wchar_t g_csUniMsg[]={0x4e00, 0x4e01, 0x0031, 0x0032, 0x0066, 0x0067, 0x0068};
将上面画串的函数后加入:

代码:
 // Draw Unicode message.
 XwcDrawString(dpy, w, fontSet, gc, 10, 40, g_csUniMsg,
 sizeof(g_csUniMsg)/sizeof(wchar_t));
屏幕上会出现"一丁12fgh".
使用GB18030更好些, 因为GB18030包含所有的Unicode汉字.


我们再测试一下utf8字串的绘制.
首先定义一个utf8字串.

代码:
//utf-8 message. "01一丁fg"
const char g_csUtf8Msg[]={0x30, 0x31, 0xe4, 0xb8, 0x80, 0xe4, 0xb8, 0x81, 0x66, 0x67};
然后改变程序的Locale, 为"zh_CN.utf8", 这个名字很奇怪.. 直接叫utf8好了, 干嘛还加zh_CN? 和中文完全无关嘛

代码:
 if ( setlocale (LC_ALL,"zh_CN.utf8") == NULL ) {
 (void) fprintf (stderr, "%s: cannot set locale.n",
 argv[0] );
 }

然后绘制字符串

代码:
// Draw utf8 message.
 XmbDrawString(dpy, w, fontSet, gc, 10, 20, g_csUtf8Msg,
 sizeof(g_csUtf8Msg));
屏幕上出现"12一丁fg".

如果想创建一个包含所有编码区间的超级字符集, 可以考虑安装unifont, 然后用下面语句:

代码:
fontset = XCreateFontSet (dpy, "-*-*-*-*-*-*-16-*-*-*-*-*-*-*",
 &missing_charsets, &num_missing_charsets,
 &default_string);
大多数程序使用GTK+Pango, 或QT4, 有空继续.

作者: swordhui   发布时间: 2009-09-24

swordhui 兄是从哪这么快学会了这么多东西的?
能否把源处亮出来给大家共享一下?

作者: Vamperor   发布时间: 2009-09-24

引用:
作者: Vamperor
swordhui 兄是从哪这么快学会了这么多东西的?
能否把源处亮出来给大家共享一下?
呵呵, 最好的源是google.

用好的关键字搜索, 事半功倍

Wiki也是另外一个不错的源.

作者: swordhui   发布时间: 2009-09-24