Tchaikov’s Journal

June 27, 2006

X 的字体和渲染

Filed under: GNU/Linux

对于 GNU/Linux 的中文用户来说,X 的字体设置是一个恒久的话题。似乎永远都谈不厌,说不完。为了备忘,在这里再做个简单的综述。

* X modules

X 为了渲染各种字体以 module 的形式提供了多个后端(backend),其中 freetype 和 xtt 能够处理 TrueType 字体:

  • freetype - 支持 TrueType (ttf, ttc), Type1 (pfa, pfb), CID (cid), CFF, OpenType, bitmap (bdf, pcf, snf), Windows (FNT), PFR, and Type42 fonts
  • xtt - 支持 True Type (ttf, ttc) fonts (conflicts with freetype)
xtt,即 X-TT (X-TrueType)。由于它针对 CJKV 的 TrueType 字体显示专门提供了设置和优化的选项(TTCap),因而它为广大中文用户所熟知。X-TT 基于 FreeType 1 开发。但是随着新的 FreeType 2 (libfreetype-xtt2)的发展,xtt 逐渐走到了它历史的尽头。X-TT 最后由 After X-TT 项目维护,在 2004年4月停止了开发。并于 X.Org X11R6.8 中退役,将从 XFree86 中消失。取而代之的是 FreeType 后端(即 libfreetype-xtt2,曾被称为 xfsft)。从它的名字,我们可以看出,它基于 freetype,又有 X-TT 的血脉。没错,新的 FreeType 吸收了 After X-TT 项目(该项目是 X-TT 最后的维护者)的改进,集成了 FreeType2 提供的存取、渲染各种字体的能力。 FreeType 在 X 里就是上面列出的 freetype 模块。它有种种好处,如今一般用户在配置 X server 时都会用新的 freetype module,而非 xtt。

但是 X 的字体技术没有就此停滞不前,X 核心协议中字体配置的缺乏灵活性,加上难看的 XLFD,催生了 Xft。

* Xft

Xft 最早出现在 XFree86 4.0,它的作者是 Keith Packard同学,其目的是更好的管理和渲染字体。从 XFree 4.02 开始,XFree86/Xft 开始提供对字型反锯齿显示的支持。新的版本是 Xft2,下面的说明都是基于 Xft2 的。Xft2 和它的前辈 Xft 最大的区别就是后者的设置由 Xftconfig 所控制,前者的设置则由 fontconfig 库全权负责。fontconfig 使用的 XML 格式的配置和 Xftconfig 相比大大简化了设置的难度。为了从核心的字体渲染平滑过渡到 X Render extension (后文会提到) 渲染,Xft 可以既可以核心字体,也可以用 FreeType 和 Render extension 的黄金组合。


通过 Xft,客户端的 X 程序能够使用新的 X render extension 和 freetype2 来渲染字体,字体的定位、命名和替换规则由 Fontconfig 负责。用户可以根据自己的喜好和口味自行设置 fontconfig。这里需要提醒一下,是使用 X 核心渲染还是 Xft 的渲染方式,是由 X 程序决定的。

既然你配置好了 Xrender 和 freetype,那么试试吧,这里我打开了 Xft 的调试信息

$ export XFT_DEBUG=2
$ xterm -fa charter -fs 14

* XRender

说到 Xft 就不得不说一下 X Render。RENDER 是 X 的一个 extension,这个 extension 又是 Keith 同学(我为什么要说“又”?)的作品。X Render 能通过硬件实现的 compositing 操作,提供反锯齿和 alpha 混合(半透明)的绘图功能。你可以用 xpdyinfo 看看你的 X server 是否使用了它,或者也可以检查一下 /var/log/Xorg.0.log。除了画三角形和椭圆之外,X clients 也可以使用 X Render 提供的绘图功能绘制反锯齿的字型。最近的 Qt 提供支持,让 Xft 能使用 FreeType2 和 XRender 绘制反锯齿字型。可以说,FreeType2 负责告诉 X client,字型的形状(glyphs),而 XRender 把这些形状绘制在 X server 上,当然,是有反锯齿和半透明效果的。如果没有 X Render 可用,Xft 就只好使用老式的核心的字体绘制方式了。

* Cairo

