如何自动选择最适合不同语言的字体? [英] How to automatically choose most suitable font for different language?

查看:420
本文介绍了如何自动选择最适合不同语言的字体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要得到最适合不同语言的字体。所以我可以在不使用GDI文本的情况下绘制不同语言的文本(如TextOut)。



其实,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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