Check if Unicode or Tofu Symbol Is Displayed

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 ) {

    // 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;
}

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, , -, ).

- ?

+6
2

, API Win7, Win10. gdi32 API , , DirectWrite . , , , ( - ), ​​ , , , .

-, , Win7 U + 1F5A4, , .

, , , , , , . DirectWrite , , , U + 1F5A4 , , , , .

, , .

+1

, 16- . , 16- .

0xd800 0xdbff 0xdc00 0xdfff

"" , .

. UTF-16.

-3

All Articles