https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6e4e5a004c9da6276695d90187fb577812e8892f

commit 6e4e5a004c9da6276695d90187fb577812e8892f
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Sun Jan 6 10:43:34 2019 +0900
Commit:     GitHub <[email protected]>
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);

Reply via email to