My question is similar to this , but a little step forward.
In my Win32 program, I have a menu button with Unicode characters above BMP, for example U + 1F5A4 π€ (pairs of surrogates UTF-16 0xD83D 0xDDA4).
In Windows 10, the Segoe UI system font does not have this symbol: it is automatically replaced by the Segoe UI Symbol font and is displayed correctly in the button thanks to a process called font binding (or font indentation that is not yet clear to me).
But in Windows 7, font binding results in a font that does not have this glyph, and surrogate pairs look like two empty fields . Same thing in Windows XP with the Tahoma font.
I want to avoid these replacement boxes by analyzing the text before or after assigning to the button and replacing the missing glyph with some common ASCII character.
I tried to GetGlyphOutline, ScriptGetCMap, GetFontUnicodeRangesand GetGlyphIndices, but they do not support surrogate pairs.
I also tried GetCharacterPlacementUniscribe ScriptItemize+ ScriptShape, which supports surrogate pairs, but all these functions only look for the base HDC font (Segoe UI), they do not end up looking for the fallback font (Symgo UI Symbol), which is the π€ symbol.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink This is the place where I looked, but I really think that there is no system to which fonts will refer.
The question is: how can I find out if system font binding creates the correct glyph or tofu characters?
Edit
- , trom GetCharacterPlacement.
#include <usp10.h>
wchar_t *checkGlyphExist( HWND hwnd, wchar_t *sUnicode, wchar_t *sLimited ) {
HDC hdc = GetDC( hwnd );
HDC metaFileDC = CreateEnhMetaFile( hdc, NULL, NULL, NULL );
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 );
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 );
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 );
if( infoStr.lpGlyphs[0] == 3 ||
infoStr.lpGlyphs[0] == 0 )
return sLimited;
else
return sUnicode;
}
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;
}
checkGlyphExist( hWnd, L"π€", L"<3" );
Windows 10 : Windows 7 Professional, Windows XP SP2.
, - , EnumEnhMetaFile , :
- Windows 7 Microsoft Sans Serif, Symgo UI Symbol.
- Windows XP Tahoma Microsoft Sans Serif, ( BMP- Microsoft Sans Serif, , -, ).
- ?