Cairo 是一个相当有野心的项目。它企图把二维的图像输出到各种对象,从 X11、win32、或者内存中的图像缓冲区。写入PostScript、PDF和图像文件(PNG)的工作也有了初步的成果。Cairo 也不会放过硬件加速的机会,它能使用 glitz 和 X Render 进行渲染。

* Pango and QT

** Pango

既然 Cairo 和 Xft 提供了画字的手段,那字和段落的编排、布局呢?Pango 来也!Pango 能够使用多种后端,主要有三种搭配:

  • FreeType2+fontconfig +(Cairo|Xft)
  • Windows 的字体+(Cairo|Win32 API)
  •  MacOS X 字体 + Cairo。
作为 GTK+2.x 的处理文字和字体的核心组件,Pango 对国际化提供着良好的支持。这就意味着它能够处理从右向左书写的希伯莱文字,也能够处理从左向右书写的法文。插一句,其实 Pango 就是“盘古”的音译呢!

** QT
一图胜千文,直接看

* Xfs
在早期 Red Hat 发行版缺省的 X 配置文件中常常可以看到关于 xfs 的设置。xfs (X Font Server)是一个运行在后台的字体服务器。如果您设置的 X 服务器不想(或者是没有能力)操心字体配置和处理的烦心事,就可以单设置一个 FontPath(事实上是一个端口),让 xfs 代劳。在更早的时候 XFree86 3.x 的时代[8],字体服务器甚至是让 X 使用 TrueType 字体的唯一途径,那时的 XFree86 3.x 还没有内建的 TrueType 支持。最常见的配置就像这样:
FontPath   “unix/:7100″
在 这里,unix 是指的 unix domain,即让 X server 通过本地的 7100 端口连接 xfs 服务器。xfs 服务器会对 X server 请求的字体信息作出相应。如果让 X server 用 inet domain 连 Xfs 的话,就是 tcp/fs.x.org:7100, tcp/
18.30.0.212:7101/all 了。

除了文中提到的链接之外,这里也说得相当不错,还有力气的话,建议你看看。

June 12, 2006

Emacs snapshot-unicode-2

Filed under: Emacs

在水木上听说 GNU Emacs emacs-unicode-2 竟然宣布支持 XFT。吃了一惊,赶忙下了一个,

cvs -z3 -d:pserver:anonymous@ftp.tsinghua.edu.cn/cvsroot co -r emacs-unicode-2 -d emacs \
      cvs.savannah.gnu.org/emacs/emacs
./configure --with-xft --with-freetype --with-gtk --with-x --enable-font-backend --prefix=/opt/emacs23
make bootstrap && make

哼哧哼哧编译了半天。还好没有白等,效果相当不错。但是没有 Emacs python-modesession,从 sf 下了 cp 到 share/emacs/site-lisp/ 顺利得无法相信。一切如常!

唯一有些不如意的是,LC_CTYPE还是要设置成 zh_CN.gbk 才能呼出 SCIM。



Screenshot-emacs@glPlot.py.png, originally uploaded by tchaikov.

June 5, 2006

Python, OpenGL 和 Profile

Filed under: Python

平台,平台,演示平台。虽然有一万分的不愿意,我还是耐着性子研究如何画界面。而磁敏曲线的界面天生就没有吸引力。先不管这么多吧,从头开始。为了获得和平台图形界面相同的感官效果,我们就用 WxWidget。为了让开发简单快捷,跨平台,语言就用 Python。哈哈!
WxWidget 画界面应该没有问题。但是我们这里有两个难关。

  • 动态的磁敏波形
  • 以后可能加入的同步视频演示窗口
