ReactOS  0.4.15-dev-4594-g505ac65
font.c File Reference
#include "precomp.h"
#include <winuser.h>
#include "settings.h"
#include "font.h"
#include <debug.h>
Include dependency graph for font.c:

Go to the source code of this file.

Classes

struct  _FIND_SUITABLE_FONT_PROC_PARAM
 
struct  _IS_VALID_CONSOLE_FONT_PARAM
 

Macros

#define NDEBUG
 
#define DBGFNT   DPRINT
 
#define DBGFNT1   DPRINT1
 
#define TERMINAL_FACENAME   L"Terminal"
 
#define DEFAULT_NON_DBCS_FONTFACE   L"Lucida Console"
 
#define DEFAULT_TT_FONT_FACENAME   L"__DefaultTTFont__"
 
#define TM_IS_TT_FONT(x)   (((x) & TMPF_TRUETYPE) == TMPF_TRUETYPE)
 
#define SIZE_EQUAL(s1, s2)   (((s1).X == (s2).X) && ((s1).Y == (s2).Y))
 

Typedefs

typedef struct _FIND_SUITABLE_FONT_PROC_PARAM FIND_SUITABLE_FONT_PROC_PARAM
 
typedef struct _FIND_SUITABLE_FONT_PROC_PARAMPFIND_SUITABLE_FONT_PROC_PARAM
 
typedef struct _IS_VALID_CONSOLE_FONT_PARAM IS_VALID_CONSOLE_FONT_PARAM
 
typedef struct _IS_VALID_CONSOLE_FONT_PARAMPIS_VALID_CONSOLE_FONT_PARAM
 

Functions

BYTE CodePageToCharSet (_In_ UINT CodePage)
 Retrieves the character set associated with a given code page. More...
 
static BOOL CALLBACK FindSuitableFontProc (_In_ PLOGFONTW lplf, _In_ PNEWTEXTMETRICW lpntm, _In_ DWORD FontType, _In_ LPARAM lParam)
 EnumFontFamiliesEx() callback helper for FindSuitableFont(). More...
 
static BOOL FindSuitableFont (_Inout_ PFONT_DATA FontData, _In_ UINT CodePage)
 Finds a font suitable for the given code page, based on the current font and its characteristics provided in input. More...
 
static HFONT CreateConsoleFontWorker (_In_ PFONT_DATA FontData, _In_ UINT CodePage)
 Validates and creates a suitable console font based on the font characteristics given in input. More...
 
HFONT CreateConsoleFontEx (_In_ LONG Height, _In_opt_ LONG Width, _Inout_updates_z_(LF_FACESIZE) PWSTR FaceName, _In_ ULONG FontWeight, _In_ ULONG FontFamily, _In_ UINT CodePage, _In_ BOOL UseDefaultFallback, _Out_ PFONT_DATA FontData)
 Validates and creates a suitable console font based on the font characteristics given in input. More...
 
HFONT CreateConsoleFont2 (_In_ LONG Height, _In_opt_ LONG Width, _Inout_ PCONSOLE_STATE_INFO ConsoleInfo)
 A wrapper for CreateConsoleFontEx(). More...
 
HFONT CreateConsoleFont (_Inout_ PCONSOLE_STATE_INFO ConsoleInfo)
 A wrapper for CreateConsoleFontEx(). More...
 
 _Success_ (return)
 Retrieves the cell size for a console font. More...
 
BOOL IsValidConsoleFont2 (_In_ PLOGFONTW lplf, _In_ PNEWTEXTMETRICW lpntm, _In_ DWORD FontType, _In_ UINT CodePage)
 Validates whether a given font can be supported in the console, under the specified code page. More...
 
static BOOL CALLBACK IsValidConsoleFontProc (_In_ PLOGFONTW lplf, _In_ PNEWTEXTMETRICW lpntm, _In_ DWORD FontType, _In_ LPARAM lParam)
 EnumFontFamiliesEx() callback helper for IsValidConsoleFont(). More...
 
BOOL IsValidConsoleFont (_In_ PCWSTR FaceName, _In_ UINT CodePage)
 Validates whether a given font can be supported in the console, under the specified code page. More...
 
VOID InitTTFontCache (VOID)
 Initializes the console TrueType font cache. More...
 
VOID ClearTTFontCache (VOID)
 Clears the console TrueType font cache. More...
 
VOID RefreshTTFontCache (VOID)
 Refreshes the console TrueType font cache, by clearing and re-initializing it. More...
 
PTT_FONT_ENTRY FindCachedTTFont (_In_reads_or_z_opt_(LF_FACESIZE) PCWSTR FaceName, _In_ UINT CodePage)
 Searches for a font in the console TrueType font cache, with the specified code page. More...
 

Variables

SINGLE_LIST_ENTRY TTFontCache = { NULL }
 

Macro Definition Documentation

◆ DBGFNT

#define DBGFNT   DPRINT

Definition at line 21 of file font.c.

◆ DBGFNT1

#define DBGFNT1   DPRINT1

Definition at line 22 of file font.c.

◆ DEFAULT_NON_DBCS_FONTFACE

#define DEFAULT_NON_DBCS_FONTFACE   L"Lucida Console"

Definition at line 28 of file font.c.

◆ DEFAULT_TT_FONT_FACENAME

#define DEFAULT_TT_FONT_FACENAME   L"__DefaultTTFont__"

Definition at line 29 of file font.c.

◆ NDEBUG

#define NDEBUG

Definition at line 18 of file font.c.

◆ SIZE_EQUAL

#define SIZE_EQUAL (   s1,
  s2 
)    (((s1).X == (s2).X) && ((s1).Y == (s2).Y))

Definition at line 78 of file font.c.

◆ TERMINAL_FACENAME

#define TERMINAL_FACENAME   L"Terminal"

Definition at line 27 of file font.c.

◆ TM_IS_TT_FONT

#define TM_IS_TT_FONT (   x)    (((x) & TMPF_TRUETYPE) == TMPF_TRUETYPE)

Definition at line 77 of file font.c.

Typedef Documentation

◆ FIND_SUITABLE_FONT_PROC_PARAM

◆ IS_VALID_CONSOLE_FONT_PARAM

◆ PFIND_SUITABLE_FONT_PROC_PARAM

◆ PIS_VALID_CONSOLE_FONT_PARAM

Function Documentation

◆ _Success_()

_Success_ ( return  )

Retrieves the cell size for a console font.

Parameters
[in,opt]hDC An optional GDI device context handle.
[in]hFontThe GDI handle to the font.
[out]HeightIn case of success, receives the cell height size (in pixels).
[out]WidthIn case of success, receives the cell height size (in pixels).
Returns
TRUE if success, FALSE in case of failure.

Definition at line 686 of file font.c.

