多语言字符串的字体问题

原创 2012年03月22日 12:20:01
一个字符能够在Windows界面上显示出来,首先是当前编码要跟该字符的编码一致,同时还需要当前的字体支持。如果编码不匹配,显示出来往往就是乱码,如果字体不匹配,显示出来则往往是一个个方框。这里我们要分析一下字体的问题,对于一段字符串,如果里面包含了多种语言,尤其东亚语言,则用户选定的字体,往往不能支持所有的语言,比如中文并不支持Arial和Tahoma等字体。如果该字符没有对应的字体支持,就不会正常显示。那么究竟如何选择字体来显示含有多语言的字符串呢?

首先来介绍一下原理。OpenType font是由Microsoft和Adobe联合开发的基于Unicode的字体系统,它扩展了由Apple开发的TrueType font,能够对应字符(character)和它的图形(glyph)。在Windows中,核心字体包括Times New Roman, Courier New, Arial, Microsoft Sans Serif和Tahoma,这些字体能够显示包括了拉丁,希伯来、阿拉伯、希腊等语言,但没有包括东亚语言。当选择上面这些字体时,对于东亚语言,实际上是用了另外的字体进行了显示。也就是说,对于一段含有多语言的字符串,虽然选定了一种字体,但实际上对于那些该字体支持不了的字符,有另外的字体与之对应

这种字体对应的技术,在Windows中主要包括Font Fallback和Font Linking两种技术。一般而言,Font Fallback是在Application中完成,而Font Linking是在操作系统的GDI中完成。可以想见,如果两种技术都用到的话,那么一个字符的显示,首先用Font Fallback处理,然后还会用Font Linking处理,也就说后者可能会覆盖前者的结果。

Font Fallback - 为每种语言提供默认字体
-----------------------------------------
微软提供了Uniscribe模块,以库USP10.DLL的形式,能够使Application实现Windows的Font FallbackUniscribe是一组处理unicode字符的API函数服务集,这些函数可以被分成两大类:一种是底层的API函数,另一种就是叫做ScriptString的Wrapper library,封装了底层的API。ScriptString一般用于单种选定的字体(包含实际显示不同语言字符的不同字体)或者单种颜色的情况,典型的例子就是Windows的Notepad程序。但一些高级的应用,就不能简单的使用ScriptString,而是要用到Uniscribe的底层API函数。

注意,对于Font Fallback,Uniscribe的底层API并没有处理它,所以基于Uniscribe的应用可能需要自己内建fallback font列表来解决这个问题;但是ScriptString,即Uniscribe的封装库,却提供了这个功能,但是需要操作系统激活它才行(见后面说明)。请参考http://www.catch22.net/tuts/more-uniscribe-mysteries

我们下面所说的,都是指Uniscribe自动支持Font Fallback的情况,比如Notepad显示复杂字符串的过程。(一般Windows提供的API,比如DrawText,都会调用ExtTextOut,应该使用Uniscribe的ScriptString来实现Font Fallback功能?,所以如果你要实现自己的复杂的编辑器,比如word那样的软件,你可能不能简单的使用ExtTextOut,而是要用到Uniscribe的底层API?)

通过Uniscribe提供Font fallback的过程,可参见下面的图。当Application通过Win32 API函数ExtTextOut()输出字符串时,如果该函数发现作为参数输入的字符串是复杂字符串,并会调用Uniscribe提供的API函数进行处理,然后传给GDI进行显示;当然字符串不是复杂字符串,则可以直接传送给GDI。


比如Notepad上要显示一段文本,包括了英语、希伯来语和Telugu语,用户选用Tahoma来显示它。Tahoma是Opentype字体,支持英语和希伯来语的显示,但不支持Telugu语,所以当解析到Telugu字符时,Uniscribe发现Tahoma无法显示字符,便使用Telugu的默认字体Gautami来显示它。这些默认的字体,用户无法增加或修改。整个过程对用户来讲是透明的,不需要用户去关心其中。

需要注意的是,网上有资料说,ExtTextOut()函数本身并不会自动支持复杂字符串的处理,必须在Windows XP中选中下图所示的两个配置后,Uniscribe的Font Fallback技术才能被激活使用。参见http://www.catch22.net/tuts/introduction-uniscribe


在Windows 7之后,提供了DirectWrite,实现Uniscribe类似的功能。

有关Font Fallback在Windows中的支持,详见http://msdn.microsoft.com/en-us/goglobal/bb688099

Font Linking - 为一种字体提供多种链接字体
--------------------------------------------
Font Linking技术被GDI实现。不像Font Fallback固定的使用默认字体,Font Linking技术能够使用一种甚至多种字体(linked font)链接到另外一种字体(base font)。你如果使用base font去显示某一段多语言的文本,对于不支持base font的文字,系统能够自动使用linked font代替。