对 wxWidget 比较熟悉的朋友应该立即能找到对应的模块,前者是 wx.lib.plot 或者重量级的 matplotlib。后者则是 wx.media 或者 pymedia。接下来把它们简单比较一下。 先说 matplotlib。不久之前,我对 matplotlib 做过测试,显示效果虽然不错,但是 FPS 很低。用 GTK+ 前端的话,只有 40fps,而且 CPU 占用率达到了 100%。如果要平滑地显示磁敏曲线,这样的性能明显是不可接受的。wx.lib.plot 是 wxPython 的嫡系正宗,但是很久没有更新了,而且它的绘图方式应该是用操作系统的 GDI,想来速度不会很好。回头再测试一下。 在搜索相关资料的时候,我发现有人 和我有相同的问题,不过时间已经是 6 年之前了。thread 的主人原来的程序是使用 Tkinter 的,他希望能在1/10秒里画1000条线,但是在他的P166机器上速度太慢了。thread 里有人做了实验,用 Windows NT, P200, 64M 的机器,使 wxPython 跑出了 0.18s 画 1000 条线的成绩。这位仁兄同时还建议试试 OpenGL 和双缓存的方法,以提高速度。还是在这个帖子里。也有人建议楼主用 Canvas.coords 来移动线条,然后再 redraw 这些线。值得注意的是 Guido 叔叔也参与了讨论,他的方法是绕过 Python 的 Tkinter 绑定,直接用 Tcl 的语法调用 <widget>.tk.call(…), Guido 发现这样能让速度提升一个层次。也有人用 OpenGL 和 NumPy获得了每帧几百条线的成绩,但是不知道他每秒能有多少帧? 看完这个 thread,我立即试了一下 PyOpenGL。glut* 函数相当好用,只要在 glutIdleFunc 注册的函数里更新坐标就可以画出动画。没有几分钟我就凑出来个蠕动的 sine 曲线。但是问题在于 sine 曲线运动得太快了,刷新频率太高,同时 CPU 的使用率也是满档。然后把更新坐标的函数改成注册到 glutTimerFunc,就好了大半。接下来就是每秒多少帧和帧间移动多少的权衡了。总体效果还过得去,CPU占用率也很小。 wx.media 自己是无法完成解码的工作的。它借助平台相关的后端进行不同格式媒体文件的解读。Windows 上,后端可以用 wxMEDIABACKEND_DIRECTSHOW,GNU/Linux 上用 wxMEDIABACKEND_GSTREAMER。pymedia 也是一个前端,它自己无法播放视频文件。它借助 pygame 来做这件麻烦事。目前,Debian 还没有收录 pymedia,所以现在先考虑 wx.media。

June 4, 2006

Python 的点点滴滴 —— new style class 的 property

Filed under: Python

Python 2.2 引入了 new style class,让撰写 OO 的 class 更为简洁,有的方面可以用上更 pythonic 的解决方案。其中一个重要的改进就是增加了 properties 的设计。既然可以直接访问成员变量,为什么要这些累赘的 getter 和 setter 呢?
要让访问对象的属性操作有更多的灵活性,直接访问对象的数据成员的办法明显有些襟。因此必须通过 getter 和 setter 来包装。因为有的属性无法与对象的成员变量直接对应。它(这类属性)有可能就是需要临时计算得到。比如一个有序队列的最大值。
第一次看到 property 是在 Delphi (Object Pascal)里。语法和 Python 惊人的相似:

 Property Top    : Longint Index 1 read GetCoord write SetCoord;

Python 里则是

top = property(fget=get_coord, fset=set_coord)

但是要注意的是,new style class 必须继承自 object,否则,当我们高高兴兴地使用 foo.top = 1 的时候,get_coord 是不会被调用的,虽然 Python 一声不吭地接受了你的 property 声明(它的确没有 warning,或者类似 property statement is only available in new style class 的错误警告)。但是,foo.top = 1,仅仅是执行了 foo.__dict__[’top’] = 1 的操作,不多也不少。

June 3, 2006

gcov 和 gprof

Filed under: GNU/Linux, Programming, C++

gcov 和 gprof 都是 GNU 开发的程序。它们为程序员和测试工程师提供了很好的工具。
前者能够做 coverage 评测,这对 QA 来说会有很大的帮助。后者则能提供一个程序运行的 profile,帮助程序员快速找到程序的 hotspot。以前在看 CS APP 的时候曾用过 gprof。但是 gcov 是今天才知道的。原来像英特尔这样的大公司使用 GNU 工具的频度还是很高的。

June 1, 2006

Python 的点点滴滴 — dict 和 %

Filed under: Python

这里看来的。print 竟然可以这样玩!

dict = {\"name\": \"Guido\"}
print \"Hello %(name)s!\" % dict

可以注意到, %(name)s 中,name 是 dict 的 key,而 s 则是 format string。
读过 OSCON 2005 Effective Python Programming slides 之后,我看到刚才链接里的文章把 Python 的 Template 模式玩到了新的高度,令人咋舌不已。感叹道:
Python,你真是太邪门了!

Get free blog up and running in minutes with Blogsome
Theme designed by Jay of onefinejay.com