如何检查哪些字符集(代码页)字体支持(有字母)?

时间:2016-01-31 09:14:41

标签: delphi fonts character delphi-xe2

对于我的应用程序,我需要显示系统字体列表,但过滤掉所有不支持20种预定义语言的字体(该集合是硬编码的)并仅显示那些字体。

我可以通过拨打Vcl.Forms.Screen.Fonts获得可用字体列表 只知道该列表中的字体名称,如何检查此字体支持的字符集(代码页)(具有实际字母)?

例如,像Arial或Times New Roman这样的常用字体几乎包含所有欧洲语言的字符,包括西里尔语(以及中文等)。然而,许多不太常见的字体通常只有英文字母。

该应用程序供内部使用,因此如果字体具有特定于某些字符集/代码页的特定字母(例如ФЎ或{{1},则具有简单查询字体的功能<)与其他通用字体(或某个占位符)的字母替换它就足够了。

2 个答案:

答案 0 :(得分:6)

GetGlyphIndices函数可用于确定字体中是否存在字形。

引用MSDN文档:

DWORD GetGlyphIndices(
  _In_  HDC     hdc,
  _In_  LPCTSTR lpstr,
  _In_  int     c,
  _Out_ LPWORD  pgi,
  _In_  DWORD   fl
);
     

参数[...]

     

fl [in]:指定字形的处理方式(如果不是)                支持的。此参数可以是以下值。

     

GGI_MARK_NONEXISTING_GLYPHS - 使用十六进制值0xffff标记不受支持的字形。

备注部分再次链接到Uniscribe功能,例如ScriptGetCMap

  

此函数尝试为lpstr指向的字符串中的每个字符标识单字形表示。虽然这对于某些低级目的(例如操作字体文件)很有用,但希望将字符串映射到字形的高级应用程序通常希望使用Uniscribe函数。

由于两个API都是从Win2k开始支持的,因此可能需要使用哪种API。

(编辑:刚刚注意到导入已经在Windows.pas中)

示例代码

procedure Test( dc : HDC);
var str : UnicodeString;
    buf : array of WORD;
    len,i : Integer;
    count : DWORD;
begin
  str := 'abc'+WideChar($0416)+'äöü';
  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

答案 1 :(得分:1)

如果要检查整个字符集支持,可以使用Windows API中的EnumFontFamiliesEx - 这不会让您查询单个字体,而是返回支持给定字符的已安装字体列表set(或具有任何其他可查询功能集)。

您需要一个回调函数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似乎是管理该任务的明智工具。