693 {
694  BOOL Success = FALSE;
695  HDC hOrgDC = hDC;
696  HFONT hOldFont;
697  // LONG LogSize, PointSize;
699  TEXTMETRICW tm;
700  // SIZE CharSize;
701 
702  if (!hDC)
703  hDC = GetDC(NULL);
704 
705  hOldFont = SelectObject(hDC, hFont);
706  if (hOldFont == NULL)
707  {
708  DBGFNT1("GetFontCellSize: SelectObject failed\n");
709  goto Quit;
710  }
711 
712 /*
713  * See also: Display_SetTypeFace in applications/fontview/display.c
714  */
715 
716  /*
717  * Note that the method with GetObjectW just returns
718  * the original parameters with which the font was created.
719  */
720  if (!GetTextMetricsW(hDC, &tm))
721  {
722  DBGFNT1("GetFontCellSize: GetTextMetrics failed\n");
723  goto Cleanup;
724  }
725 
726  CharHeight = tm.tmHeight + tm.tmExternalLeading;
727 
728 #if 0
729  /* Measure real char width more precisely if possible */
730  if (GetTextExtentPoint32W(hDC, L"R", 1, &CharSize))
731  CharWidth = CharSize.cx;
732 #else
733  CharWidth = tm.tmAveCharWidth; // tm.tmMaxCharWidth;
734 #endif
735 
736 #if 0
737  /*** Logical to Point size ***/
738  LogSize = tm.tmHeight - tm.tmInternalLeading;
739  PointSize = MulDiv(LogSize, 72, GetDeviceCaps(hDC, LOGPIXELSY));
740  /*****************************/
741 #endif
742 
743  *Height = (UINT)CharHeight;
744  *Width = (UINT)CharWidth;
745  Success = TRUE;
746 
747 Cleanup:
748  SelectObject(hDC, hOldFont);
749 Quit:
750  if (!hOrgDC)
751  ReleaseDC(NULL, hDC);
752 
753  return Success;
754 }
BOOL WINAPI GetTextMetricsW(_In_ HDC, _Out_ LPTEXTMETRICW)
Definition: text.c:221
HDC WINAPI GetDC(_In_opt_ HWND)
#define TRUE
Definition: types.h:120
_In_ HFONT _Out_ PUINT _Out_ PUINT Width
Definition: font.h:124
static HDC
Definition: imagelist.c:92
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
_In_ HFONT _Out_ PUINT Height
Definition: font.h:124
INT WINAPI MulDiv(INT nNumber, INT nNumerator, INT nDenominator)
Definition: muldiv.c:25
HFONT hFont
Definition: main.c:53
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
static int CharHeight
Definition: carets.c:8
static int CharWidth
Definition: carets.c:7
int WINAPI GetDeviceCaps(_In_opt_ HDC, _In_ int)
Definition: time.h:68
static const WCHAR Cleanup[]
Definition: register.c:80
static HDC hDC
Definition: 3dtext.c:33
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
#define LOGPIXELSY
Definition: wingdi.h:719
BOOL WINAPI GetTextExtentPoint32W(_In_ HDC hdc, _In_reads_(c) LPCWSTR lpString, _In_ int c, _Out_ LPSIZE psizl)
#define DBGFNT1
Definition: font.c:22

◆ ClearTTFontCache()

VOID ClearTTFontCache ( VOID  )

Clears the console TrueType font cache.

Returns
None.

Definition at line 1131 of file font.c.

1132 {
1134  PTT_FONT_ENTRY FontEntry;
1135 
1136  while (TTFontCache.Next != NULL)
1137  {
1139  FontEntry = CONTAINING_RECORD(Entry, TT_FONT_ENTRY, Entry);
1140  RtlFreeHeap(RtlGetProcessHeap(), 0, FontEntry);
1141  }
1142  TTFontCache.Next = NULL;
1143 }
struct _Entry Entry
Definition: kefuncs.h:629
Definition: ntbasedef.h:628
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
FORCEINLINE PSINGLE_LIST_ENTRY PopEntryList(_Inout_ PSINGLE_LIST_ENTRY ListHead)
Definition: rtlfuncs.h:240
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:629
Definition: font.h:72
#define NULL
Definition: types.h:112
SINGLE_LIST_ENTRY TTFontCache
Definition: font.c:32
base of all file and directory entries
Definition: entries.h:82

Referenced by InitApplet(), and RefreshTTFontCache().

◆ CodePageToCharSet()

BYTE CodePageToCharSet ( _In_ UINT  CodePage)

Retrieves the character set associated with a given code page.

Parameters
[in]CodePageThe code page to convert.
Returns
The character set corresponding to the code page, or DEFAULT_CHARSET.

Definition at line 51 of file font.c.

53 {
54  CHARSETINFO CharInfo;
55  if (TranslateCharsetInfo(UlongToPtr(CodePage), &CharInfo, TCI_SRCCODEPAGE))
56  return (BYTE)CharInfo.ciCharset;
57  else
58  return DEFAULT_CHARSET;
59 }
#define DEFAULT_CHARSET
Definition: wingdi.h:384
UINT ciCharset
Definition: wingdi.h:1546
#define UlongToPtr(u)
Definition: config.h:106
unsigned char BYTE
Definition: xxhash.c:193
BOOL WINAPI TranslateCharsetInfo(LPDWORD lpSrc, LPCHARSETINFO lpCs, DWORD flags)
Definition: font.c:2186
#define TCI_SRCCODEPAGE
Definition: wingdi.h:962

Referenced by CON_API(), CreateConsoleFontWorker(), FindSuitableFont(), and IsValidConsoleFont().

◆ CreateConsoleFont()

HFONT CreateConsoleFont ( _Inout_ PCONSOLE_STATE_INFO  ConsoleInfo)

A wrapper for CreateConsoleFontEx().

Parameters
[in,out]ConsoleInfoA pointer to console settings information, containing in particular (in input) the face name and characteristics of the font to create with the current console code page. In output, the font information gets updated. Note that a default fallback font is always being used in case neither the specified font nor any substitute font could be found and created for the specified code page.
Returns
A GDI handle to the created font, or NULL in case of failure.
See also
CreateConsoleFontEx(), CreateConsoleFont2()

Definition at line 653 of file font.c.

655 {
656  /*
657  * Format:
658  * Width = FontSize.X = LOWORD(FontSize);
659  * Height = FontSize.Y = HIWORD(FontSize);
660  */
661  /* NOTE: FontSize is always in cell height/width units (pixels) */
662  return CreateConsoleFont2((LONG)(ULONG)ConsoleInfo->FontSize.Y,
663  (LONG)(ULONG)ConsoleInfo->FontSize.X,
664  ConsoleInfo);
665 }
long LONG
Definition: pedump.c:60
HFONT CreateConsoleFont2(_In_ LONG Height, _In_opt_ LONG Width, _Inout_ PCONSOLE_STATE_INFO ConsoleInfo)
A wrapper for CreateConsoleFontEx().
Definition: font.c:609
static CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo
Definition: video.c:47
unsigned int ULONG
Definition: retypes.h:1

Referenced by RefreshFontPreview().

◆ CreateConsoleFont2()

HFONT CreateConsoleFont2 ( _In_ LONG  Height,
_In_opt_ LONG  Width,
_Inout_ PCONSOLE_STATE_INFO  ConsoleInfo 
)

A wrapper for CreateConsoleFontEx().

Parameters
[in]HeightThe font height in cell units (pixels).
[in,opt]Width The font width in cell units (pixels).
[in,out]ConsoleInfoA pointer to console settings information, containing in particular (in input) the face name and characteristics of the font to create with the current console code page. In output, the font information gets updated. Note that a default fallback font is always being used in case neither the specified font nor any substitute font could be found and created for the specified code page.
Returns
A GDI handle to the created font, or NULL in case of failure.
See also
CreateConsoleFontEx(), CreateConsoleFont()

Definition at line 609 of file font.c.

613 {
614  FONT_DATA FontData;
615  HFONT hFont;
616 
618  Width,
619  ConsoleInfo->FaceName,
620  ConsoleInfo->FontWeight,
621  ConsoleInfo->FontFamily,
622  ConsoleInfo->CodePage,
623  TRUE, // UseDefaultFallback
624  &FontData);
625  if (hFont)
626  {
627  ConsoleInfo->FontWeight = FontData.Weight;
628  ConsoleInfo->FontFamily = FontData.Family;
629  }
630 
631  return hFont;
632 }
#define TRUE
Definition: types.h:120
_In_ HFONT _Out_ PUINT _Out_ PUINT Width
Definition: font.h:124
_In_ HFONT _Out_ PUINT Height
Definition: font.h:124
HFONT hFont
Definition: main.c:53
HFONT CreateConsoleFontEx(_In_ LONG Height, _In_opt_ LONG Width, _Inout_updates_z_(LF_FACESIZE) PWSTR FaceName, _In_ ULONG FontWeight, _In_ ULONG FontFamily, _In_ UINT CodePage, _In_ BOOL UseDefaultFallback, _Out_ PFONT_DATA FontData)
Validates and creates a suitable console font based on the font characteristics given in input.
Definition: font.c:505
ULONG Family
Definition: font.h:93
ULONG Weight
Definition: font.h:92
static CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo
Definition: video.c:47
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)

