https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6e4e5a004c9da6276695d…
commit 6e4e5a004c9da6276695d90187fb577812e8892f
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Sun Jan 6 10:43:34 2019 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Sun Jan 6 10:43:34 2019 +0900
[FONT][GDI32] Fix font enumeration functions (#1221)
Fix EnumFonts, EnumFontFamilies and EnumFontFamiliesEx functions.
The charsets of the font substitutes are also enumerated.
Delete meaningless codes. CORE-15558
---
win32ss/gdi/gdi32/objects/font.c | 98 ++++++++++++++++++--
win32ss/gdi/ntgdi/freetype.c | 196 +++++++++------------------------------
2 files changed, 136 insertions(+), 158 deletions(-)
diff --git a/win32ss/gdi/gdi32/objects/font.c b/win32ss/gdi/gdi32/objects/font.c
index 38758fa790..566d703ccb 100644
--- a/win32ss/gdi/gdi32/objects/font.c
+++ b/win32ss/gdi/gdi32/objects/font.c
@@ -204,9 +204,88 @@ NewTextMetricExW2A(NEWTEXTMETRICEXA *tma, NEWTEXTMETRICEXW *tmw)
tma->ntmFontSig = tmw->ntmFontSig;
}
+// IntFontFamilyCompareEx's flags
+#define IFFCX_CHARSET 1
+#define IFFCX_STYLE 2
+
+FORCEINLINE int FASTCALL
+IntFontFamilyCompareEx(const FONTFAMILYINFO *ffi1,
+ const FONTFAMILYINFO *ffi2, DWORD dwCompareFlags)
+{
+ const LOGFONTW *plf1 = &ffi1->EnumLogFontEx.elfLogFont;
+ const LOGFONTW *plf2 = &ffi2->EnumLogFontEx.elfLogFont;
+ ULONG WeightDiff1, WeightDiff2;
+ int cmp = _wcsicmp(plf1->lfFaceName, plf2->lfFaceName);
+ if (cmp)
+ return cmp;
+ if (dwCompareFlags & IFFCX_STYLE)
+ {
+ WeightDiff1 = labs(plf1->lfWeight - FW_NORMAL);
+ WeightDiff2 = labs(plf2->lfWeight - FW_NORMAL);
+ if (WeightDiff1 < WeightDiff2)
+ return -1;
+ if (WeightDiff1 > WeightDiff2)
+ return 1;
+ if (plf1->lfItalic < plf2->lfItalic)
+ return -1;
+ if (plf1->lfItalic > plf2->lfItalic)
+ return 1;
+ }
+ if (dwCompareFlags & IFFCX_CHARSET)
+ {
+ if (plf1->lfCharSet < plf2->lfCharSet)
+ return -1;
+ if (plf1->lfCharSet > plf2->lfCharSet)
+ return 1;
+ }
+ return 0;
+}
+
+static int __cdecl
+IntFontFamilyCompare(const void *ffi1, const void *ffi2)
+{
+ return IntFontFamilyCompareEx(ffi1, ffi2, IFFCX_STYLE | IFFCX_CHARSET);
+}
+
+// IntEnumFontFamilies' flags:
+#define IEFF_UNICODE 1
+#define IEFF_EXTENDED 2
+
+int FASTCALL
+IntFontFamilyListUnique(FONTFAMILYINFO *InfoList, INT nCount,
+ const LOGFONTW *plf, DWORD dwFlags)
+{
+ FONTFAMILYINFO *first, *last, *result;
+ DWORD dwCompareFlags = 0;
+
+ if (plf->lfFaceName[0])
+ dwCompareFlags |= IFFCX_STYLE;
+
+ if ((dwFlags & IEFF_EXTENDED) && plf->lfCharSet == DEFAULT_CHARSET)
+ dwCompareFlags |= IFFCX_CHARSET;
+
+ // std::unique(first, last, IntFontFamilyCompareEx);
+ if (nCount == 0)
+ return 0;
+
+ result = first = InfoList;
+ last = &InfoList[nCount];
+ while (++first != last)
+ {
+ if (IntFontFamilyCompareEx(result, first, dwCompareFlags) != 0 &&
+ ++result != first)
+ {
+ *result = *first;
+ }
+ }
+ nCount = (int)(++result - InfoList);
+
+ return nCount;
+}
+
static int FASTCALL
IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc, LPARAM lParam,
- BOOL Unicode)
+ DWORD dwFlags)
{
int FontFamilyCount;
int FontFamilySize;
@@ -256,9 +335,15 @@ IntEnumFontFamilies(HDC Dc, LPLOGFONTW LogFont, PVOID EnumProc,
LPARAM lParam,
}
}
+ DPRINT("qsort\n");
+ qsort(Info, FontFamilyCount, sizeof(*Info), IntFontFamilyCompare);
+ DPRINT("qsort done\n");
+ FontFamilyCount = IntFontFamilyListUnique(Info, FontFamilyCount, LogFont, dwFlags);
+ DPRINT("unique done\n");
+
for (i = 0; i < FontFamilyCount; i++)
{
- if (Unicode)
+ if (dwFlags & IEFF_UNICODE)
{
Ret = ((FONTENUMPROCW) EnumProc)(
(VOID*)&Info[i].EnumLogFontEx,
@@ -299,7 +384,8 @@ int WINAPI
EnumFontFamiliesExW(HDC hdc, LPLOGFONTW lpLogfont, FONTENUMPROCW lpEnumFontFamExProc,
LPARAM lParam, DWORD dwFlags)
{
- return IntEnumFontFamilies(hdc, lpLogfont, lpEnumFontFamExProc, lParam, TRUE);
+ return IntEnumFontFamilies(hdc, lpLogfont, lpEnumFontFamExProc, lParam,
+ IEFF_UNICODE | IEFF_EXTENDED);
}
@@ -320,7 +406,7 @@ EnumFontFamiliesW(HDC hdc, LPCWSTR lpszFamily, FONTENUMPROCW
lpEnumFontFamProc,
lstrcpynW(LogFont.lfFaceName, lpszFamily, LF_FACESIZE);
}
- return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, TRUE);
+ return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam,
IEFF_UNICODE);
}
@@ -341,7 +427,7 @@ EnumFontFamiliesExA (HDC hdc, LPLOGFONTA lpLogfont, FONTENUMPROCA
lpEnumFontFamE
else pLogFontW = NULL;
/* no need to convert LogFontW back to lpLogFont b/c it's an [in] parameter only
*/
- return IntEnumFontFamilies(hdc, pLogFontW, lpEnumFontFamExProc, lParam, FALSE);
+ return IntEnumFontFamilies(hdc, pLogFontW, lpEnumFontFamExProc, lParam,
IEFF_EXTENDED);
}
@@ -362,7 +448,7 @@ EnumFontFamiliesA(HDC hdc, LPCSTR lpszFamily, FONTENUMPROCA
lpEnumFontFamProc,
MultiByteToWideChar(CP_THREAD_ACP, 0, lpszFamily, -1, LogFont.lfFaceName,
LF_FACESIZE);
}
- return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, FALSE);
+ return IntEnumFontFamilies(hdc, &LogFont, lpEnumFontFamProc, lParam, 0);
}
diff --git a/win32ss/gdi/ntgdi/freetype.c b/win32ss/gdi/ntgdi/freetype.c
index dc229a75d5..a74d223cd5 100644
--- a/win32ss/gdi/ntgdi/freetype.c
+++ b/win32ss/gdi/ntgdi/freetype.c
@@ -2251,73 +2251,6 @@ IntGetOutlineTextMetrics(PFONTGDI FontGDI,
return Cache->OutlineRequiredSize;
}
-static PFONTGDI FASTCALL
-FindFaceNameInList(PUNICODE_STRING FaceName, PLIST_ENTRY Head)
-{
- PLIST_ENTRY Entry;
- PFONT_ENTRY CurrentEntry;
- ANSI_STRING EntryFaceNameA;
- UNICODE_STRING EntryFaceNameW;
- FONTGDI *FontGDI;
- NTSTATUS status;
-
- for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
- {
- CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
-
- FontGDI = CurrentEntry->Font;
- ASSERT(FontGDI);
-
- RtlInitAnsiString(&EntryFaceNameA,
FontGDI->SharedFace->Face->family_name);
- status = RtlAnsiStringToUnicodeString(&EntryFaceNameW, &EntryFaceNameA,
TRUE);
- if (!NT_SUCCESS(status))
- {
- break;
- }
-
- if ((LF_FACESIZE - 1) * sizeof(WCHAR) < EntryFaceNameW.Length)
- {
- EntryFaceNameW.Length = (LF_FACESIZE - 1) * sizeof(WCHAR);
- EntryFaceNameW.Buffer[LF_FACESIZE - 1] = L'\0';
- }
-
- if (RtlEqualUnicodeString(FaceName, &EntryFaceNameW, TRUE))
- {
- RtlFreeUnicodeString(&EntryFaceNameW);
- return FontGDI;
- }
-
- RtlFreeUnicodeString(&EntryFaceNameW);
- }
-
- return NULL;
-}
-
-static PFONTGDI FASTCALL
-FindFaceNameInLists(PUNICODE_STRING FaceName)
-{
- PPROCESSINFO Win32Process;
- PFONTGDI Font;
-
- /* Search the process local list.
- We do not have to search the 'Mem' list, since those fonts are linked in
the PrivateFontListHead */
- Win32Process = PsGetCurrentProcessWin32Process();
- IntLockProcessPrivateFonts(Win32Process);
- Font = FindFaceNameInList(FaceName, &Win32Process->PrivateFontListHead);
- IntUnLockProcessPrivateFonts(Win32Process);
- if (NULL != Font)
- {
- return Font;
- }
-
- /* Search the global list */
- IntLockGlobalFonts();
- Font = FindFaceNameInList(FaceName, &g_FontListHead);
- IntUnLockGlobalFonts();
-
- return Font;
-}
-
/* See
https://msdn.microsoft.com/en-us/library/bb165625(v=vs.90).aspx */
static BYTE
CharSetFromLangID(LANGID LangID)
@@ -2744,67 +2677,10 @@ FontFamilyFillInfo(PFONTFAMILYINFO Info, LPCWSTR FaceName,
Info->NewTextMetricEx.ntmFontSig = fs;
}
-static int FASTCALL
-FindFaceNameInInfo(PUNICODE_STRING FaceName, PFONTFAMILYINFO Info, DWORD InfoEntries)
-{
- DWORD i;
- UNICODE_STRING InfoFaceName;
-
- for (i = 0; i < InfoEntries; i++)
- {
- RtlInitUnicodeString(&InfoFaceName,
Info[i].EnumLogFontEx.elfLogFont.lfFaceName);
- if (RtlEqualUnicodeString(&InfoFaceName, FaceName, TRUE))
- {
- return i;
- }
- }
-
- return -1;
-}
-
-static BOOLEAN FASTCALL
-FontFamilyInclude(LPLOGFONTW LogFont, PUNICODE_STRING FaceName,
- PFONTFAMILYINFO Info, DWORD InfoEntries)
-{
- UNICODE_STRING LogFontFaceName;
-
- RtlInitUnicodeString(&LogFontFaceName, LogFont->lfFaceName);
- if (0 != LogFontFaceName.Length &&
- !RtlEqualUnicodeString(&LogFontFaceName, FaceName, TRUE))
- {
- return FALSE;
- }
-
- return FindFaceNameInInfo(FaceName, Info, InfoEntries) < 0;
-}
-
-static BOOL FASTCALL
-FontFamilyFound(PFONTFAMILYINFO InfoEntry,
- PFONTFAMILYINFO Info, DWORD InfoCount)
-{
- LPLOGFONTW plf1 = &InfoEntry->EnumLogFontEx.elfLogFont;
- LPWSTR pFullName1 = InfoEntry->EnumLogFontEx.elfFullName;
- LPWSTR pFullName2;
- DWORD i;
-
- for (i = 0; i < InfoCount; ++i)
- {
- LPLOGFONTW plf2 = &Info[i].EnumLogFontEx.elfLogFont;
- if (plf1->lfCharSet != plf2->lfCharSet)
- continue;
-
- pFullName2 = Info[i].EnumLogFontEx.elfFullName;
- if (_wcsicmp(pFullName1, pFullName2) != 0)
- continue;
-
- return TRUE;
- }
- return FALSE;
-}
-
static BOOLEAN FASTCALL
GetFontFamilyInfoForList(LPLOGFONTW LogFont,
PFONTFAMILYINFO Info,
+ LPCWSTR NominalName,
DWORD *pCount,
DWORD MaxCount,
PLIST_ENTRY Head)
@@ -2831,28 +2707,38 @@ GetFontFamilyInfoForList(LPLOGFONTW LogFont,
{
if (Count < MaxCount)
{
- FontFamilyFillInfo(&Info[Count], NULL, NULL, FontGDI);
+ FontFamilyFillInfo(&Info[Count], NominalName, NULL, FontGDI);
}
Count++;
continue;
}
- FontFamilyFillInfo(&InfoEntry, NULL, NULL, FontGDI);
+ FontFamilyFillInfo(&InfoEntry, NominalName, NULL, FontGDI);
- if (_wcsnicmp(LogFont->lfFaceName,
InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName, RTL_NUMBER_OF(LogFont->lfFaceName)-1) !=
0 &&
- _wcsnicmp(LogFont->lfFaceName, InfoEntry.EnumLogFontEx.elfFullName,
RTL_NUMBER_OF(LogFont->lfFaceName)-1) != 0)
+ if (NominalName)
{
- continue;
+ RtlStringCchCopyW(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName,
+
RTL_NUMBER_OF(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName),
+ NominalName);
}
-
- if (!FontFamilyFound(&InfoEntry, Info, min(Count, MaxCount)))
+ else
{
- if (Count < MaxCount)
+ if (_wcsnicmp(LogFont->lfFaceName,
+ InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName,
+ RTL_NUMBER_OF(LogFont->lfFaceName) - 1) != 0 &&
+ _wcsnicmp(LogFont->lfFaceName,
+ InfoEntry.EnumLogFontEx.elfFullName,
+ RTL_NUMBER_OF(LogFont->lfFaceName) - 1) != 0)
{
- RtlCopyMemory(&Info[Count], &InfoEntry, sizeof(InfoEntry));
+ continue;
}
- Count++;
}
+
+ if (Count < MaxCount)
+ {
+ RtlCopyMemory(&Info[Count], &InfoEntry, sizeof(InfoEntry));
+ }
+ Count++;
}
*pCount = Count;
@@ -2868,10 +2754,9 @@ GetFontFamilyInfoForSubstitutes(LPLOGFONTW LogFont,
{
PLIST_ENTRY pEntry, pHead = &g_FontSubstListHead;
PFONTSUBST_ENTRY pCurrentEntry;
- PUNICODE_STRING pFromW;
- FONTGDI *FontGDI;
+ PUNICODE_STRING pFromW, pToW;
LOGFONTW lf = *LogFont;
- UNICODE_STRING NameW;
+ PPROCESSINFO Win32Process = PsGetCurrentProcessWin32Process();
for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink)
{
@@ -2880,25 +2765,32 @@ GetFontFamilyInfoForSubstitutes(LPLOGFONTW LogFont,
pFromW = &pCurrentEntry->FontNames[FONTSUBST_FROM];
if (LogFont->lfFaceName[0] != UNICODE_NULL)
{
- if (!FontFamilyInclude(LogFont, pFromW, Info, min(*pCount, MaxCount)))
+ if (_wcsicmp(LogFont->lfFaceName, pFromW->Buffer) != 0)
continue; /* mismatch */
}
+ pToW = &pCurrentEntry->FontNames[FONTSUBST_TO];
+ if (RtlEqualUnicodeString(pFromW, pToW, TRUE) &&
+ pCurrentEntry->CharSets[FONTSUBST_FROM] ==
+ pCurrentEntry->CharSets[FONTSUBST_TO])
+ {
+ continue;
+ }
+
IntUnicodeStringToBuffer(lf.lfFaceName, sizeof(lf.lfFaceName), pFromW);
SubstituteFontRecurse(&lf);
+ if (LogFont->lfCharSet != DEFAULT_CHARSET && LogFont->lfCharSet !=
lf.lfCharSet)
+ continue;
- RtlInitUnicodeString(&NameW, lf.lfFaceName);
- FontGDI = FindFaceNameInLists(&NameW);
- if (FontGDI == NULL)
- {
- continue; /* no real font */
- }
+ IntLockGlobalFonts();
+ GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount,
&g_FontListHead);
+ IntUnLockGlobalFonts();
- if (*pCount < MaxCount)
- {
- FontFamilyFillInfo(&Info[*pCount], pFromW->Buffer, NULL, FontGDI);
- }
- (*pCount)++;
+ IntLockProcessPrivateFonts(Win32Process);
+ GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount,
+ &Win32Process->PrivateFontListHead);
+ IntUnLockProcessPrivateFonts(Win32Process);
+ break;
}
return TRUE;
@@ -5541,7 +5433,7 @@ NtGdiGetFontFamilyInfo(HDC Dc,
/* Enumerate font families in the global list */
IntLockGlobalFonts();
Count = 0;
- if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size,
&g_FontListHead) )
+ if (! GetFontFamilyInfoForList(&LogFont, Info, NULL, &Count, Size,
&g_FontListHead) )
{
IntUnLockGlobalFonts();
ExFreePoolWithTag(Info, GDITAG_TEXT);
@@ -5552,7 +5444,7 @@ NtGdiGetFontFamilyInfo(HDC Dc,
/* Enumerate font families in the process local list */
Win32Process = PsGetCurrentProcessWin32Process();
IntLockProcessPrivateFonts(Win32Process);
- if (! GetFontFamilyInfoForList(&LogFont, Info, &Count, Size,
+ if (! GetFontFamilyInfoForList(&LogFont, Info, NULL, &Count, Size,
&Win32Process->PrivateFontListHead))
{
IntUnLockProcessPrivateFonts(Win32Process);