[CONSOLE][CONCFG][CONSRV] Provide support for specified additional TrueType fonts + bugfixes.

CORE-12451 CORE-13182 CORE-13196

- CONSOLE: Initialize the additional TrueType fonts cache.
  * Fix the font preview when a TrueType font has been selected.
  * Refresh the available fonts and the font preview when the selected
    code page is changed (Work In Progress), or when the OS pool of
    font resources has changed (WM_FONTCHANGE message).

- CONCFG: Implement support for the additional TrueType fonts cache:
  the contents of the cache is enumerated under the registry key
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont

  * Add helper functions and macros.
  * In CreateConsoleFontEx(), set the mandatory font pitch&family flags
    and remove those that we do not support.
  * In IsValidConsoleFont2(), update the validity checks and the
    documentation links.

- CONSRV: Load/refresh the additional TrueType fonts cache when needed.
This commit is contained in:
Hermès Bélusca-Maïto 2019-05-19 22:55:14 +02:00
parent 73d7fd1415
commit c4e2826c73
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
11 changed files with 497 additions and 108 deletions

View file

@ -227,11 +227,9 @@ InitApplet(HANDLE hSectionOrWnd)
InitDefaultConsoleInfo(ConInfo);
}
/* Initialize the font support */
FontPreview.hFont = CreateConsoleFont(ConInfo);
if (FontPreview.hFont == NULL)
DPRINT1("InitApplet: CreateConsoleFont() failed\n");
GetFontCellSize(NULL, FontPreview.hFont, &FontPreview.CharHeight, &FontPreview.CharWidth);
/* Initialize the font support -- additional TrueType fonts cache and current preview font */
InitTTFontCache();
RefreshFontPreview(&FontPreview, ConInfo);
/* Initialize the property sheet structure */
ZeroMemory(&psh, sizeof(psh));
@ -274,8 +272,8 @@ InitApplet(HANDLE hSectionOrWnd)
UnRegisterWinPrevClass(hApplet);
/* Clear the font support */
if (FontPreview.hFont) DeleteObject(FontPreview.hFont);
FontPreview.hFont = NULL;
ResetFontPreview(&FontPreview);
ClearTTFontCache();
/* Save the console settings */
if (SetConsoleInfo)

View file