Referenced by CreateConsoleFont(), and FontSizeChange().

◆ CreateConsoleFontEx()

HFONT CreateConsoleFontEx ( _In_ LONG  Height,
_In_opt_ LONG  Width,
_Inout_updates_z_(LF_FACESIZE) PWSTR  FaceName,
_In_ ULONG  FontWeight,
_In_ ULONG  FontFamily,
_In_ UINT  CodePage,
_In_ BOOL  UseDefaultFallback,
_Out_ PFONT_DATA  FontData 
)

Validates and creates a suitable console font based on the font characteristics given in input.

Parameters
[in]HeightThe font height in cell units (pixels).
[in,opt]Width The font width in cell units (pixels).
[in,out]FaceNameA pointer to a maximally LF_FACESIZE-sized buffer. In input: The buffer contains the face name of the font to try to create. In output: The buffer receives the face name of the font that has been created, in case of success. It may, or may not be, identical to the face name provided in input, in case a substitute font has been chosen.
[in]FontWeightThe font weight.
[in]FontFamilyThe font family.
[in]CodePageThe code page the font has to support.
[in]UseDefaultFallbackWhether (TRUE) or not (FALSE) to use a default fallback font in case neither the specified font nor any substitute font could be found and created for the specified code page.
[out]FontDataThe face name and characteristics of the created font.
Returns
A GDI handle to the created font, or NULL in case of failure.
Remarks
Similar to FindCreateFont() https://github.com/microsoft/terminal/blob/main/src/propsheet/fontdlg.cpp#L1113 but:
  • does not support an internal font cache for now;
  • returns a font handle (and not a font index to the cache).

Definition at line 505 of file font.c.

515 {
516  HFONT hFont;
517 
518  FontData->FaceName = FaceName;
519  FontData->Weight = FontWeight;
520  FontData->Family = FontFamily;
521  /* NOTE: FontSize is always in cell height/width units (pixels) */
522  FontData->Size.X = Width;
523  FontData->Size.Y = Height;
524  FontData->CharSet = 0; // CodePageToCharSet(CodePage);
525 
526  if (/* !FaceName || */ !*FaceName || wcscmp(FaceName, DEFAULT_TT_FONT_FACENAME) == 0)
527  {
528  /* We do not have an actual font face name yet and should find one.
529  * Call FindSuitableFont() to determine the default font to use. */
530  }
531  else
532  {
533  hFont = CreateConsoleFontWorker(FontData, CodePage);
534  if (hFont)
535  return hFont;
536 
537  DBGFNT1("CreateConsoleFont('%S') failed - Try to find a suitable font...\n",
538  FaceName);
539  }
540 
541  /*
542  * We could not create a font with the default settings.
543  * Try to find a suitable font and retry.
544  */
545  if (!FindSuitableFont(FontData, CodePage))
546  {
547  /* We could not find any suitable font, fall back
548  * to some default one if required to do so. */
549  DBGFNT1("FindSuitableFont could not find anything - %s\n",
550  UseDefaultFallback ? "Falling back to 'Terminal'"
551  : "Bailing out");
552 
553  /* No fallback: no font! */
554  if (!UseDefaultFallback)
555  return NULL;
556 
557  //
558  // FIXME: See also !*FaceName case in FindSuitableFont().
559  //
560  /* Use "Terminal" as the fallback */
562 #if 0
563  // FIXME: CJK font choose workaround: Don't choose Asian
564  // charset font if there is no preferred font for CJK.
565  if (IsCJKCodePage(CodePage))
566  FontData->CharSet = ANSI_CHARSET;
567 #endif
568  FontData->Family &= ~TMPF_TRUETYPE;
569  }
570  else
571  {
572  DBGFNT1("FindSuitableFont found: '%S', size (%d x %d)\n",
573  FaceName, FontData->Size.X, FontData->Size.Y);
574  }
575 
576  /* Retry creating the font */
577  hFont = CreateConsoleFontWorker(FontData, CodePage);
578  if (!hFont)
579  DBGFNT1("CreateConsoleFont('%S') failed\n", FaceName);
580 
581  return hFont;
582 }
#define LF_FACESIZE
Definition: dimm.idl:39
_In_ HFONT _Out_ PUINT _Out_ PUINT Width
Definition: font.h:124
_In_ HFONT _Out_ PUINT Height
Definition: font.h:124
HFONT hFont
Definition: main.c:53
static HFONT CreateConsoleFontWorker(_In_ PFONT_DATA FontData, _In_ UINT CodePage)
Validates and creates a suitable console font based on the font characteristics given in input.
Definition: font.c:424
#define TMPF_TRUETYPE
Definition: wingdi.h:1313
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
static BOOL FindSuitableFont(_Inout_ PFONT_DATA FontData, _In_ UINT CodePage)
Finds a font suitable for the given code page, based on the current font and its characteristics prov...
Definition: font.c:307
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define IsCJKCodePage(CodePage)
Definition: pager.c:42
#define TERMINAL_FACENAME
Definition: font.c:27
#define NULL
Definition: types.h:112
#define DEFAULT_TT_FONT_FACENAME
Definition: font.c:29
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
#define ANSI_CHARSET
Definition: wingdi.h:383
#define DBGFNT1
Definition: font.c:22

Referenced by CreateConsoleFont2(), and InitFonts().

◆ CreateConsoleFontWorker()

static HFONT CreateConsoleFontWorker ( _In_ PFONT_DATA  FontData,
_In_ UINT  CodePage 
)
static

Validates and creates a suitable console font based on the font characteristics given in input.

Parameters
[in]FontDataThe face name and characteristics of the font to create.
[in]CodePageThe code page the font has to support.
Returns
A GDI handle to the created font, or NULL in case of failure.

Definition at line 424 of file font.c.

