如何自动选择最适合不同语言的字体? [英] How to automatically choose most suitable font for different language?
问题描述
其实,api TextOut就是这样做的。
HFONT hFont = NULL;
LOGFONT lg = {0};
lg.lfHeight = 14;
lg.lfWeight = FW_NORMAL;
wcscpy_s(lg.lfFaceName,LF_FACESIZE,LArial);
hFont = CreateFontIndirect(& lg);
SelectObject(hdc,hFont);
TextOut(hdc,0,50,Labc我爱,5);
由于Arial字体不支持中文,所以TextOut不应该能够画出中文'我爱。但它确实,并选择一个合适的字体,一个正常的字体,而不是某种艺术字体,为此。
我怎么可以模拟TextOut做什么,或者有什么其他的方法来找出在Windows下的一种语言最适合的字体?
是的,这是可能的。这里是从chrome项目中轻微修改过的代码片段,
$ p $回调到EnumEnhMetaFile()拦截字体创建。
int CALLBACK MetaFileEnumProc(HDC hdc,
HANDLETABLE * table,
CONST ENHMETARECORD * record,
int table_entries,
LPARAM log_font)
{$ b $ (记录 - > iType == EMR_EXTCREATEFONTINDIRECTW){
const EMREXTCREATEFONTINDIRECTW * create_font_record =
reinterpret_cast< const EMREXTCREATEFONTINDIRECTW *>>(record);
* reinterpret_cast< LOGFONT *>(log_font)= create_font_record> elfw.elfLogFont;
}
return 1;
}
//查找用于渲染指定的| text |的后备字体关于
//一个初始|字体|。通过param | result |返回结果字体。返回
// | true |如果找到回退字体。
//改编自WebKit的| FontCache :: GetFontDataForCharacters()|。
// TODO(asvitkine):这个应该移到font_fallback_win.cc。
bool ChooseFallbackFont(HDC hdc,
HFONT font,
const wchar_t * text,
int text_length,
LOGFONT * result)
{
//使用元文件截取Uniscribe选择的回退字体。
HDC meta_file_dc = CreateEnhMetaFile(hdc,NULL,NULL,NULL);
if(!meta_file_dc)
return false;
if(font)
SelectObject(meta_file_dc,font);
SCRIPT_STRING_ANALYSIS script_analysis;
HRESULT hresult =
ScriptStringAnalyse(meta_file_dc,text,text_length,0,-1,
SSA_METAFILE | SSA_FALLBACK | SSA_GLYPHS | SSA_LINK,
0,NULL,NULL,NULL,NULL, NULL,& script_analysis);
if(SUCCEEDED(hresult)){
hresult = ScriptStringOut(script_analysis,0,0,0,NULL,0,0,FALSE);
ScriptStringFree(& script_analysis);
}
bool found_fallback = false;
HENHMETAFILE meta_file = CloseEnhMetaFile(meta_file_dc);
if(SUCCEEDED(hresult)){
LOGFONT log_font;
log_font.lfFaceName [0] = 0;
EnumEnhMetaFile(0,meta_file,MetaFileEnumProc,& log_font,NULL);
if(log_font.lfFaceName [0]){
* result = log_font;
found_fallback = true;
}
}
DeleteEnhMetaFile(meta_file);
return found_fallback;
示例代码:
std :: wstring arabicStr = Lششش;
hdc = BeginPaint(hWnd,& ps);
LOGFONT logFont = {0};
wcscpy_s(logFont.lfFaceName,L微软雅黑);
HFONT hFont = CreateFontIndirect(& logFont);
ChooseFallbackFont(hdc,hFont,arabicStr.c_str(),arabicStr.length(),& logFont);
ATLTRACE(logFont.lfFaceName);
HFONT hFontNew = CreateFontIndirect(& logFont);
HFONT hFontOld =(HFONT)SelectObject(hdc,hFontNew);
wchar_t glyphs [10] = {0};
GCP_RESULTS gcpRet = {0};
gcpRet.lStructSize = sizeof(gcpRet);
gcpRet.lpGlyphs = glyphs;
gcpRet.nGlyphs = 10;
ATLASSERT(GetCharacterPlacement(hdc,arabicStr.c_str(),arabicStr.length(),GCP_MAXEXTENT,& gcpRet,
GCP_DISPLAYZWG | GCP_GLYPHSHAPE | GCP_REORDER));
RECT rcClient;
GetClientRect(hWnd,& rcClient);
ExtTextOut(hdc,200,200,ETO_GLYPH_INDEX | ETO_RTLREADING,& rcClient,gcpRet.lpGlyphs,gcpRet.nGlyphs,NULL);
SelectObject(hdc,hFontOld);
DeleteObject(hFontNew);
DeleteObject(hFont);
EndPaint(hWnd,& ps);
微软雅黑
不支持阿拉伯语,所以我们需要阿拉伯语的后备字体。在我的盒子里,GDI自动为阿拉伯语选择 Microsoft Sans Serif
。
I need to get the most suitable font for different language. So I could draw different language's text without using GDI text out API such as TextOut.
Actually, the api TextOut does it.
HFONT hFont = NULL;
LOGFONT lg = {0};
lg.lfHeight = 14;
lg.lfWeight = FW_NORMAL;
wcscpy_s(lg.lfFaceName, LF_FACESIZE ,L"Arial");
hFont = CreateFontIndirect(&lg);
SelectObject(hdc,hFont);
TextOut(hdc, 0, 50, L"abc我爱", 5);
Because the Arial font does not support Chinese, TextOut should not be able to draw the Chinese '我爱'. But it does and choose a suitable font, a normal font rather than some kind of art font, for it.
How could I simulate what TextOut does, or is there any other way to figure out the best suitable font for one language under Windows?
Yes, it is possible to do this. Here is the slight modified code snippet from chrome project,
// Callback to |EnumEnhMetaFile()| to intercept font creation.
int CALLBACK MetaFileEnumProc(HDC hdc,
HANDLETABLE* table,
CONST ENHMETARECORD* record,
int table_entries,
LPARAM log_font)
{
if (record->iType == EMR_EXTCREATEFONTINDIRECTW) {
const EMREXTCREATEFONTINDIRECTW* create_font_record =
reinterpret_cast<const EMREXTCREATEFONTINDIRECTW*>(record);
*reinterpret_cast<LOGFONT*>(log_font) = create_font_record->elfw.elfLogFont;
}
return 1;
}
// Finds a fallback font to use to render the specified |text| with respect to
// an initial |font|. Returns the resulting font via out param |result|. Returns
// |true| if a fallback font was found.
// Adapted from WebKit's |FontCache::GetFontDataForCharacters()|.
// TODO(asvitkine): This should be moved to font_fallback_win.cc.
bool ChooseFallbackFont(HDC hdc,
HFONT font,
const wchar_t* text,
int text_length,
LOGFONT* result)
{
// Use a meta file to intercept the fallback font chosen by Uniscribe.
HDC meta_file_dc = CreateEnhMetaFile(hdc, NULL, NULL, NULL);
if (!meta_file_dc)
return false;
if (font)
SelectObject(meta_file_dc, font);
SCRIPT_STRING_ANALYSIS script_analysis;
HRESULT hresult =
ScriptStringAnalyse(meta_file_dc, text, text_length, 0, -1,
SSA_METAFILE | SSA_FALLBACK | SSA_GLYPHS | SSA_LINK,
0, NULL, NULL, NULL, NULL, NULL, &script_analysis);
if (SUCCEEDED(hresult)) {
hresult = ScriptStringOut(script_analysis, 0, 0, 0, NULL, 0, 0, FALSE);
ScriptStringFree(&script_analysis);
}
bool found_fallback = false;
HENHMETAFILE meta_file = CloseEnhMetaFile(meta_file_dc);
if (SUCCEEDED(hresult)) {
LOGFONT log_font;
log_font.lfFaceName[0] = 0;
EnumEnhMetaFile(0, meta_file, MetaFileEnumProc, &log_font, NULL);
if (log_font.lfFaceName[0]) {
*result = log_font;
found_fallback = true;
}
}
DeleteEnhMetaFile(meta_file);
return found_fallback;
}
Sample code:
std::wstring arabicStr = L"ششش";
hdc = BeginPaint(hWnd, &ps);
LOGFONT logFont = {0};
wcscpy_s(logFont.lfFaceName, L"微软雅黑");
HFONT hFont = CreateFontIndirect(&logFont);
ChooseFallbackFont(hdc, hFont, arabicStr.c_str(), arabicStr.length(), &logFont);
ATLTRACE(logFont.lfFaceName);
HFONT hFontNew = CreateFontIndirect(&logFont);
HFONT hFontOld = (HFONT)SelectObject(hdc, hFontNew);
wchar_t glyphs[10] = {0};
GCP_RESULTS gcpRet = {0};
gcpRet.lStructSize = sizeof(gcpRet);
gcpRet.lpGlyphs = glyphs;
gcpRet.nGlyphs = 10;
ATLASSERT(GetCharacterPlacement(hdc, arabicStr.c_str(), arabicStr.length(), GCP_MAXEXTENT, &gcpRet,
GCP_DISPLAYZWG | GCP_GLYPHSHAPE | GCP_REORDER ));
RECT rcClient;
GetClientRect(hWnd, &rcClient);
ExtTextOut(hdc, 200, 200, ETO_GLYPH_INDEX | ETO_RTLREADING, &rcClient, gcpRet.lpGlyphs, gcpRet.nGlyphs, NULL);
SelectObject(hdc, hFontOld);
DeleteObject(hFontNew);
DeleteObject(hFont);
EndPaint(hWnd, &ps);
微软雅黑
is a font which does not support arabic, so we need a fallback font for the arabic. In my box, GDI automatically choose Microsoft Sans Serif
for the arabic.
这篇关于如何自动选择最适合不同语言的字体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!