如何检查字体支持哪些字符集(代码页)(有字母)?
How to check which character sets (codepages) font supports (has letters for)?
对于我的应用程序,我需要显示系统字体列表,但过滤掉所有不支持 20 种预定义语言的字体(该集合是硬编码的)并仅显示支持的字体。
我可以通过调用 Vcl.Forms.Screen.Fonts
获得可用字体列表。
只知道该列表中的字体名称,如何检查该字体支持哪些字符集(代码页)(具有实际字母)?
例如,Arial 或 Times New Roman 等常见字体具有几乎所有欧洲语言的字符,包括西里尔字母(以及中文等)。然而,许多不太常见的字体通常只有英文字母。
该应用程序供内部使用,因此具有简单查询字体的功能,如果它具有特定于某些字符集/代码页的特定字母(例如 Ф
或 Ў
或 ξ
) 并且它不被另一种通用字体(或某些占位符)的字母替换就足够了。
GetGlyphIndices函数可用于判断字形是否存在于字体中。
引用 MSDN 文档:
DWORD GetGlyphIndices(
_In_ HDC hdc,
_In_ LPCTSTR lpstr,
_In_ int c,
_Out_ LPWORD pgi,
_In_ DWORD fl
);
Parameters [...]
fl
[in]: Specifies how glyphs should be handled if they are not
supported. This parameter can be the following value.
GGI_MARK_NONEXISTING_GLYPHS
-- Marks unsupported glyphs with the hexadecimal value 0xffff.
备注 部分再次链接到 Uniscribe 函数,例如ScriptGetCMap
This function attempts to identify a single-glyph representation for each character in the string pointed to by lpstr. While this is useful for certain low-level purposes (such as manipulating font files), higher-level applications that wish to map a string to glyphs will typically wish to use the Uniscribe functions.
由于从 Win2k 开始都支持这两种 API,因此使用哪一个可能是个人喜好问题。
(编辑:刚注意到导入已经在 Windows.pas)
示例代码
procedure Test( dc : HDC);
var str : UnicodeString;
buf : array of WORD;
len,i : Integer;
count : DWORD;
begin
str := 'abc'+WideChar(16)+'äöü';
len := Length(str);
SetLength( buf, len);
count := GetGlyphIndicesW( dc, PWideChar(str), len, @buf[0], GGI_MARK_NONEXISTING_GLYPHS);
if count > 0 then begin
for i := 0 to count-1 do begin
Write('index ',i,': ');
if buf[i] = $FFFF
then Writeln('glyph missing')
else Writeln('ok');
end;
end;
end;
产量
index 0: ok
index 1: ok
index 2: ok
index 3: glyph missing
index 4: ok
index 5: ok
index 6: ok
如果您想检查整个字符集支持,您可以使用 Windows API 中的 EnumFontFamiliesEx
- 这不会让您查询单个字体,而是 returns 支持给定字符集(或具有任何其他可查询功能集)的已安装字体列表。
你需要一个回调函数 of the appropriate type :
function EnumFontCallback(lpelfe : PLogFont;
lpntme : PNewTextMetricEX;
FontType : DWORD;
lp : LPARAM) : integer; stdcall;
begin
TMemo(lp).Lines.Add(lpelfe^.lfFaceName);
result := 1; // return zero to end enumeration
end;
然后调用为:
procedure TForm1.Button1Click(Sender: TObject);
var
lf : TLogFont;
begin
ZeroMemory(@lf,SizeOf(TLogFont));
lf.lfCharSet := CHINESEBIG5_CHARSET;
if not EnumFontFamiliesEx(Canvas.Handle, // HDC
lf, // TLogFont
@EnumFontCallback, // Callback Pointer
NativeInt(Memo1), // user supplied pointer
0) then // must be zero
begin
// function call failed.
end;
end;
通过 TLogFont (MSDN) 结构中的各个字段,您可以查询各种字体功能。在这种情况下,我只限制了字符集(在上例中限制为中文 Big-5)。
回调将针对查询返回的每种结果字体触发一次。当这些信息被返回时,您将需要设法收集这些信息。要为多个字符集添加限制,您需要为每个感兴趣的字符集调用一次 EnumFontFamiliesEx
。以下常量在 RTL Windows 单元中定义:
ANSI_CHARSET
BALTIC_CHARSET
CHINESEBIG5_CHARSET
DEFAULT_CHARSET // depends on system locale
EASTEUROPE_CHARSET
GB2312_CHARSET
GREEK_CHARSET
HANGUL_CHARSET
MAC_CHARSET
OEM_CHARSET // depends on OS
RUSSIAN_CHARSET
SHIFTJIS_CHARSET
SYMBOL_CHARSET
TURKISH_CHARSET
VIETNAMESE_CHARSET
JOHAB_CHARSET
ARABIC_CHARSET
HEBREW_CHARSET
THAI_CHARSET
交叉引用将由您决定 - TDictionary
似乎是管理该任务的明智工具。
对于我的应用程序,我需要显示系统字体列表,但过滤掉所有不支持 20 种预定义语言的字体(该集合是硬编码的)并仅显示支持的字体。
我可以通过调用 Vcl.Forms.Screen.Fonts
获得可用字体列表。
只知道该列表中的字体名称,如何检查该字体支持哪些字符集(代码页)(具有实际字母)?
例如,Arial 或 Times New Roman 等常见字体具有几乎所有欧洲语言的字符,包括西里尔字母(以及中文等)。然而,许多不太常见的字体通常只有英文字母。
该应用程序供内部使用,因此具有简单查询字体的功能,如果它具有特定于某些字符集/代码页的特定字母(例如 Ф
或 Ў
或 ξ
) 并且它不被另一种通用字体(或某些占位符)的字母替换就足够了。
GetGlyphIndices函数可用于判断字形是否存在于字体中。
引用 MSDN 文档:
DWORD GetGlyphIndices( _In_ HDC hdc, _In_ LPCTSTR lpstr, _In_ int c, _Out_ LPWORD pgi, _In_ DWORD fl );
Parameters [...]
fl
[in]: Specifies how glyphs should be handled if they are not supported. This parameter can be the following value.
GGI_MARK_NONEXISTING_GLYPHS
-- Marks unsupported glyphs with the hexadecimal value 0xffff.
备注 部分再次链接到 Uniscribe 函数,例如ScriptGetCMap
This function attempts to identify a single-glyph representation for each character in the string pointed to by lpstr. While this is useful for certain low-level purposes (such as manipulating font files), higher-level applications that wish to map a string to glyphs will typically wish to use the Uniscribe functions.
由于从 Win2k 开始都支持这两种 API,因此使用哪一个可能是个人喜好问题。
(编辑:刚注意到导入已经在 Windows.pas)
示例代码
procedure Test( dc : HDC);
var str : UnicodeString;
buf : array of WORD;
len,i : Integer;
count : DWORD;
begin
str := 'abc'+WideChar(16)+'äöü';
len := Length(str);
SetLength( buf, len);
count := GetGlyphIndicesW( dc, PWideChar(str), len, @buf[0], GGI_MARK_NONEXISTING_GLYPHS);
if count > 0 then begin
for i := 0 to count-1 do begin
Write('index ',i,': ');
if buf[i] = $FFFF
then Writeln('glyph missing')
else Writeln('ok');
end;
end;
end;
产量
index 0: ok
index 1: ok
index 2: ok
index 3: glyph missing
index 4: ok
index 5: ok
index 6: ok
如果您想检查整个字符集支持,您可以使用 Windows API 中的 EnumFontFamiliesEx
- 这不会让您查询单个字体,而是 returns 支持给定字符集(或具有任何其他可查询功能集)的已安装字体列表。
你需要一个回调函数 of the appropriate type :
function EnumFontCallback(lpelfe : PLogFont;
lpntme : PNewTextMetricEX;
FontType : DWORD;
lp : LPARAM) : integer; stdcall;
begin
TMemo(lp).Lines.Add(lpelfe^.lfFaceName);
result := 1; // return zero to end enumeration
end;
然后调用为:
procedure TForm1.Button1Click(Sender: TObject);
var
lf : TLogFont;
begin
ZeroMemory(@lf,SizeOf(TLogFont));
lf.lfCharSet := CHINESEBIG5_CHARSET;
if not EnumFontFamiliesEx(Canvas.Handle, // HDC
lf, // TLogFont
@EnumFontCallback, // Callback Pointer
NativeInt(Memo1), // user supplied pointer
0) then // must be zero
begin
// function call failed.
end;
end;
通过 TLogFont (MSDN) 结构中的各个字段,您可以查询各种字体功能。在这种情况下,我只限制了字符集(在上例中限制为中文 Big-5)。
回调将针对查询返回的每种结果字体触发一次。当这些信息被返回时,您将需要设法收集这些信息。要为多个字符集添加限制,您需要为每个感兴趣的字符集调用一次 EnumFontFamiliesEx
。以下常量在 RTL Windows 单元中定义:
ANSI_CHARSET
BALTIC_CHARSET
CHINESEBIG5_CHARSET
DEFAULT_CHARSET // depends on system locale
EASTEUROPE_CHARSET
GB2312_CHARSET
GREEK_CHARSET
HANGUL_CHARSET
MAC_CHARSET
OEM_CHARSET // depends on OS
RUSSIAN_CHARSET
SHIFTJIS_CHARSET
SYMBOL_CHARSET
TURKISH_CHARSET
VIETNAMESE_CHARSET
JOHAB_CHARSET
ARABIC_CHARSET
HEBREW_CHARSET
THAI_CHARSET
交叉引用将由您决定 - TDictionary
似乎是管理该任务的明智工具。