427 {
428  LOGFONTW lf;
429 
430  RtlZeroMemory(&lf, sizeof(lf));
431 
432  lf.lfHeight = (LONG)(ULONG)FontData->Size.Y;
433  lf.lfWidth = (LONG)(ULONG)FontData->Size.X;
434 
435  lf.lfEscapement = 0;
436  lf.lfOrientation = 0; // TA_BASELINE; // TA_RTLREADING; when the console supports RTL?
437  // lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = FALSE;
438  lf.lfWeight = FontData->Weight;
439  lf.lfCharSet = CodePageToCharSet(CodePage);
443 
444  /* Set the mandatory flags and remove those that we do not support */
445  lf.lfPitchAndFamily = (BYTE)( (FIXED_PITCH | FF_MODERN | FontData->Family) &
447 
448  if (!IsValidConsoleFont(FontData->FaceName, CodePage))
449  return NULL;
450 
452  FontData->FaceName, LF_FACESIZE);
453 
454  return CreateFontIndirectW(&lf);
455 }
HFONT WINAPI CreateFontIndirectW(CONST LOGFONTW *lplf)
Definition: font.c:1803
STRSAFEAPI StringCchCopyNW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc, size_t cchToCopy)
Definition: strsafe.h:236
#define LF_FACESIZE
Definition: dimm.idl:39
BYTE lfPitchAndFamily
Definition: dimm.idl:71
#define VARIABLE_PITCH
Definition: wingdi.h:445
#define DEFAULT_QUALITY
Definition: wingdi.h:436
static LONG(WINAPI *pGdiGetCharDimensions)(HDC hdc
#define FF_DECORATIVE
Definition: wingdi.h:447
BOOL IsValidConsoleFont(_In_ PCWSTR FaceName, _In_ UINT CodePage)
Validates whether a given font can be supported in the console, under the specified code page.
Definition: font.c:974
LONG lfHeight
Definition: dimm.idl:59
BYTE lfCharSet
Definition: dimm.idl:67
BYTE lfClipPrecision
Definition: dimm.idl:69
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
LONG lfEscapement
Definition: dimm.idl:61
#define FIXED_PITCH
Definition: wingdi.h:444
LONG lfOrientation
Definition: dimm.idl:62
#define CLIP_DEFAULT_PRECIS
Definition: wingdi.h:426
LONG lfWidth
Definition: dimm.idl:60
BYTE lfOutPrecision
Definition: dimm.idl:68
BYTE CodePageToCharSet(_In_ UINT CodePage)
Retrieves the character set associated with a given code page.
Definition: font.c:51
#define OUT_DEFAULT_PRECIS
Definition: wingdi.h:415
BYTE lfQuality
Definition: dimm.idl:70
#define FF_ROMAN
Definition: wingdi.h:450
unsigned char BYTE
Definition: xxhash.c:193
#define FF_SWISS
Definition: wingdi.h:452
#define FF_MODERN
Definition: wingdi.h:449
#define NULL
Definition: types.h:112
#define FF_SCRIPT
Definition: wingdi.h:451
WCHAR lfFaceName[LF_FACESIZE]
Definition: dimm.idl:72
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
LONG lfWeight
Definition: dimm.idl:63

Referenced by CreateConsoleFontEx().

◆ FindCachedTTFont()

PTT_FONT_ENTRY FindCachedTTFont ( _In_reads_or_z_opt_(LF_FACESIZE) PCWSTR  FaceName,
_In_ UINT  CodePage 
)

Searches for a font in the console TrueType font cache, with the specified code page.

Parameters
[in,opt]FaceName An optional pointer to a maximally LF_FACESIZE-sized buffer. The buffer contains the face name of the font to search for.
  • If FaceName != NULL, search for the named font that should match the provided code page (when CodePage != INVALID_CP).
  • If FaceName == NULL, search for a font with the provided code page. In this case, CodePage cannot be == INVALID_CP, otherwise the search fails.
Parameters
[in]CodePageThe code page the font has to support, or INVALID_CP when searching a font by face name only.
Returns
A pointer to the cache entry for the font, or NULL if not found.

Definition at line 1183 of file font.c.

1187 {
1189  PTT_FONT_ENTRY FontEntry;
1190 
1191  if (FaceName)
1192  {
1193  /* Search for the named font */
1194  for (Entry = TTFontCache.Next;
1195  Entry != NULL;
1196  Entry = Entry->Next)
1197  {
1198  FontEntry = CONTAINING_RECORD(Entry, TT_FONT_ENTRY, Entry);
1199 
1200  /* NOTE: The font face names are case-sensitive */
1201  if ((wcscmp(FontEntry->FaceName , FaceName) == 0) ||
1202  (wcscmp(FontEntry->FaceNameAlt, FaceName) == 0))
1203  {
1204  /* Return the font if we don't search by code page, or when they match */
1205  if ((CodePage == INVALID_CP) || (CodePage == FontEntry->CodePage))
1206  {
1207  return FontEntry;
1208  }
1209  }
1210  }
1211  }
1212  else if (CodePage != INVALID_CP)
1213  {
1214  /* Search for a font with the specified code page */
1215  for (Entry = TTFontCache.Next;
1216  Entry != NULL;
1217  Entry = Entry->Next)
1218  {
1219  FontEntry = CONTAINING_RECORD(Entry, TT_FONT_ENTRY, Entry);
1220 
1221  /* Return the font if the code pages match */
1222  if (CodePage == FontEntry->CodePage)
1223  return FontEntry;
1224  }
1225  }
1226 
1227  return NULL;
1228 }
struct _Entry Entry
Definition: kefuncs.h:629
Definition: ntbasedef.h:628
UINT CodePage
Definition: font.h:75
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define INVALID_CP
Definition: stream.h:53
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:629
WCHAR FaceName[LF_FACESIZE]
Definition: font.h:77
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
Definition: font.h:72
#define NULL
Definition: types.h:112
WCHAR FaceNameAlt[LF_FACESIZE]
Definition: font.h:78
SINGLE_LIST_ENTRY TTFontCache
Definition: font.c:32
base of all file and directory entries
Definition: entries.h:82

Referenced by FindSuitableFont().

◆ FindSuitableFont()

static BOOL FindSuitableFont ( _Inout_ PFONT_DATA  FontData,
_In_ UINT  CodePage 
)
static

Finds a font suitable for the given code page, based on the current font and its characteristics provided in input.

Parameters
[in,out]FontDataIn input: The face name and characteristics of the font to search for, possibly getting a best match. In output: The face name and characteristics of the suitable font, in case of success.
[in]CodePageThe code page the font has to support.
Returns
TRUE in case a suitable font has been found. Its name and characteristics are returned in FontData. FALSE if no suitable font has been found.

Definition at line 307 of file font.c.

310 {
313  HDC hDC;
314  LOGFONTW lf;
315  PTT_FONT_ENTRY FontEntry;
316 
317  /* Save the original FaceName pointer */
318  FaceName = FontData->FaceName;
319 
320  /* Save our current search criteria */
321  RtlZeroMemory(&Param, sizeof(Param));
322  Param.SearchFont = *FontData;
323 
324  Param.SearchFont.CharSet = CodePageToCharSet(CodePage);
325  Param.CodePage = CodePage;
326 
327  if (/* !FaceName || */ !*FaceName)
328  {
329  /* Find and use a default Raster font */
330 
331  /* Use "Terminal" as the fallback */
333 #if 0
334  // FIXME: CJK font choose workaround: Don't choose Asian
335  // charset font if there is no preferred font for CJK.
336  if (IsCJKCodePage(CodePage))
337  FontData->CharSet = ANSI_CHARSET;
338 #endif
339  FontData->Family &= ~TMPF_TRUETYPE;
340  }
341  else if (wcscmp(FaceName, DEFAULT_TT_FONT_FACENAME) == 0)
342  {
343  /* Find and use a default TrueType font */
344  FontEntry = FindCachedTTFont(NULL, CodePage);
345  if (FontEntry)
346  {
347  StringCchCopyW(FaceName, LF_FACESIZE, FontEntry->FaceName);
348  }
349  else
350  {
352  }
353  FontData->Family |= TMPF_TRUETYPE;
354  }
355 
356  /* Search for a TrueType alternative face name */
357  FontEntry = FindCachedTTFont(FaceName, CodePage);
358  if (FontEntry)
359  {
360  /* NOTE: The font face names are case-sensitive */
361  if (wcscmp(FontEntry->FaceName, FaceName) == 0)
362  Param.AltFaceName = FontEntry->FaceNameAlt;
363  else if (wcscmp(FontEntry->FaceNameAlt, FaceName) == 0)
364  Param.AltFaceName = FontEntry->FaceName;
365  }
366  else
367  {
368  Param.AltFaceName = FaceName;
369  }
370 
371  /* Initialize the search: start with a strict search, then a relaxed one */
372  Param.FontFound = FALSE;
373 
374  Param.StrictSearch = TRUE;
375 SearchAgain:
376  /*
377  * Enumerate all fonts with the given character set.
378  * We will match them with the search criteria.
379  */
380  RtlZeroMemory(&lf, sizeof(lf));
381  lf.lfCharSet = Param.SearchFont.CharSet;
382  // lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
383 
384  hDC = GetDC(NULL);
386  ReleaseDC(NULL, hDC);
387 
388  /* If we failed to find any font, search again with relaxed criteria */
389  if (Param.StrictSearch && !Param.FontFound)
390  {
391  Param.StrictSearch = FALSE;
392  goto SearchAgain;
393  }
394 
395  /* If no font was found again, return failure */
396  if (!Param.FontFound)
397  return FALSE;
398 
399  /* Return the font details */
400  *FontData = Param.CandidateFont;
401  FontData->FaceName = FaceName; // Restore the original FaceName pointer.
402  StringCchCopyNW(FaceName, LF_FACESIZE,
403  Param.CandidateFaceName,
404  ARRAYSIZE(Param.CandidateFaceName));
405 
406  return TRUE;
407 }
int WINAPI EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc, LPARAM lParam, DWORD dwFlags)
Definition: font.c:400
STRSAFEAPI StringCchCopyNW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc, size_t cchToCopy)
Definition: strsafe.h:236
#define LF_FACESIZE
Definition: dimm.idl:39
HDC WINAPI GetDC(_In_opt_ HWND)
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
static BOOL CALLBACK FindSuitableFontProc(_In_ PLOGFONTW lplf, _In_ PNEWTEXTMETRICW lpntm, _In_ DWORD FontType, _In_ LPARAM lParam)
EnumFontFamiliesEx() callback helper for FindSuitableFont().
Definition: font.c:90
BYTE lfCharSet
Definition: dimm.idl:67
static HDC
Definition: imagelist.c:92
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define FALSE
Definition: types.h:117
#define TMPF_TRUETYPE
Definition: wingdi.h:1313
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
LONG_PTR LPARAM
Definition: windef.h:208
BYTE CodePageToCharSet(_In_ UINT CodePage)
Retrieves the character set associated with a given code page.
Definition: font.c:51
WCHAR FaceName[LF_FACESIZE]
Definition: font.h:77
static HDC hDC
Definition: 3dtext.c:33
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
Definition: font.h:72
FARPROC FONTENUMPROCW
Definition: wingdi.h:2897
#define IsCJKCodePage(CodePage)
Definition: pager.c:42
#define TERMINAL_FACENAME
Definition: font.c:27
#define _Inout_updates_z_(size)
Definition: ms_sal.h:389
#define NULL
Definition: types.h:112
#define DEFAULT_TT_FONT_FACENAME
Definition: font.c:29
WCHAR FaceNameAlt[LF_FACESIZE]
Definition: font.h:78
#define DEFAULT_NON_DBCS_FONTFACE
Definition: font.c:28
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
PTT_FONT_ENTRY FindCachedTTFont(_In_reads_or_z_opt_(LF_FACESIZE) PCWSTR FaceName, _In_ UINT CodePage)
Searches for a font in the console TrueType font cache, with the specified code page.
Definition: font.c:1183
#define ANSI_CHARSET
Definition: wingdi.h:383

