Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3129972
  • 博文数量: 117
  • 博客积分: 10003
  • 博客等级: 上将
  • 技术积分: 5405
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-23 09:34
文章分类

全部博文(117)

文章存档

2011年(1)

2010年(10)

2009年(69)

2008年(37)

分类: LINUX

2009-09-15 15:40:15

试析FreeBSD桌面系统中利用Fontconfig进行字体配置的运作原理(一)

杜比环绕声

概要:本文以KDE桌面环境为例,试析Fontconfig的运作机制


一、Fontconfig在桌面系统中的作用

KDE是类Unix系统中建立在X基础上的一个主流桌面环境,对用户来说,它提供了良好的图形界面和语言切换机制,用以满足来自不同国家、使用不同语言的用户的使用需求,这种机制简称“国际化”。主要包括界面文字的翻译,多种语言字体的管理、显示的支持以及输入法等等。这其中系统层面字体的管理和显示的支持直接关系到文字的显示效果,因此显得尤为重要。在KDE系统中,字体管理、显示的支持采用的是如下框架。

Fontconfig(字体配置)-------->Freetype(字库操作)-------------->xft(字体渲染)

Fontconfig : 管理系统安装的字体,根据应用程序的字体配置,match(匹配)一种字体,填充match字体的各种属性。

Freetype : 以Fontconfig匹配到的字体为参数,根据应用程序需要读取相应的字库。

xft: 对需要显示的语言文字进行渲染

二、X系统中字体的管理

作为KDE底层支持的X,它使用字体服务器(xfs)对安装的字体进行管理,也称之为“核心字库管理系统”,基本配置原理是xfs使用可维护的字体安装目录和fonts.dir文件对字体进行操作。

X为之提供了一些工具来完成管理操作。诸如 :

mkfontdir,mkfontscale 用来生成安装字体的 fonts.dir和fonts.scale。

xlsfonts 用来显示安装的字体。

xfd 用来显示指定字库的信息。

xset 用来管理字体服务器。

对于FreeBSD,在安装了xorg 7.2并且X server运行的情况下,字体安装目录可用 xset q来查询

shell>xset q



Font Path:

/usr/local/lib/X11/fonts/misc/,/usr/local/lib/X11/fonts/TTF/,

/usr/local/lib/X11/fonts/OTF,/usr/local/lib/X11/fonts/Type1/,

/usr/local/lib/X11/fonts/100dpi/,/usr/local/lib/X11/fonts/75dpi/,

/home/dbhrscom/.fonts


上面显示的是X系统安装时定义的字体目录。在这些目录中,都有利用mkfontdir生成的fonts.dir(对于true type 字体需要使用mkfontscale 生成 fonts.scale,然后拷贝到fonts.dir中)。fonts.dir是个文本文件,里面保存的是所在目录的字体信息。关于这些信息的具体含义,可以参见X的man手册,这里不再赘述。

如果准备把一个字体安装到X系统中,并且使用Xfs进行管理,大致需要以下过程:

1、建立一个目录,并且把字库文件拷贝到这个目录下

2、运行mkfontdir或者mkfontscale,生成安装字库的fonts.dir文件。

3、运行“mkfontdir -e 系统编码目录” 生成encodings.dir 文件(可选)

4、运行 “xset +fp 字体目录” 或者  “xset fp+ 字体目录”,把字体目录添加到xfs的字体目录列表中。需要注意的是当字体目录没有fonts.dir这个文件时,这种添加字体目录操作会失败。

5、运行“xset rehash”进行更新,确保新添加的字体可用。

注意:作为一种X系统的约定,安装字体最方便的做法是把字体文件拷贝到“$HOME/.fonts/“目录下,这样省去了添加字体目录的操作,而且xset +fp 是针对当前会话有效,如果准备系统启动时有效,还要修改相关的配置文件。

三、Fontconfig的字体管理

简单的说Fontconfig是使用字体缓存的机制来进行字体管理的。这个Xfs有所不同。fontconfig提供fc-cache来建立这个缓存。

shell >fc-cache -v



/usr/local/lib/X11/fonts: skipping, 0 fonts, 12 dirs

/usr/local/lib/X11/fonts/100dpi: skipping, 398 fonts, 0 dirs