@ -49,6 +49,23 @@ extern FONT_PREVIEW FontPreview;
VOID ApplyConsoleInfo(HWND hwndDlg);
VOID
RefreshFontPreview(
IN FONT_PREVIEW* Preview,
IN PCONSOLE_STATE_INFO pConInfo);
VOID
UpdateFontPreview(
IN FONT_PREVIEW* Preview,
IN HFONT hFont,
IN UINT CharWidth,
IN UINT CharHeight);
#define ResetFontPreview(Preview) \
UpdateFontPreview((Preview), NULL, 0, 0)
/* Preview Windows */
BOOL
RegisterWinPrevClass(

View file

@ -45,6 +45,31 @@ static INT CurrentSelFont = LB_ERR;
static DWORD CurrentFontType = (DWORD)-1; // Invalid font type
VOID
RefreshFontPreview(
IN FONT_PREVIEW* Preview,
IN PCONSOLE_STATE_INFO pConInfo)
{
if (Preview->hFont) DeleteObject(Preview->hFont);
Preview->hFont = CreateConsoleFont(pConInfo);
if (Preview->hFont == NULL)
DPRINT1("RefreshFontPreview: CreateConsoleFont() failed\n");
GetFontCellSize(NULL, Preview->hFont, &Preview->CharHeight, &Preview->CharWidth);
}
VOID
UpdateFontPreview(
IN FONT_PREVIEW* Preview,
IN HFONT hFont,
IN UINT CharWidth,
IN UINT CharHeight)
{
if (Preview->hFont) DeleteObject(Preview->hFont);
Preview->hFont = hFont;
Preview->CharWidth = CharWidth;
Preview->CharHeight = CharHeight;
}
// PLIST_GETCOUNT
static INT
RasterSizeList_GetCount(
@ -284,13 +309,6 @@ EnumFaceNamesProc(
{
PFACE_NAMES_PROC_PARAM Param = (PFACE_NAMES_PROC_PARAM)lParam;
/*
* 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
*/
if (IsValidConsoleFont2(lplf, lpntm, FontType, Param->CodePage))
{
/* Add the font to the list */
@ -374,7 +392,7 @@ FaceNameList_Initialize(
ZeroMemory(&lf, sizeof(lf));
lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(CodePage);
// lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
// lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
hDC = GetDC(NULL);
EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFaceNamesProc, (LPARAM)&Param, 0);
@ -397,9 +415,14 @@ FaceNameList_Initialize(
}
static VOID
FaceNameList_SelectFaceName(
FaceNameList_SelectFont(
IN HWND hDlg,
IN HWND hWndList,
IN LPCWSTR FaceName)
IN PFONTSIZE_LIST_CTL SizeList,
IN LPCWSTR FaceName,
IN ULONG FontFamily,
IN ULONG FontWeight,
IN COORD FontSize)
{
INT iItem;
@ -410,6 +433,21 @@ FaceNameList_SelectFaceName(
iItem = 0;
SendMessageW(hWndList, LB_SETCURSEL, (WPARAM)iItem, 0);
if (FontWeight >= FW_BOLD)
CheckDlgButton(hDlg, IDC_CHECK_BOLD_FONTS, BST_CHECKED);
else
CheckDlgButton(hDlg, IDC_CHECK_BOLD_FONTS, BST_UNCHECKED);
/* Select the current font size */
/*
* Format:
* Width = FontSize.X = LOWORD(FontSize);
* Height = FontSize.Y = HIWORD(FontSize);
*/
SizeList->CurrentRasterSize = MAKELONG(FontSize.X, FontSize.Y);
SizeList->CurrentTTSize = FontSize.Y;
// FontSizeList_SelectFontSize(SizeList, SizeList->CurrentRasterSize);
// return iItem;
}
@ -486,7 +524,6 @@ FontTypeChange(
{
HWND hListBox = GetDlgItem(hDlg, IDC_LBOX_FONTTYPE);
INT Length, nSel;
LOGFONTW lf;
LPWSTR FaceName;
DWORD FontType;
LPCWSTR FontGrpBoxLabelTpl = NULL;
@ -518,12 +555,7 @@ FontTypeChange(
FaceName[Length] = L'\0';
StringCchCopyW(pConInfo->FaceName, ARRAYSIZE(pConInfo->FaceName), FaceName);
DPRINT1("pConInfo->FaceName = '%S'\n", pConInfo->FaceName);
ZeroMemory(&lf, sizeof(lf));
lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(pConInfo->CodePage);
// lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
StringCchCopyW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), FaceName);
DPRINT("pConInfo->FaceName = '%S'\n", pConInfo->FaceName);
/*
* Retrieve the read-only font group box label string template,
@ -560,6 +592,7 @@ FontTypeChange(
if ((CurrentFontType != FontType) ||
(FontType == RASTER_FONTTYPE && CurrentSelFont != nSel))
{
LOGFONTW lf;
HDC hDC;
if (SizeList->UseRasterOrTTList)
@ -567,6 +600,11 @@ FontTypeChange(
else
SendMessageW(SizeList->hWndTTSizeList, CB_RESETCONTENT, 0, 0);
ZeroMemory(&lf, sizeof(lf));
lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(pConInfo->CodePage);
// lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
StringCchCopyW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), pConInfo->FaceName);
hDC = GetDC(NULL);
EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFontSizesProc, (LPARAM)SizeList, 0);
ReleaseDC(NULL, hDC);
@ -597,7 +635,9 @@ FontSizeChange(
IN PFONTSIZE_LIST_CTL SizeList,
IN OUT PCONSOLE_STATE_INFO pConInfo)
{
LONG FontSize, CharWidth, CharHeight;
LONG FontSize;
UINT CharWidth, CharHeight;
HFONT hFont;
WCHAR szFontSize[100];
/*
@ -610,35 +650,44 @@ FontSizeChange(
if (FontSize == 0)
return FALSE; // We have got an invalid font size...
CharHeight = (SizeList->UseRasterOrTTList ? (LONG)HIWORD(FontSize) : FontSize);
CharWidth = (SizeList->UseRasterOrTTList ? (LONG)LOWORD(FontSize) : 0);
/*
* For TrueType fonts we set the requested width to zero
* so as to obtain a default aspect-ratio width.
*/
CharHeight = (UINT)(SizeList->UseRasterOrTTList ? HIWORD(FontSize) : FontSize);
CharWidth = (UINT)(SizeList->UseRasterOrTTList ? LOWORD(FontSize) : 0);
if (FontPreview.hFont) DeleteObject(FontPreview.hFont);
FontPreview.hFont = CreateConsoleFont2(CharHeight, CharWidth, pConInfo);
if (FontPreview.hFont == NULL)
hFont = CreateConsoleFont2((LONG)CharHeight, (LONG)CharWidth, pConInfo);
if (hFont == NULL)
DPRINT1("FontSizeChange: CreateConsoleFont2() failed\n");
/* Retrieve the real character size in pixels */
GetFontCellSize(NULL, FontPreview.hFont, &FontPreview.CharHeight, &FontPreview.CharWidth);
GetFontCellSize(NULL, hFont, &CharHeight, &CharWidth);
/*
* Update the font preview as well, and store the font handle. It will be
* freed at later update or when the font preview is refreshed or reset.
* For TrueType fonts, the preview will show the actual character width.
*/
UpdateFontPreview(&FontPreview, hFont, CharWidth, CharHeight);
/*
* Format:
* Width = FontSize.X = LOWORD(FontSize);
* Height = FontSize.Y = HIWORD(FontSize);
*/
pConInfo->FontSize.X = (SHORT)(SizeList->UseRasterOrTTList ? FontPreview.CharWidth : 0);
pConInfo->FontSize.Y = (SHORT)FontPreview.CharHeight;
pConInfo->FontSize.X = (SHORT)(SizeList->UseRasterOrTTList ? CharWidth : 0);
pConInfo->FontSize.Y = (SHORT)CharHeight;
DPRINT1("pConInfo->FontSize = (%d x %d) ; (CharWidth x CharHeight) = (%d x %d)\n",
pConInfo->FontSize.X, pConInfo->FontSize.Y,
FontPreview.CharWidth, FontPreview.CharHeight);
DPRINT("pConInfo->FontSize = (%d x %d) ; (CharWidth x CharHeight) = (%d x %d)\n",
pConInfo->FontSize.X, pConInfo->FontSize.Y, CharWidth, CharHeight);
InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_FONT_WINDOW_PREVIEW), NULL, TRUE);
InvalidateRect(GetDlgItem(hDlg, IDC_STATIC_SELECT_FONT_PREVIEW), NULL, TRUE);
StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", FontPreview.CharWidth);
StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", CharWidth);
SetDlgItemText(hDlg, IDC_FONT_SIZE_X, szFontSize);
StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", FontPreview.CharHeight);
StringCchPrintfW(szFontSize, ARRAYSIZE(szFontSize), L"%d", CharHeight);
SetDlgItemText(hDlg, IDC_FONT_SIZE_Y, szFontSize);
return TRUE;
@ -689,22 +738,12 @@ FontProc(HWND hDlg,
/* Select the current font */
DPRINT1("ConInfo->FaceName = '%S'\n", ConInfo->FaceName);
FaceNameList_SelectFaceName(hFontList, ConInfo->FaceName);
if (ConInfo->FontWeight >= FW_BOLD)
CheckDlgButton(hDlg, IDC_CHECK_BOLD_FONTS, BST_CHECKED);
else
CheckDlgButton(hDlg, IDC_CHECK_BOLD_FONTS, BST_UNCHECKED);
/* Select the current font size */
/*
* Format:
* Width = FontSize.X = LOWORD(FontSize);
* Height = FontSize.Y = HIWORD(FontSize);
*/
SizeList->CurrentRasterSize = MAKELONG(ConInfo->FontSize.X, ConInfo->FontSize.Y);
SizeList->CurrentTTSize = ConInfo->FontSize.Y;
// FontSizeList_SelectFontSize(SizeList, SizeList->CurrentRasterSize);
FaceNameList_SelectFont(hDlg, hFontList,
SizeList,
ConInfo->FaceName,
ConInfo->FontFamily,
ConInfo->FontWeight,
ConInfo->FontSize);
/* Refresh everything */
FontTypeChange(hDlg, SizeList, ConInfo);
@ -737,6 +776,42 @@ FontProc(HWND hDlg,
break;
}
#if 0
case PSM_QUERYSIBLINGS:
{
/*
* If this is a notification from the "Options" dialog because we
* changed the code page, treat it using the WM_FONTCHANGE case,
* otherwise ignore it.
*/
if (wParam != IDL_CODEPAGE)
return FALSE;
/* Fall through */
}
#endif
case WM_FONTCHANGE:
{
/* The pool of font resources has changed, re-enumerate the fonts */
HWND hFontList = GetDlgItem(hDlg, IDC_LBOX_FONTTYPE);
/* Initialize the font list */
FaceNameList_Initialize(hFontList, ConInfo->CodePage);
/* Select the current font */
FaceNameList_SelectFont(hDlg, hFontList,
SizeList,
ConInfo->FaceName,
ConInfo->FontFamily,
ConInfo->FontWeight,
ConInfo->FontSize);
/* Refresh everything */
FontTypeChange(hDlg, SizeList, ConInfo);
break;
}
case WM_NOTIFY:
{
switch (((LPNMHDR)lParam)->code)

View file

@ -203,6 +203,9 @@ WinPrev_OnDraw(
* Compute the console window layout
*/
if (FontPreview.hFont == NULL)
RefreshFontPreview(&FontPreview, pConInfo);
/* We start with the console client area, rescaled for the preview */
SetRect(&rcWin, 0, 0,
pConInfo->WindowSize.X * FontPreview.CharWidth,
@ -489,6 +492,9 @@ PaintText(
hBrush = CreateSolidBrush(nbkColor);
if (!hBrush) return;
if (FontPreview.hFont == NULL)
RefreshFontPreview(&FontPreview, pConInfo);
hOldFont = SelectObject(drawItem->hDC, FontPreview.hFont);
//if (hOldFont == NULL)
//{

View file

@ -72,7 +72,8 @@ AddCodePage(
static VOID
BuildCodePageList(
IN HWND hDlg)
IN HWND hDlg,
IN UINT CurrentCodePage)
{
LIST_CTL ListCtl;
HKEY hKey;
@ -126,7 +127,7 @@ BuildCodePageList(
AddCodePage(&ListCtl, CP_UTF8);
/* Find and select the current code page in the sorted list */
if (BisectListSortedByValue(&ListCtl, ConInfo->CodePage, &CodePage, FALSE) == CB_ERR ||
if (BisectListSortedByValue(&ListCtl, CurrentCodePage, &CodePage, FALSE) == CB_ERR ||
CodePage == CB_ERR)
{
/* Not found, select the first element */
@ -212,7 +213,7 @@ OptionsProc(HWND hDlg,
{
case WM_INITDIALOG:
{
BuildCodePageList(hDlg);
BuildCodePageList(hDlg, ConInfo->CodePage);
UpdateDialogElements(hDlg, ConInfo);
return TRUE;
}
@ -332,6 +333,7 @@ OptionsProc(HWND hDlg,
}
}
else
// (HIWORD(wParam) == CBN_KILLFOCUS)
if ((HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == CBN_SELENDOK) &&
(LOWORD(wParam) == IDL_CODEPAGE))
{
@ -347,11 +349,15 @@ OptionsProc(HWND hDlg,
if (CodePage == CB_ERR)
break;
ConInfo->CodePage = CodePage;
/* Change the property sheet state only if the user validated */
if (HIWORD(wParam) == CBN_SELENDOK)
/* If the user validated a different code page... */
if ((HIWORD(wParam) == CBN_SELENDOK) && (CodePage != ConInfo->CodePage))
{
/* ... update the code page, notify the siblings and change the property sheet state */
ConInfo->CodePage = CodePage;
// PropSheet_QuerySiblings(GetParent(hDlg), IDL_CODEPAGE, 0);
ResetFontPreview(&FontPreview);
PropSheet_Changed(GetParent(hDlg), hDlg);
}
}
break;

View file

@ -20,6 +20,11 @@
#include <debug.h>
/* GLOBALS ********************************************************************/
// RTL_STATIC_LIST_HEAD(TTFontCache);
LIST_ENTRY TTFontCache = {&TTFontCache, &TTFontCache};
/* FUNCTIONS ******************************************************************/
/* Retrieves the character set associated with a given code page */
@ -58,7 +63,10 @@ CreateConsoleFontEx(
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfPitchAndFamily = (BYTE)(FIXED_PITCH | FontFamily);
/* Set the mandatory flags and remove those that we do not support */
lf.lfPitchAndFamily = (BYTE)( (FIXED_PITCH | FF_MODERN | FontFamily) &
~(VARIABLE_PITCH | FF_DECORATIVE | FF_ROMAN | FF_SCRIPT | FF_SWISS));
if (!IsValidConsoleFont(FaceName, CodePage))
StringCchCopyW(FaceName, LF_FACESIZE, L"Terminal");
@ -179,13 +187,10 @@ IsValidConsoleFont2(
{
LPCWSTR FaceName = lplf->lfFaceName;
/* Record the font's attributes (Fixedwidth and Truetype) */
// BOOL fFixed = ((lplf->lfPitchAndFamily & 0x03) == FIXED_PITCH);
// BOOL fTrueType = (lplf->lfOutPrecision == OUT_STROKE_PRECIS);
/*
* According to: http://support.microsoft.com/kb/247815
* the criteria for console-eligible fonts are:
* According to: https://web.archive.org/web/20140901124501/http://support.microsoft.com/kb/247815
* "Necessary criteria for fonts to be available in a command window",
* the criteria for console-eligible fonts are as follows:
* - The font must be a fixed-pitch font.
* - The font cannot be an italic font.
* - The font cannot have a negative A or C space.
@ -198,6 +203,10 @@ IsValidConsoleFont2(
* - If it is not a TrueType font, the face name must be "Terminal".
* - If it is an Asian TrueType font, it must also be an Asian character set.
*
* See also Raymond Chen's blog: https://devblogs.microsoft.com/oldnewthing/?p=26843
* and MIT-licensed Microsoft Terminal source code: https://github.com/microsoft/Terminal/blob/master/src/propsheet/misc.cpp
* for other details.
*
* 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
@ -205,27 +214,30 @@ IsValidConsoleFont2(
* HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts
*/
/*
* In ReactOS we relax some of the criteria:
* - We allow fixed-pitch FF_MODERN (Monospace) TrueType fonts
* that can be italic or have negative A or C space.
* - If it is not a TrueType font, it can be from another character set
* than OEM_CHARSET.
* - We do not look into the magic registry key mentioned above.
*/
/*
* In ReactOS we relax some of the criteria:
* - We allow fixed-pitch FF_MODERN (Monospace) TrueType fonts
* that can be italic or have negative A or C space.
* - If it is not a TrueType font, it can be from another character set
* than OEM_CHARSET. When an Asian codepage is active however, we require
* that this non-TrueType font has an Asian character set.
*/
/* Reject variable width fonts */
if (((lplf->lfPitchAndFamily & 0x03) != FIXED_PITCH)
#if 0 /* Reject italic and TrueType fonts with negative A or C space */
|| (lplf->lfItalic)
|| !(lpntm->ntmFlags & NTM_NONNEGATIVE_AC)
/* Reject variable-width fonts ... */
if ( ( ((lplf->lfPitchAndFamily & 0x03) != FIXED_PITCH)
#if 0 /* Reject italic and TrueType fonts with negative A or C space ... */
|| (lplf->lfItalic)
|| !(lpntm->ntmFlags & NTM_NONNEGATIVE_AC)
#endif
)
) &&
/* ... if they are not in the list of additional TrueType fonts to include */
!IsAdditionalTTFont(FaceName) )
{
DPRINT1("Font '%S' rejected because it%s (lfPitchAndFamily = %d).\n",
FaceName, !(lplf->lfPitchAndFamily & FIXED_PITCH) ? "'s not FIXED_PITCH"
: (!(lpntm->ntmFlags & NTM_NONNEGATIVE_AC) ? " has negative A or C space"
: " is broken"),
DPRINT1("Font '%S' rejected because it%s (lfPitchAndFamily = %d)\n",
FaceName,
!(lplf->lfPitchAndFamily & FIXED_PITCH) ? "'s not FIXED_PITCH"
: (!(lpntm->ntmFlags & NTM_NONNEGATIVE_AC) ? " has negative A or C space"
: " is broken"),
lplf->lfPitchAndFamily);
return FALSE;
}
@ -238,25 +250,66 @@ IsValidConsoleFont2(
return FALSE;
}
/* Reject vertical fonts (tategaki) */
if (FaceName[0] == L'@')
{
DPRINT1("Font '%S' rejected because it's vertical\n", FaceName);
return FALSE;
}
/* Is the current code page Chinese, Japanese or Korean? */
if (IsCJKCodePage(CodePage))
{
/* It's Asian */
/* It's CJK */
if (FontType == TRUETYPE_FONTTYPE)
{
if (lplf->lfCharSet != CodePageToCharSet(CodePage))
/*
* Here we are inclusive and check for any CJK character set,
* instead of looking just at the current one via CodePageToCharSet().
*/
if (!IsCJKCharSet(lplf->lfCharSet)
#if 1 // FIXME: Temporary HACK!
&& wcscmp(FaceName, L"Terminal") != 0
#endif
)
{
DPRINT1("TrueType font '%S' rejected because it's not user Asian charset (lfCharSet = %d)\n",
DPRINT1("TrueType font '%S' rejected because it's not Asian charset (lfCharSet = %d)\n",
FaceName, lplf->lfCharSet);
return FALSE;
}
/*
* If this is a cached TrueType font that is used only for certain
* code pages, verify that the charset it claims is the correct one.
*
* Since there may be multiple entries for a cached TrueType font,
* a general one (code page == 0) and one or more for explicit
* code pages, we need to perform two search queries instead of
* just one and retrieving the code page for this entry.
*/
if (IsAdditionalTTFont(FaceName) && !IsAdditionalTTFontCP(FaceName, 0) &&
!IsCJKCharSet(lplf->lfCharSet))
{
DPRINT1("Cached TrueType font '%S' rejected because it claims a code page that is not Asian charset (lfCharSet = %d)\n",
FaceName, lplf->lfCharSet);
return FALSE;
}
}
else
{
/* Reject non-TrueType fonts that do not have an Asian character set */
if (!IsCJKCharSet(lplf->lfCharSet) && (lplf->lfCharSet != OEM_CHARSET))
{
DPRINT1("Non-TrueType font '%S' rejected because it's not Asian charset or OEM_CHARSET (lfCharSet = %d)\n",
FaceName, lplf->lfCharSet);
return FALSE;
}
/* Reject non-TrueType fonts that are not Terminal */
if (wcscmp(FaceName, L"Terminal") != 0)
{
DPRINT1("Non-TrueType font '%S' rejected because it's not Terminal\n", FaceName);
DPRINT1("Non-TrueType font '%S' rejected because it's not 'Terminal'\n", FaceName);
return FALSE;
}
}
@ -264,6 +317,8 @@ IsValidConsoleFont2(
else
{
/* Not CJK */
/* Reject non-TrueType fonts that are not OEM or similar */
if ((FontType != TRUETYPE_FONTTYPE) &&
(lplf->lfCharSet != ANSI_CHARSET) &&
(lplf->lfCharSet != DEFAULT_CHARSET) &&
@ -275,13 +330,6 @@ IsValidConsoleFont2(
}
}
/* Reject fonts that are vertical (tategaki) */
if (FaceName[0] == L'@')
{
DPRINT1("Font '%S' rejected because it's vertical\n", FaceName);
return FALSE;
}
/* All good */
return TRUE;
}
@ -320,7 +368,7 @@ IsValidConsoleFont(
RtlZeroMemory(&lf, sizeof(lf));
lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(CodePage);
// lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
// lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
StringCchCopyW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), FaceName);
hDC = GetDC(NULL);
@ -330,4 +378,173 @@ IsValidConsoleFont(
return Param.IsValidFont;
}
/*
* 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
*
* This function initializes the cache of the fonts listed there.
*/
VOID
InitTTFontCache(VOID)
{
BOOLEAN Success;
HKEY hKeyTTFonts; // hKey;
DWORD dwNumValues = 0;
DWORD dwIndex;
DWORD dwType;
WCHAR szValueName[MAX_PATH];
DWORD dwValueName;
WCHAR szValue[LF_FACESIZE] = L"";
DWORD dwValue;
PTT_FONT_ENTRY FontEntry;
PWCHAR pszNext = NULL;
UINT CodePage;
if (!IsListEmpty(&TTFontCache))
return;
// InitializeListHead(&TTFontCache);
/* Open the key */
// "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Console\\TrueTypeFont"
Success = (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Console\\TrueTypeFont",
0,
KEY_READ,
&hKeyTTFonts) == ERROR_SUCCESS);
if (!Success)
return;
/* Enumerate each value */
if (RegQueryInfoKeyW(hKeyTTFonts, NULL, NULL, NULL, NULL, NULL, NULL,
&dwNumValues, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
{
DPRINT("ConCfgReadUserSettings: RegQueryInfoKeyW failed\n");
RegCloseKey(hKeyTTFonts);
return;
}
for (dwIndex = 0; dwIndex < dwNumValues; dwIndex++)
{
dwValue = sizeof(szValue);
dwValueName = ARRAYSIZE(szValueName);
if (RegEnumValueW(hKeyTTFonts, dwIndex, szValueName, &dwValueName, NULL, &dwType, (BYTE*)szValue, &dwValue) != ERROR_SUCCESS)
{
DPRINT1("InitTTFontCache: RegEnumValueW failed, continuing...\n");
continue;
}
/* Only (multi-)string values are supported */
if ((dwType != REG_SZ) && (dwType != REG_MULTI_SZ))
continue;
/* The value name is a code page (in decimal), validate it */
CodePage = wcstoul(szValueName, &pszNext, 10);
if (*pszNext)
continue; // Non-numerical garbage followed...
// IsValidCodePage(CodePage);
FontEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*FontEntry));
if (!FontEntry)
{
DPRINT1("InitTTFontCache: Failed to allocate memory, continuing...\n");
continue;
}
FontEntry->CodePage = CodePage;
pszNext = szValue;
/* Check whether bold is disabled for this font */
if (*pszNext == L'*')
{
FontEntry->DisableBold = TRUE;
++pszNext;
}
else
{
FontEntry->DisableBold = FALSE;
}
/* Copy the font name */
StringCchCopyNW(FontEntry->FaceName, ARRAYSIZE(FontEntry->FaceName),
pszNext, wcslen(pszNext));
if (dwType == REG_MULTI_SZ)
{
/* There may be an alternate face name as the second string */
pszNext += wcslen(pszNext) + 1;
/* Check whether bold is disabled for this font */
if (*pszNext == L'*')
{
FontEntry->DisableBold = TRUE;
++pszNext;
}
// else, keep the original setting.
/* Copy the alternate font name */
StringCchCopyNW(FontEntry->FaceNameAlt, ARRAYSIZE(FontEntry->FaceNameAlt),
pszNext, wcslen(pszNext));
}
InsertTailList(&TTFontCache, &FontEntry->Entry);
}
/* Close the key and quit */
RegCloseKey(hKeyTTFonts);
}
VOID
ClearTTFontCache(VOID)
{
PLIST_ENTRY Entry;
PTT_FONT_ENTRY FontEntry;
while (!IsListEmpty(&TTFontCache))
{
Entry = RemoveHeadList(&TTFontCache);
FontEntry = CONTAINING_RECORD(Entry, TT_FONT_ENTRY, Entry);
RtlFreeHeap(RtlGetProcessHeap(), 0, FontEntry);
}
InitializeListHead(&TTFontCache);
}
VOID
RefreshTTFontCache(VOID)
{
ClearTTFontCache();
InitTTFontCache();
}
PTT_FONT_ENTRY
FindCachedTTFont(
IN LPCWSTR FaceName,
IN UINT CodePage)
{
PLIST_ENTRY Entry;
PTT_FONT_ENTRY FontEntry;
/* Search for the font in the cache */
for (Entry = TTFontCache.Flink;
Entry != &TTFontCache;
Entry = Entry->Flink)
{
FontEntry = CONTAINING_RECORD(Entry, TT_FONT_ENTRY, Entry);
/* NOTE: The font face names are case-sensitive */
if ((wcscmp(FontEntry->FaceName , FaceName) == 0) ||
(wcscmp(FontEntry->FaceNameAlt, FaceName) == 0))
{
/* Return a match if we don't look at the code pages, or when they match */
if ((CodePage == INVALID_CP) || (CodePage == FontEntry->CodePage))
{
return FontEntry;
}
}
}
return NULL;
}
/* EOF */

View file

@ -11,16 +11,50 @@
/* DEFINES ********************************************************************/
#define CP_SHIFTJIS 932 // Japanese Shift-JIS
#define CP_HANGUL 949 // Korean Hangul
#define CP_GB2312 936 // Chinese Simplified (GB2312)
#define CP_BIG5 950 // Chinese Traditional (Big5)
#define INVALID_CP ((UINT)-1)
#define CP_SHIFTJIS 932 // Japanese Shift-JIS
#define CP_HANGUL 949 // Korean Hangul/Wansung
#define CP_JOHAB 1361 // Korean Johab
#define CP_GB2312 936 // Chinese Simplified (GB2312)
#define CP_BIG5 950 // Chinese Traditional (Big5)
/* IsFarEastCP(CodePage) */
#define IsCJKCodePage(CodePage) \
((CodePage) == CP_SHIFTJIS || (CodePage) == CP_HANGUL || \
/* (CodePage) == CP_JOHAB || */ \
(CodePage) == CP_BIG5 || (CodePage) == CP_GB2312)
#if !defined(_WINGDI_) || defined(NOGDI)
#define SHIFTJIS_CHARSET 128
#define HANGEUL_CHARSET 129
#define HANGUL_CHARSET 129 // HANGEUL_CHARSET
#if(WINVER >= 0x0400)
#define JOHAB_CHARSET 130
#endif /* WINVER */
#define GB2312_CHARSET 134
#define CHINESEBIG5_CHARSET 136
#endif /* !defined(_WINGDI_) || defined(NOGDI) */
/* IsAnyDBCSCharSet(CharSet) */
#define IsCJKCharSet(CharSet) \
((CharSet) == SHIFTJIS_CHARSET || (CharSet) == HANGUL_CHARSET || \
/* (CharSet) == JOHAB_CHARSET || */ \
(CharSet) == GB2312_CHARSET || (CharSet) == CHINESEBIG5_CHARSET)
#define IsBoldFont(Weight) \
((Weight) >= FW_SEMIBOLD) /* Sometimes, just > FW_MEDIUM */
typedef struct _TT_FONT_ENTRY
{
LIST_ENTRY Entry;
UINT CodePage;
BOOL DisableBold;
WCHAR FaceName[LF_FACESIZE];
WCHAR FaceNameAlt[LF_FACESIZE];
} TT_FONT_ENTRY, *PTT_FONT_ENTRY;
/* FUNCTIONS ******************************************************************/
BYTE
@ -65,4 +99,33 @@ IsValidConsoleFont(
IN LPCWSTR FaceName,
IN UINT CodePage);
/*
* 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
*
* This function initializes the cache of the fonts listed there.
*/
VOID
InitTTFontCache(VOID);
VOID
ClearTTFontCache(VOID);
VOID
RefreshTTFontCache(VOID);
PTT_FONT_ENTRY
FindCachedTTFont(
IN LPCWSTR FaceName,
IN UINT CodePage);
#define IsAdditionalTTFont(FaceName) \
(FindCachedTTFont((FaceName), INVALID_CP) != NULL)
#define IsAdditionalTTFontCP(FaceName, CodePage) \
(FindCachedTTFont((FaceName), (CodePage)) != NULL)
/* EOF */

View file

@ -31,7 +31,8 @@
#include <ndk/obfuncs.h>
#include <ndk/rtlfuncs.h>
#include <stdio.h> // for swprintf
#include <stdio.h> // For swprintf()
#include <stdlib.h> // For wcstoul()
#include <strsafe.h>
/* EOF */

View file

@ -20,7 +20,7 @@
#define NDEBUG
#include <debug.h>
#include "font.h"
#include "concfg/font.h"
#include "guiterm.h"
#include "resource.h"

View file

@ -14,6 +14,7 @@
#define NDEBUG
#include <debug.h>
#include "concfg/font.h"
#include "guiterm.h"
#include "guisettings.h"
@ -331,7 +332,8 @@ GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
/* Set the terminal informations */
/* Change the font */
/* Refresh the additional TrueType fonts cache and change the font */
RefreshTTFontCache();
InitFonts(GuiData,
pConInfo->FaceName,
pConInfo->FontFamily,

View file

@ -16,6 +16,7 @@
#define NDEBUG
#include <debug.h>
#include "concfg/font.h"
#include "guiterm.h"
#include "resource.h"
@ -294,12 +295,15 @@ GuiInit(IN PCONSOLE_INIT_INFO ConsoleInitInfo,
HANDLE hInputThread;
CLIENT_ID ClientId;
/*
* Initialize and register the console window class, if needed.
*/
/* Perform one-time initialization */
if (!ConsInitialized)
{
/* Initialize and register the console window class */
if (!RegisterConWndClass(ConSrvDllInstance)) return FALSE;
/* Initialize the font support -- additional TrueType fonts cache */
InitTTFontCache();
ConsInitialized = TRUE;
}