Referenced by CreateConsoleFontEx().

◆ FindSuitableFontProc()

static BOOL CALLBACK FindSuitableFontProc ( _In_ PLOGFONTW  lplf,
_In_ PNEWTEXTMETRICW  lpntm,
_In_ DWORD  FontType,
_In_ LPARAM  lParam 
)
static

EnumFontFamiliesEx() callback helper for FindSuitableFont().

Remarks
It implements a nearly-identical console-suitable font search algorithm based on the one from FindCreateFont() https://github.com/microsoft/terminal/blob/main/src/propsheet/fontdlg.cpp#L1113 excepting that for now, it does not support an internal font cache.

Definition at line 90 of file font.c.

95 {
97  PFONT_DATA SearchFont = &Param->SearchFont;
98 
99  if (!IsValidConsoleFont2(lplf, lpntm, FontType, Param->CodePage))
100  {
101  /* This font does not suit us; continue enumeration */
102  return TRUE;
103  }
104 
105 #ifndef FONT_CACHE_PRESENT
106  /*
107  * Since we don't cache all the possible font sizes for TrueType fonts,
108  * we cannot check our requested size (and weight) against the enumerated
109  * one; therefore reset the enumerated values to the requested ones.
110  * On the contrary, Raster fonts get their specific font sizes (and weights)
111  * enumerated separately, so for them we can keep the enumerated values.
112  */
113  if (FontType == TRUETYPE_FONTTYPE)
114  {
115  lplf->lfHeight = SearchFont->Size.Y;
116  lplf->lfWidth = 0; // SearchFont->Size.X;
117  lplf->lfWeight = FW_NORMAL;
118  }
119 #endif
120 
121  if (Param->StrictSearch)
122  {
123  /*
124  * Find whether this is an exact match.
125  */
126 
127  /* If looking for a particular family, skip non-matches */
128  if ((SearchFont->Family != 0) &&
129  ((BYTE)SearchFont->Family != (lplf->lfPitchAndFamily & 0xF0)))
130  {
131  /* Continue enumeration */
132  return TRUE;
133  }
134 
135  /* Skip non-matching sizes */
136 #if 0
137  if ((FontInfo[i].SizeWant.Y != Size.Y) &&
138  !SIZE_EQUAL(FontInfo[i].Size, Size))
139 #endif
140  if ((lplf->lfHeight != SearchFont->Size.Y) &&
141  !(lplf->lfWidth == SearchFont->Size.X &&
142  lplf->lfHeight == SearchFont->Size.Y))
143  {
144  /* Continue enumeration */
145  return TRUE;
146  }
147 
148  /* Skip non-matching weights */
149  if ((SearchFont->Weight != 0) &&
150  (SearchFont->Weight != lplf->lfWeight))
151  {
152  /* Continue enumeration */
153  return TRUE;
154  }
155 
156  /* NOTE: We are making the font enumeration at fixed CharSet,
157  * with the one specified in the parameter block. */
158  ASSERT(lplf->lfCharSet == SearchFont->CharSet);
159 
160  if ((FontType != TRUETYPE_FONTTYPE) && // !TM_IS_TT_FONT(lpntm->tmPitchAndFamily)
161  (lplf->lfCharSet != SearchFont->CharSet) &&
162  !(lplf->lfCharSet == OEM_CHARSET && IsCJKCodePage(Param->CodePage))) // g_fEastAsianSystem
163  {
164  /* Continue enumeration */
165  return TRUE;
166  }
167 
168  /*
169  * Size (and maybe family) match. If we don't care about the name or
170  * if it matches, use this font. Otherwise, if name doesn't match and
171  * it is a raster font, consider it.
172  *
173  * NOTE: The font face names are case-sensitive.
174  */
175  if (!SearchFont->FaceName || !*(SearchFont->FaceName) ||
176  (wcscmp(lplf->lfFaceName, SearchFont->FaceName) == 0) ||
177  (wcscmp(lplf->lfFaceName, Param->AltFaceName) == 0))
178  {
179  // FontIndex = i;
180 
181  PFONT_DATA CandidateFont = &Param->CandidateFont;
182 
183  CandidateFont->FaceName = Param->CandidateFaceName;
184  StringCchCopyNW(Param->CandidateFaceName,
185  ARRAYSIZE(Param->CandidateFaceName),
186  lplf->lfFaceName, ARRAYSIZE(lplf->lfFaceName));
187 
188  CandidateFont->Weight = lplf->lfWeight;
189  CandidateFont->Family = (lplf->lfPitchAndFamily & 0xF0);
190 
191  CandidateFont->Size.X = lplf->lfWidth;
192  CandidateFont->Size.Y = lplf->lfHeight;
193 
194  CandidateFont->CharSet = lplf->lfCharSet;
195 
196  /* The font is found, stop enumeration */
197  Param->FontFound = TRUE;
198  return FALSE;
199  }
200  else if (FontType != TRUETYPE_FONTTYPE) // !TM_IS_TT_FONT(lpntm->tmPitchAndFamily)
201  {
202  // FontIndex = i;
203 
204  PFONT_DATA CandidateFont = &Param->CandidateFont;
205 
206  CandidateFont->FaceName = Param->CandidateFaceName;
207  StringCchCopyNW(Param->CandidateFaceName,
208  ARRAYSIZE(Param->CandidateFaceName),
209  lplf->lfFaceName, ARRAYSIZE(lplf->lfFaceName));
210 
211  CandidateFont->Weight = lplf->lfWeight;
212  CandidateFont->Family = (lplf->lfPitchAndFamily & 0xF0);
213 
214  CandidateFont->Size.X = lplf->lfWidth;
215  CandidateFont->Size.Y = lplf->lfHeight;
216 
217  CandidateFont->CharSet = lplf->lfCharSet;
218 
219  /* A close Raster Font fit was found; only the name doesn't match.
220  * Continue enumeration to see whether we can find better. */
221  Param->FontFound = TRUE;
222  }
223  }
224  else // !Param->StrictSearch
225  {
226  /*
227  * Failed to find exact match, even after enumeration, so now
228  * try to find a font of same family and same size or bigger.
229  */
230 
231  if (IsCJKCodePage(Param->CodePage)) // g_fEastAsianSystem
232  {
233  if ((SearchFont->Family != 0) &&
234  ((BYTE)SearchFont->Family != (lplf->lfPitchAndFamily & 0xF0)))
235  {
236  /* Continue enumeration */
237  return TRUE;
238  }
239 
240  if ((FontType != TRUETYPE_FONTTYPE) && // !TM_IS_TT_FONT(lpntm->tmPitchAndFamily)
241  (lplf->lfCharSet != SearchFont->CharSet))
242  {
243  /* Continue enumeration */
244  return TRUE;
245  }
246  }
247  else
248  {
249  if (// (SearchFont->Family != 0) &&
250  ((BYTE)SearchFont->Family != (lplf->lfPitchAndFamily & 0xF0)))
251  {
252  /* Continue enumeration */
253  return TRUE;
254  }
255  }
256 
257  if ((lplf->lfHeight >= SearchFont->Size.Y) &&
258  (lplf->lfWidth >= SearchFont->Size.X))
259  {
260  /* Same family, size >= desired */
261  // FontIndex = i;
262 
263  PFONT_DATA CandidateFont = &Param->CandidateFont;
264 
265  CandidateFont->FaceName = Param->CandidateFaceName;
266  StringCchCopyNW(Param->CandidateFaceName,
267  ARRAYSIZE(Param->CandidateFaceName),
268  lplf->lfFaceName, ARRAYSIZE(lplf->lfFaceName));
269 
270  CandidateFont->Weight = lplf->lfWeight;
271  CandidateFont->Family = (lplf->lfPitchAndFamily & 0xF0);
272 
273  CandidateFont->Size.X = lplf->lfWidth;
274  CandidateFont->Size.Y = lplf->lfHeight;
275 
276  CandidateFont->CharSet = lplf->lfCharSet;
277 
278  /* The font is found, stop enumeration */
279  Param->FontFound = TRUE;
280  return FALSE;
281  }
282  }
283 
284  /* Continue enumeration */
285  return TRUE;
286 }
STRSAFEAPI StringCchCopyNW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc, size_t cchToCopy)
Definition: strsafe.h:236
#define TRUE
Definition: types.h:120
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define FALSE
Definition: types.h:117
#define SIZE_EQUAL(s1, s2)
Definition: font.c:78
ULONG Family
Definition: font.h:93
COORD Size
Definition: font.h:94
ULONG X
Definition: bl.h:1339
#define ASSERT(a)
Definition: mode.c:44
#define OEM_CHARSET
Definition: wingdi.h:400
ULONG Weight
Definition: font.h:92
unsigned char BYTE
Definition: xxhash.c:193
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define IsCJKCodePage(CodePage)
Definition: pager.c:42
#define FW_NORMAL
Definition: wingdi.h:373
struct _FIND_SUITABLE_FONT_PROC_PARAM * PFIND_SUITABLE_FONT_PROC_PARAM
BOOL IsValidConsoleFont2(_In_ PLOGFONTW lplf, _In_ PNEWTEXTMETRICW lpntm, _In_ DWORD FontType, _In_ UINT CodePage)
Validates whether a given font can be supported in the console, under the specified code page.
Definition: font.c:782
BYTE CharSet
Definition: font.h:95
ULONG Y
Definition: bl.h:1340
LPARAM lParam
Definition: combotst.c:139
#define TRUETYPE_FONTTYPE
Definition: wingdi.h:1109