/usr/local/lib/X11/fonts/75dpi: skipping, 398 fonts, 0 dirs

/usr/local/lib/X11/fonts/Fonts: skipping, 4 fonts, 0 dirs

/usr/local/lib/X11/fonts/OTF: skipping, 23 fonts, 0 dirs

/usr/local/lib/X11/fonts/TTF: skipping, 13 fonts, 0 dirs

/usr/local/lib/X11/fonts/Type1: skipping, 29 fonts, 0 dirs

/usr/local/lib/X11/fonts/bitstream-vera: skipping, 10 fonts, 0 dirs

/usr/local/lib/X11/fonts/cyrillic: skipping, 0 fonts, 0 dirs

/usr/local/lib/X11/fonts/encodings: skipping, 0 fonts, 1 dirs

/usr/local/lib/X11/fonts/encodings/large: skipping, 0 fonts, 0 dirs

/usr/local/lib/X11/fonts/local: skipping, 0 fonts, 0 dirs

/usr/local/lib/X11/fonts/misc: skipping, 55 fonts, 0 dirs

/usr/local/lib/X11/fonts/util: skipping, 0 fonts, 0 dirs

/home/dbhrscom/.fonts: skipping, 0 fonts, 0 dirs

/var/db/fontconfig: not cleaning unwritable cache directory

/home/dbhrscom/.fontconfig: cleaning cache directory

fc-cache: succeeded


fc-cache的运行原理是扫描fontconfig的配置文件中定义的字体目录,然后利用扫描的结果生成系统字体缓存。在这个fc- cache -v的运行结果中可以看到,它所扫描的路径已经涵盖了xfs所管理的系统字体路径。但这并不表示fontconfig和xfs的继承关系, fontconfig扫描这些目录,完全是因为在配置文件fonts.conf中有这样的定义!





        /usr/local/lib/X11/fonts



        ~/.fonts







        /var/db/fontconfig

        ~/.fontconfig


fc-cache所作的扫描都是基于以上的定义。

这个配置文件在fontconfig最新版本中,默认放在下面的目录中

/usr/local/etc/fonts/

而生成的字体缓存按照系统和当前用户,分别存放到

/var/db/fontconfig
~/.fontconfig
这两个目录中,诸如下面所看到的

0c3f6abf7a2705d2e8570f7f70e9302d-x86.cache-2

1e99991e6eeb0b3e05d4185c886f4b19-x86.cache-2

2550ddc31d0b62d94bc27b0fea358aba-x86.cache-2

55cbb48b13195d29d336fd465f155e7b-x86.cache-2

75ff5e8ddb5aa19e5f229f72d89c73db-x86.cache-2


.cache-2 就是fc-cache的运行记号,fontconfig通过这个缓存来管理系统安装的字体,也因为这种机制在系统中安装字体变得非常简单,只要把字体文件放到fonts.conf定义的目录中,然后运行一下fc-cache。

甚至fc-cache一下也不需要,因为在fonts.conf中定义了刷新时间:



                

                        30

                


     

由此看出,fontconfig和xfs相比,fontconfig提供了更加灵活的字体管理机制,目前系统中保持xfs和fontconfig 并行工作的理由,只能是为必须使用xfs机制的程序提供一种支援。而作为KDE,它使用的就是fontconfig进行字体管理。举例来说,KDE的控制中心有个“字体安装”模块,通过分析可知它进行字体安装的原理就是自定义一个安装路径,放到fontconfig的配置文件中,然后把字体拷贝到自定义的目录。

四、Fontconfig配置文件的结构

在2.4.2以后的版本中,Fonfconfig的配置文件采用了模块化的结构。配置文件由以下文件组成

/usr/local/etc/fonts/fonts.conf