比如,我们将hangul字体和Japanese字体链接到Tahoma字体上,也就说这里base font是Tahoma,linked font有两个,是hangul和Janpanese字体。这样,对于包含日文和韩文的文本,用户可以设定Tahoma字体来统一显示,对于里面的韩文,系统自动会用hangul字体显示。

如果系统使能了Font Linking,用户可以在Windows注册表上修改Font Linking信息。它们在HKEY_LOCAL_MACHINE–\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink中能够找到。我们可以如下图所示进行修改。
Figure 1: RegEdit's
注意上面对话框中的Value data表示linked fonts信息,每一行表示一个Linked font,前面是font的文件名,用逗号分隔,后面则是字体名。
修改后,必须重启系统才能生效。

Font Substitution
--------------------------------------------------------
提供了对将对一种字体的请求转化到另一种字体的机制。参见注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes

详细的信息,参考网址:http://msdn.microsoft.com/en-us/goglobal/bb688134

实际问题的分析
---------------------------------------------------------
问题现象:一个英文韩文混杂的文件,在Windows XP的系统上用Notepad显示,如字体用Tahoma,则显示正常,如果字体用Arial或其他几种,则韩文显示成方框,文件编码正常,主要是字体问题,如何解释?
原因分析:
根据前面介绍,该文件内部的字符串要正常显示,可能会先后经过Font Fallback和Font Linking这两种技术的处理。对于Font Fallback,因为在Windows XP系统的语言设置中,没有完全激活自动的Font Fallback功能,所以不再考虑。对于Font Linking技术,看到Windows注册表中,对于Tahoma字体,设置了其到能够显示韩文的字体的Linking,所以当我们选择字体Tahoma时,能够正常显示,但选择Arial时,注册表中并没有对其做Font Linking,所以没法显示。

DrawText输出Unicode中文时乱码的问题

自行设置了字体,:
  • chenlycly
  • chenlycly
  • 2014年11月03日 21:31
  • 2128

tesseract OCR的多语言,多字体字符识别

识别多种字体、多种语言的字符,在实际应用中是很常见的问题。 经过测试,及查看tesseract3.01的源码,tesseract 3.01版本是不支持多语言、多种字体OCR识别的。 tessera...
  • viewcode
  • viewcode
  • 2012年08月28日 18:24
  • 15212

Android系统应用开发(四)系统语言以及添加字体库

1.如何向android的setting语言列表中添加一门语言 第一种:修改配置文件 位置:build/target/product/languages_full.mk| languages_sm...
  • sky_pjf
  • sky_pjf
  • 2016年09月12日 17:46
  • 3181

android判断手机是否支持某种语言

在做app多语言的时候,遇到手机不支持某种语言时,显示空白,或方框里面打叉。 原因是手机系统的字体库不支持该种语言。 解决思路:去检测手机系统是否支持,不支持时,不显示该种语言设置选择。 方法:例如旁...
  • xu20082100226
  • xu20082100226
  • 2017年08月18日 17:28
  • 203

如何使MessageBox显示多语言

public static void MessageBoxShow(string default_Language,string CN_Language, int i)        {       ...
  • kongzifan
  • kongzifan
  • 2008年09月25日 14:15
  • 1310

QT国际化与多语言实现

1.Unicode编码         Unicode是一种支持世界上绝大多数文字系统的字符编码标准。QT中的QString类用于将字符串存储为Unicode。 2.应用程序如何翻译QT文件  ...
  • VIPCCJ
  • VIPCCJ
  • 2015年11月16日 13:25
  • 778

ubuntu因“不完整的语言支持”更新后字体变难看的解决

原本类似于微软雅黑的字体一下子成了宋体,圆圆的方方正正就是感
  • gaopu12345
  • gaopu12345
  • 2014年08月22日 22:37
  • 2529

易语言支持,含皮肤、欢迎大家下载

  • 2010年04月19日 21:44
  • 211KB
  • 下载

解析android多语言与自定义字体

一、android多语言 这里以汉语 英文 印尼文为例记录一下实现流程 1.1,value文件夹下添加不同语言的String.xml文件,分别是 values默认 多语言例子 ...
  • liuxingyuzaixian
  • liuxingyuzaixian
  • 2018年01月02日 16:33
  • 58

web多语言url的设计

因为项目要支持国际化,最近跟一个同事在讨论多语言版本下面url如何设计,假如我们需要支持en和cn的版本。 他倾向于支持如下的url格式,后续以格式1指代: /en/group/abc.htm...
  • siddontang
  • siddontang
  • 2014年03月17日 09:15
  • 1657
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:多语言字符串的字体问题
举报原因:
原因补充:

(最多只允许输入30个字)