Referenced by FindSuitableFont().

◆ InitTTFontCache()

VOID InitTTFontCache ( VOID  )

Initializes the console TrueType font cache.

Remarks
To install additional TrueType fonts to be available for the console, add entries of type REG_SZ named "0", "00" etc... in: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont The names of the fonts listed there should match those in: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts
Returns
None.

Definition at line 1013 of file font.c.

1014 {
1015  LRESULT lResult;
1016  HKEY hKey;
1017  DWORD dwIndex, dwType;
1018  WCHAR szValueName[MAX_PATH];
1019  DWORD cchValueName;
1020  WCHAR szValue[LF_FACESIZE] = L"";
1021  DWORD cbValue;
1022  UINT CodePage;
1023  PTT_FONT_ENTRY FontEntry;
1024  PWCHAR pszNext;
1025 
1026  if (TTFontCache.Next != NULL)
1027  return;
1028  // TTFontCache.Next = NULL;
1029 
1030  /* Open the Console\TrueTypeFont key */
1031  // "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Console\\TrueTypeFont"
1033  L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Console\\TrueTypeFont",
1034  0,
1036  &hKey) != ERROR_SUCCESS)
1037  {
1038  return;
1039  }
1040 
1041  /* Enumerate all the available TrueType console fonts */
1042  for (dwIndex = 0, cchValueName = ARRAYSIZE(szValueName),
1043  cbValue = sizeof(szValue);
1044  (lResult = RegEnumValueW(hKey, dwIndex,
1045  szValueName, &cchValueName,
1046  NULL, &dwType,
1047  (PBYTE)szValue, &cbValue)) != ERROR_NO_MORE_ITEMS;
1048  ++dwIndex, cchValueName = ARRAYSIZE(szValueName),
1049  cbValue = sizeof(szValue))
1050  {
1051  /* Ignore if we failed for another reason, e.g. because
1052  * the value name is too long (and thus, invalid). */
1053  if (lResult != ERROR_SUCCESS)
1054  continue;
1055 
1056  /* Validate the value name (exclude the unnamed value) */
1057  if (!cchValueName || (*szValueName == UNICODE_NULL))
1058  continue;
1059  /* Too large value names have already been handled with ERROR_MORE_DATA */
1060  ASSERT((cchValueName < ARRAYSIZE(szValueName)) &&
1061  (szValueName[cchValueName] == UNICODE_NULL));
1062 
1063  /* Only (multi-)string values are supported */
1064  if ((dwType != REG_SZ) && (dwType != REG_MULTI_SZ))
1065  continue;
1066 
1067  /* The value name is a code page (in decimal), validate it */
1068  CodePage = wcstoul(szValueName, &pszNext, 10);
1069  if (*pszNext)
1070  continue; // Non-numerical garbage followed...
1071  // IsValidCodePage(CodePage);
1072 
1073  FontEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*FontEntry));
1074  if (!FontEntry)
1075  {
1076  DBGFNT1("InitTTFontCache: Failed to allocate memory, continuing...\n");
1077  continue;
1078  }
1079 
1080  FontEntry->CodePage = CodePage;
1081 
1082  pszNext = szValue;
1083 
1084  /* Check whether bold is disabled for this font */
1085  if (*pszNext == BOLD_MARK)
1086  {
1087  FontEntry->DisableBold = TRUE;
1088  ++pszNext;
1089  }
1090  else
1091  {
1092  FontEntry->DisableBold = FALSE;
1093  }
1094 
1095  /* Copy the font name */
1096  StringCchCopyNW(FontEntry->FaceName, ARRAYSIZE(FontEntry->FaceName),
1097  pszNext, wcslen(pszNext));
1098 
1099  if (dwType == REG_MULTI_SZ)
1100  {
1101  /* There may be an alternate face name as the second string */
1102  pszNext += wcslen(pszNext) + 1;
1103 
1104  /* Check whether bold is disabled for this font */
1105  if (*pszNext == BOLD_MARK)
1106  {
1107  FontEntry->DisableBold = TRUE;
1108  ++pszNext;
1109  }
1110  // else, keep the original setting.
1111 
1112  /* Copy the alternate font name */
1113  StringCchCopyNW(FontEntry->FaceNameAlt, ARRAYSIZE(FontEntry->FaceNameAlt),
1114  pszNext, wcslen(pszNext));
1115  }
1116 
1117  PushEntryList(&TTFontCache, &FontEntry->Entry);
1118  }
1119 
1120  /* Close the key and quit */
1121  RegCloseKey(hKey);
1122 }
STRSAFEAPI StringCchCopyNW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc, size_t cchToCopy)
Definition: strsafe.h:236
#define LF_FACESIZE
Definition: dimm.idl:39
#define ERROR_SUCCESS
Definition: deptool.c:10
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define TRUE
Definition: types.h:120
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
UINT CodePage
Definition: font.h:75
uint16_t * PWCHAR
Definition: typedefs.h:56
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
#define BOLD_MARK
Definition: font.h:70
FORCEINLINE VOID PushEntryList(_Inout_ PSINGLE_LIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PSINGLE_LIST_ENTRY Entry)
Definition: rtlfuncs.h:253
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
#define REG_MULTI_SZ
Definition: nt_native.h:1501
LONG WINAPI RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2853
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
#define ASSERT(a)
Definition: mode.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define MAX_PATH
Definition: compat.h:34
unsigned long DWORD
Definition: ntddk_ex.h:95
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:629
WCHAR FaceName[LF_FACESIZE]
Definition: font.h:77
BOOL DisableBold
Definition: font.h:76
SINGLE_LIST_ENTRY Entry
Definition: font.h:74
Definition: font.h:72
FxAutoRegKey hKey
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
WCHAR FaceNameAlt[LF_FACESIZE]
Definition: font.h:78
SINGLE_LIST_ENTRY TTFontCache
Definition: font.c:32
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3356
LONG_PTR LRESULT
Definition: windef.h:209
BYTE * PBYTE
Definition: pedump.c:66
#define RegCloseKey(hKey)
Definition: registry.h:47
#define DBGFNT1
Definition: font.c:22
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define REG_SZ
Definition: layer.c:22