/usr/local/etc/fonts/conf.avail/*.conf

/usr/local/etc/fonts/conf.d/*.conf


/usr/local/etc/fonts/conf.d/ 目录下的文件大多数是 conf.avail/ 目录下的连接,大致是如下这些:

20-fix-globaladvance.conf

20-lohit-gujarati.conf

20-unhint-small-vera.conf

30-amt-aliases.conf

30-urw-aliases.conf

40-generic.conf

49-sansserif.conf

50-user.conf

51-local.conf

60-latin.conf

65-fonts-persian.conf

65-nonlatin.conf

69-unifont.conf

80-delicious.conf

90-synthetic.conf


前面的数字用来控制执行的先后顺序,从名称上就可以看出,每个.conf文件都有针对性的字体特性进行处理。

而实现这种模块化,所借助的就是 /usr/local/etc/fonts/fonts.conf 文件。



        conf.d



分析/usr/local/etc/fonts/conf.d 目录下的文件,并通过打开Fontconfig的调试功能,可知这些配置文件的执行顺序:

        Loading config file /usr/local/etc/fonts/fonts.conf

        Scanning config dir /usr/local/etc/fonts/conf.d

        Loading config file /usr/local/etc/fonts/conf.d/20-fix-globaladvance.conf

        Loading config file /usr/local/etc/fonts/conf.d/20-lohit-gujarati.conf

        Loading config file /usr/local/etc/fonts/conf.d/20-unhint-small-vera.conf

        Loading config file /usr/local/etc/fonts/conf.d/30-amt-aliases.conf

        Loading config file /usr/local/etc/fonts/conf.d/30-urw-aliases.conf

        Loading config file /usr/local/etc/fonts/conf.d/40-generic.conf

        Loading config file /usr/local/etc/fonts/conf.d/49-sansserif.conf

        Loading config file /usr/local/etc/fonts/conf.d/50-user.conf

        Loading config file /home/dbhrscom/.fonts.conf

        Loading config file /usr/local/etc/fonts/conf.d/51-local.conf

        Loading config file /usr/local/etc/fonts/conf.d/60-latin.conf

        Loading config file /usr/local/etc/fonts/conf.d/65-fonts-persian.conf

        Loading config file /usr/local/etc/fonts/conf.d/65-nonlatin.conf

        Loading config file /usr/local/etc/fonts/conf.d/69-unifont.conf

        Loading config file /usr/local/etc/fonts/conf.d/80-delicious.conf

        Loading config file /usr/local/etc/fonts/conf.d/90-synthetic.conf


五、Fontconfig所提供的调试功能

Fontconfig提供了调制功能,用来诊断字体配置运行时的信息,使用调制功能非常简单,在KDE环境下用模拟终端定义 FC_DEBUG 这个环境变量的值即可:

例如:csh环境下

setenv FC_DEBUG 1

在模拟终端中启动相应的程序,就可以查看设定的调试信息。可以按照下面Fontconfig用户手册介绍的说明设定具体显示的调试信息。

  MATCH            1    Brief information about font matching 字体匹配信息

  MATCHV           2    Extensive font matching information

  EDIT             4    Monitor match/test/edit execution 显示match/test/edit信息

  FONTSET          8    Track loading of font information at startup

  CACHE           16    Watch cache files being written

  CACHEV          32    Extensive cache file writing information

  PARSE           64    (no longer in use)

  SCAN           128    Watch font files being scanned to build caches

  SCANV          256    Verbose font file scanning information

  MEMORY         512    Monitor fontconfig memory usage

  CONFIG        1024    Monitor which config files are loaded 显示配置文件装载信息

  LANGSET       2048    Dump char sets used to construct lang values

  OBJTYPES      4096    Display message when value typechecks fail
六、Fontconfig的字体匹配

Fontconfig的字体匹配模块是它的功能核心,设计的目标是确保根据“使用Fontconfig的应用程序所题出来的字体要求”能在系统安装的字体中找到一个匹配的字体,并为后续的字体渲染、字体显示填充一些用户可以控制的属性。字体匹配的原理简单的说就是“字体之间属性距离的计算”,通过比较应用程序所要求的字体与Fontconfig所管理的字体一些属性之间的距离,来确保可以找到一个字体,理想的字体匹配是“完全满足应用程序的要求”,但一般情况下,因为受系统中安装字体种类的限制、用户审美取向的不同以及Fontconfig配置文件的具体设定等因素的影响,只能依据“综合距离最小”的原则匹配到一种字体。然后根据Fontconfig配置文件中对具体字体的设定,以及后续字体渲染的一些要求,最终“加工”出一个“具有完整属性”的字体。

在整个字体匹配过程中,Fontconfig提供了一种非常灵活的控制字体匹配的机制,它通过可定制的的配置文件(fonts.conf)生成可对字体匹配造成影响的匹配规则,利用这些规则,用户可以替换字体,可以对可用字体进行排序,可以针对不同语言环境进行优化调整,甚至可以针对一种字体的不同大小,进行字体渲染的微调,这一切都可以利用Fontconfig的配置文件来调整,这一切也都是利用配置文件来控制,而这正符合Unix应用哲学中的“高可定制性”,因此想要掌握桌面系统的字体匹配,首先必须要了解掌握的就是Fontconfig的配置文件—fonts.conf和conf.d下的所有配置文件。

在第一部分已经提到了目前fonts.conf的一种发展趋势,就是模快化设计,但是fontconfig系统运行时,是加载全部的配置文件。

为了更深层次的对fontconfig的字体匹配机制进行分析,先明确几个概念性的东西:

(一)字体的属性

在fontconfig中定义了35种字体属性,在fontconfig的用户手册中有所介绍,现摘录如下:

 
CODE:
  属性                   类型           说明
  family          String  Font family names
  familylang      String  Languages corresponding to each family
  style           String  Font style. Overrides weight and slant
  stylelang       String  Languages corresponding to each style
  fullname        String  Font full names (often includes style)
  fullnamelang    String  Languages corresponding to each fullname
  slant           Int     Italic, oblique or roman
  weight          Int     Light, medium, demibold, bold or black
  size            Double  Point size
  width           Int     Condensed, normal or expanded
  aspect          Double  Stretches glyphs horizontally before hinting
  pixelsize       Double  Pixel size
  spacing         Int     Proportional, dual-width, monospace or charcell
  foundry         String  Font foundry name
  antialias       Bool    Whether glyphs can be antialiased
  hinting         Bool    Whether the rasterizer should use hinting
  hintstyle       Int     Automatic hinting style
  verticallayout  Bool    Use vertical layout
  autohint        Bool    Use autohinter instead of normal hinter
  globaladvance   Bool    Use font global advance data
  file            String  The filename holding the font
  index           Int     The index of the font within the file
  ftface          FT_Face Use the specified FreeType face object
  rasterizer      String  Which rasterizer is in use
  outline         Bool    Whether the glyphs are outlines
  scalable        Bool    Whether glyphs can be scaled
  scale           Double  Scale factor for point->pixel conversions
  dpi             Double  Target dots per inch
  rgba            Int     unknown, rgb, bgr, vrgb, vbgr,
                          none - subpixel geometry
  minspace        Bool    Eliminate leading from line spacing
  charset         CharSet Unicode chars encoded by the font
  lang            String  List of RFC-3066-style languages this
                          font supports
  fontversion     Int     Version number of the font
  capability      String  List of layout capabilities in the font
  embolden        Bool    Rasterizer should synthetically embolden the font

每个属性都有一个或多个值,用来描述字体的某方面特征。如 lang,它保存的是字体所支持的语言字符串,里面可以有多个值, 如 hinting ,它保存的是该字体在显示时是否进行hint渲染,值只能是 true 或 fasle。

从属性的功用上分,大致可以分为三类:

1、为后续的字体渲染所定义,fontconfig可以对这些属性进行设定,影响后续的字体显示动作。如:antialias、hinting、hintstyle、rgba 等等

2、为字体匹配所定义,这些属性用来完成字体匹配的运算。如:family、style 、lang

3、为标识字体所定义,这部分属性一般不参与字体匹配与字体渲染的操作,但用来标识字体的信息。如 fontversion。

一个具体的例子:simsun的字体属性,部分属性是根据fontconfig的配置文件生成。

 
CODE:
        family: "SimSun"(s)                 :字体家族名
        familylang: "en"(s)                :家族语言
        style: "Regular"(s)                :正常风格
        stylelang: "en"(s)                :语言风格
        slant: 0(i)(s)                        :倾斜
        weight: 80(i)(s)                :一些字体参数
        width: 100(i)(s)
        size: 12(f)(s)
        pixelsize: 12.5(f)(s)
        spacing: 90(i)(s)
        foundry: "unknown"(s)        :出品公司
        antialias: FcTrue(w)                :可antialias
        hintstyle: 2(i)(w)                :hint风格
        hinting: FcTrue(w)                :可hinting
        verticallayout: FcFalse(s)        :纵向输出
        autohint: FcFalse(s)                :不antohint       
        globaladvance: FcTrue(s)        :高级控制可用
        file: "/usr/local/lib/X11/fonts/Fonts/simsun.ttc"(s)        :字体位置
        index: 0(i)(s)                :索引
        outline: FcTrue(s)                :可outline
        scalable: FcTrue(s)                :可scalable
        dpi: 75(f)(s)                        :DPI值
        rgba: 5(i)(w)                        :rgba方式
        scale: 1(f)(s)                        :缩放方式
        charset: 0000: 00000000 ffffffff ffffffff 7fffffff 00000000 ffffffff ffffffff ffffffff (这里删去很多)
        lang: aa|ast|ay|bg|bi|br|ch|co|da|de|en|es|eu|fj|fo|fr|fur|fy|gd|gl|gv|ho|ia|id|ie|io|is|it|kum|lb|mg|nb|nds|nl|nn|no|oc|om|os|pt|rm|ru|sel|sma|smj|so|sq|sv|sw|tn|ts|vo|wa|xh|yap|zh-cn|zh-sg|zu(s) :支持zh-cn语言
        fontversion: 131072(i)(s)        :字体版本
        capability: "otlayout:hani"(s)        :兼容
        fontformat: "TrueType"(s)        :字体格式
        embeddedbitmap: FcTrue(s)        :位图字体增强
        decorative: FcFalse(s)        :可修饰

(二)、pattern

pattern是fontconfig字体匹配的核心数据结构,所有的匹配操作都是围绕着pattern来完成的,pattern可以理解成为一个在流水线上制造的汽车,汽车的用户需求相当于应用程序提出的字体要求,可以非常简单,比如sans serif字体,大小12号,这也是pattern的最初形态 ,Fontconfig相当于制造流水线,根据配置文件中所定义的匹配规则,对这个最初的pattern进行加工,随着工序的逐步完成,pattern变得有模有样,无论是功能还是外形,都按照匹配规则的定义进行了设定,最终当fontconfig的所有流水作业完成时,pattern已经被武装成了一种具体的字体 ,并添加了控制后续字体显示,渲染的属性参数。

这就是pattern,它最终表示的是一种设置周全的字体,满足应用程序,或者说用户的要求。

(三)、匹配规则

就是Fontconfig的配置文件中定义的那些规则,在进行字体匹配时fonts.conf和conf.d目录下的配置文件都要被fontconfig读取、分析,然后形成匹配规则列表,匹配规则可以分为三类

1、与pattern相关,这些规则用于进行字体匹配运算,最终可以得到一种字体

这种类型的规则在配置文件中大都以下面的形式进行定义:

 
CODE:
       
               
                        sans
               

               
                        sans-serif
               

       

简单说明一下:这个语句块的作用是,对pattern进行匹配操作,当pattern中的family属性中包含有sans时,匹配成功,执行下面的操作 —— 把pattern 中 family 属性中的 sans字体 替换成 sans-serif 字体。这里不对语句快中的具体参数进行解释,可以参看fontconfig的用户手册。

2、与font相关,这些规则主要是对匹配得到的字体进行进一步调整,满足用户的需求

 
CODE:
       
               
                        SimSun
               

               
                        false
               

       

简单说明一下:这个语句块的作用是,对匹配到的字体pattern进行字体匹配,如果这个字体pattern中的family属性是SimSun,则对这个匹配到的pattern做如下修改:把hinting的属性设定成false ,整个语句块的作用就是把simsun的hinting设定成假,如果匹配到的字体是simsun,那么这个设定就生效。如果没有匹配到simsun这个字体,这个匹配操作无效。

3、与字体渲染属性相关,这些规则主要是按照用户的需求,对字体的显示作一些定义。

 
CODE:
         
                 
                           true
               

       

简单说明一下:这个语句块是对fontconfig匹配到的字体,无论是什么字体,都修改antialias属性为true,这个语句块摘自用户目录下的.fonts.conf文件,由KDE控制中心的字体配置中进行设定。
【原文地址】
 
阅读(1933) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~