Sal*_*dor 6 c unicode winapi font-linking
我的问题类似于这个,但有点前进.
在我的Win32程序中,我有一些菜单按钮,其中包含BMP以上的Unicode字符,例如U + 1F5A4(UTF-16代理对0xD83D 0xDDA4).
在Windows 10中,系统字体Segoe UI没有这个字形:它自动替换为字体Segoe UI Symbol中的字形并在按钮中正确显示,这要归功于一个称为字体链接的过程(或字体后退,仍然不清楚)对我来说).
但是在Windows 7中,字体链接会带来一个既没有这个字形的字体,代理对也显示为两个空框▯▯.在Windows XP中使用Tahoma字体也一样.
我想避免这些替换框,通过在分配到按钮之前或之后解析文本,并用一些常见的ASCII字符替换丢失的字形.
我试过GetGlyphOutline,ScriptGetCMap,GetFontUnicodeRanges和GetGlyphIndices,但他们不支持代理对.
我也试过GetCharacterPlacement和Uniscribe ScriptItemize+ ScriptShape支持代理对,但所有这些功能只搜索到HDC(Segoe UI)的基本字体,他们不搜索最终后备字体(Segoe UI符号),这是提供字形.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink 它是我看的地方,但我真的认为系统没有将字体链接到那里.
问题是:如何知道系统字体链接是否产生正确的字形或豆腐盒?
我找到了某种解决方案来复制这段代码并添加最后一个GetCharacterPlacement.
#include <usp10.h>
wchar_t *checkGlyphExist( HWND hwnd, wchar_t *sUnicode, wchar_t *sLimited ) {
// Create metafile
HDC hdc = GetDC( hwnd );
HDC metaFileDC = CreateEnhMetaFile( hdc, NULL, NULL, NULL );
// Select menu font
NONCLIENTMETRICSW ncm;
ncm.cbSize = sizeof(ncm);
SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0 );
HFONT hFont = CreateFontIndirectW( &(ncm.lfMenuFont) );
SelectObject( metaFileDC, hFont );
wprintf( L"%s\n", ncm.lfMenuFont.lfFaceName ); // 'Segoe UI' in Win 10 and 7 (ok)
// 'Tahoma' in Win XP (ok)
// Use the meta file to intercept the fallback font chosen by Uniscribe
SCRIPT_STRING_ANALYSIS ssa;
ScriptStringAnalyse( metaFileDC, sUnicode, wcslen(sUnicode), 0, -1,
SSA_METAFILE | SSA_FALLBACK | SSA_GLYPHS | SSA_LINK,
0, NULL, NULL, NULL, NULL, NULL, &ssa );
ScriptStringFree( &ssa );
HENHMETAFILE metaFile = CloseEnhMetaFile(metaFileDC);
LOGFONTW logFont = {0};
EnumEnhMetaFile( 0, metaFile, metaFileEnumProc, &logFont, NULL );
DeleteEnhMetaFile( metaFile );
wprintf( L"%s\n", logFont.lfFaceName );
// 'Segoe UI Symbol' in Win 10 (ok)
// 'Microsoft Sans Serif' in Win 7 (wrong, should be 'Segoe UI Symbol')
// 'Tahoma' in Win XP for characters above 0xFFFF (wrong, should be 'Microsoft Sans Serif', I guess)
// Get glyph indices for the 'sUnicode' string
hFont = CreateFontIndirectW( &logFont );
SelectObject( hdc, hFont );
GCP_RESULTSW infoStr = {0};
infoStr.lStructSize = sizeof(GCP_RESULTSW);
wchar_t tempStr[wcslen(sUnicode)];
wcscpy( tempStr, sUnicode );
infoStr.lpGlyphs = tempStr;
infoStr.nGlyphs = wcslen(tempStr);
GetCharacterPlacementW( hdc, tempStr, wcslen(tempStr), 0, &infoStr, GCP_GLYPHSHAPE );
ReleaseDC( hwnd, hdc );
// Return one string
if( infoStr.lpGlyphs[0] == 3 || // for Windows 7 and 10
infoStr.lpGlyphs[0] == 0 ) // for Windows XP
return sLimited;
else
return sUnicode;
}
// Callback function to intercept font creation
int CALLBACK metaFileEnumProc( HDC hdc, HANDLETABLE *table, const ENHMETARECORD *record,
int tableEntries, LPARAM logFont ) {
if( record->iType == EMR_EXTCREATEFONTINDIRECTW ) {
const EMREXTCREATEFONTINDIRECTW* fontRecord = (const EMREXTCREATEFONTINDIRECTW *)record;
*(LOGFONTW *)logFont = fontRecord->elfw.elfLogFont;
}
return 1;
}
Run Code Online (Sandbox Code Playgroud)
你可以用它来调用它 checkGlyphExist( hWnd, L"", L"<3" );
我在Windows 10和两个虚拟机上进行了测试:Windows 7 Professional,Windows XP SP2.
它工作得很好,但是当基本字体中缺少字形时,EnumEnhMetaFile检索的后备字体仍然存在两个问题:
有人可以帮我解决这个问题吗?
小智 -3
我相信代理对的高位和低位 16 位字已被明确定义。您应该能够通过检查每个 16 位字的值范围来识别代理对。
对于高位字,它应该在 0xd800 到 0xdbff 的范围内 对于低位字,它应该在 0xdc00 到 0xdfff 的范围内
如果任意两对“角色”满足此标准,则它们是代理对。
有关详细信息,请参阅有关 UTF-16 的维基百科文章。
| 归档时间: |
|
| 查看次数: |
674 次 |
| 最近记录: |