Referenced by GuiInit(), InitApplet(), and RefreshTTFontCache().

◆ IsValidConsoleFont()

BOOL IsValidConsoleFont ( _In_ PCWSTR  FaceName,
_In_ UINT  CodePage 
)

Validates whether a given font can be supported in the console, under the specified code page.

Parameters
[in]FaceNameThe face name of the font to validate.
[in]CodePageThe code page the font has to support.
Returns
TRUE if the font is valid and supported in the console, FALSE if not.
See also
IsValidConsoleFont2()

Definition at line 974 of file font.c.

978 {
980  HDC hDC;
981  LOGFONTW lf;
982 
983  Param.IsValidFont = FALSE;
984  Param.CodePage = CodePage;
985 
986  RtlZeroMemory(&lf, sizeof(lf));
987  lf.lfCharSet = CodePageToCharSet(CodePage);
988  // lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
989  StringCchCopyW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), FaceName);
990 
991  hDC = GetDC(NULL);
993  ReleaseDC(NULL, hDC);
994 
995  return Param.IsValidFont;
996 }
int WINAPI EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc, LPARAM lParam, DWORD dwFlags)
Definition: font.c:400
HDC WINAPI GetDC(_In_opt_ HWND)
static BOOL CALLBACK IsValidConsoleFontProc(_In_ PLOGFONTW lplf, _In_ PNEWTEXTMETRICW lpntm, _In_ DWORD FontType, _In_ LPARAM lParam)
EnumFontFamiliesEx() callback helper for IsValidConsoleFont().
Definition: font.c:943
BYTE lfCharSet
Definition: dimm.idl:67
static HDC
Definition: imagelist.c:92
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define FALSE
Definition: types.h:117
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
LONG_PTR LPARAM
Definition: windef.h:208
BYTE CodePageToCharSet(_In_ UINT CodePage)
Retrieves the character set associated with a given code page.
Definition: font.c:51
static HDC hDC
Definition: 3dtext.c:33
FARPROC FONTENUMPROCW
Definition: wingdi.h:2897
#define NULL
Definition: types.h:112
WCHAR lfFaceName[LF_FACESIZE]
Definition: dimm.idl:72
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by CreateConsoleFontWorker().

◆ IsValidConsoleFont2()

BOOL IsValidConsoleFont2 ( _In_ PLOGFONTW  lplf,
_In_ PNEWTEXTMETRICW  lpntm,
_In_ DWORD  FontType,
_In_ UINT  CodePage 
)

Validates whether a given font can be supported in the console, under the specified code page.

Parameters
[in]lplf
[in]lpntm
[in]FontTypeThe GDI font characteristics of the font to validate.
[in]CodePageThe code page the font has to support.
Returns
TRUE if the font is valid and supported in the console, FALSE if not.
Remarks
Equivalent of the font validation tests in FontEnumForV2Console() (or the more restrictive ones in FontEnum()) https://github.com/microsoft/terminal/blob/main/src/propsheet/misc.cpp#L465 https://github.com/microsoft/terminal/blob/main/src/propsheet/misc.cpp#L607
See also
IsValidConsoleFont()

Definition at line 782 of file font.c.

787 {
788  LPCWSTR FaceName = lplf->lfFaceName;
789 
790  /*
791  * According to: https://web.archive.org/web/20140901124501/http://support.microsoft.com/kb/247815
792  * "Necessary criteria for fonts to be available in a command window",
793  * the criteria for console-eligible fonts are as follows:
794  * - The font must be a fixed-pitch font.
795  * - The font cannot be an italic font.
796  * - The font cannot have a negative A or C space.
797  * - If it is a TrueType font, it must be FF_MODERN.
798  * - If it is not a TrueType font, it must be OEM_CHARSET.
799  *
800  * Non documented: vertical fonts are forbidden (their name start with a '@').
801  *
802  * Additional criteria for Asian installations:
803  * - If it is not a TrueType font, the face name must be "Terminal".
804  * - If it is an Asian TrueType font, it must also be an Asian character set.
805  *
806  * See also Raymond Chen's blog: https://devblogs.microsoft.com/oldnewthing/?p=26843
807  * and MIT-licensed Microsoft Terminal source code: https://github.com/microsoft/terminal/blob/main/src/propsheet/misc.cpp
808  * for other details.
809  *
810  * To install additional TrueType fonts to be available for the console,
811  * add entries of type REG_SZ named "0", "00" etc... in:
812  * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont
813  * The names of the fonts listed there should match those in:
814  * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts
815  */
816 
817  /*
818  * In ReactOS we relax some of the criteria:
819  * - We allow fixed-pitch FF_MODERN (Monospace) TrueType fonts
820  * that can be italic or have negative A or C space.
821  * - If it is not a TrueType font, it can be from another character set
822  * than OEM_CHARSET. When an Asian codepage is active however, we require
823  * that this non-TrueType font has an Asian character set.
824  */
825 
826  /* Reject variable-width fonts ... */
827  if ( ( ((lplf->lfPitchAndFamily & 0x03) != FIXED_PITCH)
828 #if 0 /* Reject italic and TrueType fonts with negative A or C space ... */
829  || (lplf->lfItalic)
830  || !(lpntm->ntmFlags & NTM_NONNEGATIVE_AC)
831 #endif
832  ) &&
833  /* ... if they are not in the list of additional TrueType fonts to include */
834  !IsAdditionalTTFont(FaceName) )
835  {
836  DBGFNT("Font '%S' rejected because it%s (lfPitchAndFamily = %d)\n",
837  FaceName,
838  !(lplf->lfPitchAndFamily & FIXED_PITCH) ? "'s not FIXED_PITCH"
839  : (!(lpntm->ntmFlags & NTM_NONNEGATIVE_AC) ? " has negative A or C space"
840  : " is broken"),
841  lplf->lfPitchAndFamily);
842  return FALSE;
843  }
844 
845  /* Reject TrueType fonts that are not FF_MODERN */
846  if ((FontType == TRUETYPE_FONTTYPE) && ((lplf->lfPitchAndFamily & 0xF0) != FF_MODERN))
847  {
848  DBGFNT("TrueType font '%S' rejected because it's not FF_MODERN (lfPitchAndFamily = %d)\n",
849  FaceName, lplf->lfPitchAndFamily);
850  return FALSE;
851  }
852 
853  /* Reject vertical fonts (tategaki) */
854  if (FaceName[0] == L'@')
855  {
856  DBGFNT("Font '%S' rejected because it's vertical\n", FaceName);
857  return FALSE;
858  }
859 
860  /* Is the current code page Chinese, Japanese or Korean? */
861  if (IsCJKCodePage(CodePage))
862  {
863  /* It's CJK */
864 
865  if (FontType == TRUETYPE_FONTTYPE)
866  {
867  /*
868  * Here we are inclusive and check for any CJK character set,
869  * instead of looking just at the current one via CodePageToCharSet().
870  */
871  if (!IsCJKCharSet(lplf->lfCharSet))
872  {
873  DBGFNT("TrueType font '%S' rejected because it's not Asian charset (lfCharSet = %d)\n",
874  FaceName, lplf->lfCharSet);
875  return FALSE;
876  }
877 
878  /*
879  * If this is a cached TrueType font that is used only for certain
880  * code pages, verify that the charset it claims is the correct one.
881  *
882  * Since there may be multiple entries for a cached TrueType font,
883  * a general one (code page == 0) and one or more for explicit
884  * code pages, we need to perform two search queries instead of
885  * just one and retrieving the code page for this entry.
886  */
887  if (IsAdditionalTTFont(FaceName) && !IsAdditionalTTFontCP(FaceName, 0) &&
888  !IsCJKCharSet(lplf->lfCharSet))
889  {
890  DBGFNT("Cached TrueType font '%S' rejected because it claims a code page that is not Asian charset (lfCharSet = %d)\n",
891  FaceName, lplf->lfCharSet);
892  return FALSE;
893  }
894  }
895  else
896  {
897  /* Reject non-TrueType fonts that do not have an Asian character set */
898  if (!IsCJKCharSet(lplf->lfCharSet) && (lplf->lfCharSet != OEM_CHARSET))
899  {
900  DBGFNT("Non-TrueType font '%S' rejected because it's not Asian charset or OEM_CHARSET (lfCharSet = %d)\n",
901  FaceName, lplf->lfCharSet);
902  return FALSE;
903  }
904 
905  /* Reject non-TrueType fonts that are not Terminal */
906  if (wcscmp(FaceName, TERMINAL_FACENAME) != 0)
907  {
908  DBGFNT("Non-TrueType font '%S' rejected because it's not 'Terminal'\n", FaceName);
909  return FALSE;
910  }
911  }
912  }
913  else
914  {
915  /* Not CJK */
916 
917  /* Reject non-TrueType fonts that are not OEM or similar */
918  if ((FontType != TRUETYPE_FONTTYPE) &&
919  (lplf->lfCharSet != ANSI_CHARSET) &&
920  (lplf->lfCharSet != DEFAULT_CHARSET) &&
921  (lplf->lfCharSet != OEM_CHARSET))
922  {
923  DBGFNT("Non-TrueType font '%S' rejected because it's not ANSI_CHARSET or DEFAULT_CHARSET or OEM_CHARSET (lfCharSet = %d)\n",
924  FaceName, lplf->lfCharSet);
925  return FALSE;
926  }
927  }
928 
929  /* All good */
930  return TRUE;
931 }
#define IsCJKCharSet(CharSet)
Definition: font.h:54
#define NTM_NONNEGATIVE_AC
Definition: wingdi.h:25
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define TRUE
Definition: types.h:120
#define DBGFNT
Definition: font.c:21
#define DEFAULT_CHARSET
Definition: wingdi.h:384
#define IsAdditionalTTFont(FaceName)
Verifies whether the given font is an additional console TrueType font. Wrapper macros around FindCac...
Definition: font.h:168
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
#define FIXED_PITCH
Definition: wingdi.h:444
#define OEM_CHARSET
Definition: wingdi.h:400
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define IsCJKCodePage(CodePage)
Definition: pager.c:42
#define TERMINAL_FACENAME
Definition: font.c:27
#define FF_MODERN
Definition: wingdi.h:449
#define ANSI_CHARSET
Definition: wingdi.h:383
#define TRUETYPE_FONTTYPE
Definition: wingdi.h:1109
#define IsAdditionalTTFontCP(FaceName, CodePage)
Definition: font.h:171

Referenced by EnumFaceNamesProc(), FindSuitableFontProc(), and IsValidConsoleFontProc().

◆ IsValidConsoleFontProc()

static BOOL CALLBACK IsValidConsoleFontProc ( _In_ PLOGFONTW  lplf,
_In_ PNEWTEXTMETRICW  lpntm,
_In_ DWORD  FontType,
_In_ LPARAM  lParam 
)
static

EnumFontFamiliesEx() callback helper for IsValidConsoleFont().

Definition at line 943 of file font.c.

948 {
950  Param->IsValidFont = IsValidConsoleFont2(lplf, lpntm, FontType, Param->CodePage);
951 
952  /* Stop the enumeration now */
953  return FALSE;
954 }
#define FALSE
Definition: types.h:117
struct _IS_VALID_CONSOLE_FONT_PARAM * PIS_VALID_CONSOLE_FONT_PARAM
BOOL IsValidConsoleFont2(_In_ PLOGFONTW lplf, _In_ PNEWTEXTMETRICW lpntm, _In_ DWORD FontType, _In_ UINT CodePage)
Validates whether a given font can be supported in the console, under the specified code page.
Definition: font.c:782
LPARAM lParam
Definition: combotst.c:139

Referenced by IsValidConsoleFont().

◆ RefreshTTFontCache()

VOID RefreshTTFontCache ( VOID  )

Refreshes the console TrueType font cache, by clearing and re-initializing it.

Returns
None.

Definition at line 1153 of file font.c.

1154 {
1155  ClearTTFontCache();
1156  InitTTFontCache();
1157 }
VOID InitTTFontCache(VOID)
Initializes the console TrueType font cache.
Definition: font.c:1013
VOID ClearTTFontCache(VOID)
Clears the console TrueType font cache.
Definition: font.c:1131

Referenced by GuiApplyUserSettings().

Variable Documentation

◆ TTFontCache

SINGLE_LIST_ENTRY TTFontCache = { NULL }

Definition at line 32 of file font.c.

Referenced by ClearTTFontCache(), FindCachedTTFont(), and InitTTFontCache().