[FONT][WIN32SS] Use ExFreePoolWithTag instead of ExFreePool (#941)
[reactos.git] / win32ss / gdi / ntgdi / freetype.c
index 5275b36..10fb865 100644 (file)
@@ -335,6 +335,127 @@ SharedFace_Release(PSHARED_FACE Ptr)
     IntUnLockFreeType();
 }
 
+#if DBG
+VOID DumpFontGDI(PFONTGDI FontGDI)
+{
+    const char *family_name;
+    const char *style_name;
+    FT_Face Face;
+
+    if (!FontGDI)
+    {
+        DPRINT("FontGDI NULL\n");
+        return;
+    }
+
+    Face = (FontGDI->SharedFace ? FontGDI->SharedFace->Face : NULL);
+    if (Face)
+    {
+        family_name = Face->family_name;
+        if (!family_name)
+            family_name = "<NULL>";
+
+        style_name = Face->style_name;
+        if (!style_name)
+            style_name = "<NULL>";
+    }
+    else
+    {
+        family_name = "<invalid>";
+        style_name = "<invalid>";
+    }
+
+    DPRINT("family_name '%s', style_name '%s', FontGDI %p, FontObj %p, iUnique %lu, SharedFace %p, Face %p, CharSet %u, Filename '%S'\n",
+        family_name,
+        style_name,
+        FontGDI,
+        FontGDI->FontObj,
+        FontGDI->iUnique,
+        FontGDI->SharedFace,
+        Face,
+        FontGDI->CharSet,
+        FontGDI->Filename);
+}
+
+VOID DumpFontList(PLIST_ENTRY Head)
+{
+    PLIST_ENTRY Entry;
+    PFONT_ENTRY CurrentEntry;
+    PFONTGDI FontGDI;
+
+    DPRINT("## DumpFontList(%p)\n", Head);
+
+    for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
+    {
+        CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
+        FontGDI = CurrentEntry->Font;
+
+        DumpFontGDI(FontGDI);
+    }
+}
+
+VOID DumpFontSubstEntry(PFONTSUBST_ENTRY pSubstEntry)
+{
+    DPRINT("%wZ,%u -> %wZ,%u\n",
+        &pSubstEntry->FontNames[FONTSUBST_FROM],
+        pSubstEntry->CharSets[FONTSUBST_FROM],
+        &pSubstEntry->FontNames[FONTSUBST_TO],
+        pSubstEntry->CharSets[FONTSUBST_TO]);
+}
+
+VOID DumpFontSubstList(VOID)
+{
+    PLIST_ENTRY         pHead = &g_FontSubstListHead;
+    PLIST_ENTRY         pListEntry;
+    PFONTSUBST_ENTRY    pSubstEntry;
+
+    DPRINT("## DumpFontSubstList\n");
+
+    for (pListEntry = pHead->Flink;
+         pListEntry != pHead;
+         pListEntry = pListEntry->Flink)
+    {
+        pSubstEntry =
+            (PFONTSUBST_ENTRY)CONTAINING_RECORD(pListEntry, FONT_ENTRY, ListEntry);
+
+        DumpFontSubstEntry(pSubstEntry);
+    }
+}
+
+VOID DumpPrivateFontList(BOOL bDoLock)
+{
+    PPROCESSINFO Win32Process = PsGetCurrentProcessWin32Process();
+
+    if (!Win32Process)
+        return;
+
+    if (bDoLock)
+        IntLockProcessPrivateFonts(Win32Process);
+
+    DumpFontList(&Win32Process->PrivateFontListHead);
+
+    if (bDoLock)
+        IntUnLockProcessPrivateFonts(Win32Process);
+}
+
+VOID DumpGlobalFontList(BOOL bDoLock)
+{
+    if (bDoLock)
+        IntLockGlobalFonts();
+
+    DumpFontList(&g_FontListHead);
+
+    if (bDoLock)
+        IntUnLockGlobalFonts();
+}
+
+VOID DumpFontInfo(BOOL bDoLock)
+{
+    DumpGlobalFontList(bDoLock);
+    DumpPrivateFontList(bDoLock);
+    DumpFontSubstList();
+}
+#endif
 
 /*
  * IntLoadFontSubstList --- loads the list of font substitutes
@@ -522,6 +643,10 @@ InitFontSupport(VOID)
     IntLoadSystemFonts();
     IntLoadFontSubstList(&g_FontSubstListHead);
 
+#if DBG
+    DumpFontInfo(TRUE);
+#endif
+
     return TRUE;
 }
 
@@ -828,7 +953,7 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont,
     FONTGDI *           FontGDI;
     NTSTATUS            Status;
     FT_Face             Face;
-    ANSI_STRING         AnsiFaceName;
+    ANSI_STRING         AnsiString;
     FT_WinFNT_HeaderRec WinFNT;
     INT                 FaceCount = 0, CharSetCount = 0;
     PUNICODE_STRING     pFileName       = pLoadFont->pFileName;
@@ -950,8 +1075,24 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont,
     FontGDI->OriginalWeight = WeightFromStyle(Face->style_name);
     FontGDI->RequestWeight = FW_NORMAL;
 
-    RtlInitAnsiString(&AnsiFaceName, Face->family_name);
-    Status = RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE);
+    RtlInitAnsiString(&AnsiString, Face->family_name);
+    Status = RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiString, TRUE);
+    if (NT_SUCCESS(Status))
+    {
+        if (Face->style_name[0] && strcmp(Face->style_name, "Regular"))
+        {
+            RtlInitAnsiString(&AnsiString, Face->style_name);
+            Status = RtlAnsiStringToUnicodeString(&Entry->StyleName, &AnsiString, TRUE);
+            if (!NT_SUCCESS(Status))
+            {
+                RtlFreeUnicodeString(&Entry->FaceName);
+            }
+        }
+        else
+        {
+            RtlInitUnicodeString(&Entry->StyleName, NULL);
+        }
+    }
     if (!NT_SUCCESS(Status))
     {
         if (PrivateEntry)
@@ -1081,15 +1222,25 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont,
     if (CharSetIndex == -1)
     {
         INT i;
+        USHORT NameLength = Entry->FaceName.Length;
+
+        if (Entry->StyleName.Length)
+            NameLength += Entry->StyleName.Length + sizeof(WCHAR);
 
         if (pLoadFont->RegValueName.Length == 0)
         {
-            RtlCreateUnicodeString(pValueName, Entry->FaceName.Buffer);
+            pValueName->Length = 0;
+            pValueName->MaximumLength = NameLength + sizeof(WCHAR);
+            pValueName->Buffer = ExAllocatePoolWithTag(PagedPool,
+                                                       pValueName->MaximumLength,
+                                                       TAG_USTR);
+            pValueName->Buffer[0] = UNICODE_NULL;
+            RtlAppendUnicodeStringToString(pValueName, &Entry->FaceName);
         }
         else
         {
             UNICODE_STRING NewString;
-            USHORT Length = pValueName->Length + 3 * sizeof(WCHAR) + Entry->FaceName.Length;
+            USHORT Length = pValueName->Length + 3 * sizeof(WCHAR) + NameLength;
             NewString.Length = 0;
             NewString.MaximumLength = Length + sizeof(WCHAR);
             NewString.Buffer = ExAllocatePoolWithTag(PagedPool,
@@ -1104,6 +1255,11 @@ IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont,
             RtlFreeUnicodeString(pValueName);
             *pValueName = NewString;
         }
+        if (Entry->StyleName.Length)
+        {
+            RtlAppendUnicodeToString(pValueName, L" ");
+            RtlAppendUnicodeStringToString(pValueName, &Entry->StyleName);
+        }
 
         for (i = 1; i < CharSetCount; ++i)
         {
@@ -1524,6 +1680,9 @@ IntTranslateCharsetInfo(PDWORD Src, /* [in]
             Index++;
         }
         break;
+    case TCI_SRCLOCALE:
+        UNIMPLEMENTED;
+        return FALSE;
     default:
         return FALSE;
     }
@@ -4187,6 +4346,8 @@ ftGdiGetFontData(
     return Result;
 }
 
+#define GOT_PENALTY(name, value) Penalty += (value)
+
 // NOTE: See Table 1. of https://msdn.microsoft.com/en-us/library/ms969909.aspx
 static UINT
 GetFontPenalty(const LOGFONTW *               LogFont,
@@ -4228,18 +4389,19 @@ GetFontPenalty(const LOGFONTW *               LogFont,
         {
             /* CharSet Penalty 65000 */
             /* Requested charset does not match the candidate's. */
-            Penalty += 65000;
+            GOT_PENALTY("CharSet", 65000);
         }
         else
         {
             if (UserCharSet != TM->tmCharSet)
             {
-                /* UNDOCUMENTED */
-                Penalty += 100;
+                /* UNDOCUMENTED: Not user language */
+                GOT_PENALTY("UNDOCUMENTED:NotUserLanguage", 100);
+
                 if (ANSI_CHARSET != TM->tmCharSet)
                 {
-                    /* UNDOCUMENTED */
-                    Penalty += 100;
+                    /* UNDOCUMENTED: Not ANSI charset */
+                    GOT_PENALTY("UNDOCUMENTED:NotAnsiCharSet", 100);
                 }
             }
         }
@@ -4257,7 +4419,7 @@ GetFontPenalty(const LOGFONTW *               LogFont,
                 /* OutputPrecision Penalty 19000 */
                 /* Requested OUT_STROKE_PRECIS, but the device can't do it
                    or the candidate is not a vector font. */
-                Penalty += 19000;
+                GOT_PENALTY("OutputPrecision", 19000);
             }
             break;
         default:
@@ -4266,7 +4428,7 @@ GetFontPenalty(const LOGFONTW *               LogFont,
                 /* OutputPrecision Penalty 19000 */
                 /* Or OUT_STROKE_PRECIS not requested, and the candidate
                    is a vector font that requires GDI support. */
-                Penalty += 19000;
+                GOT_PENALTY("OutputPrecision", 19000);
             }
             break;
     }
@@ -4274,24 +4436,24 @@ GetFontPenalty(const LOGFONTW *               LogFont,
     Byte = (LogFont->lfPitchAndFamily & 0x0F);
     if (Byte == DEFAULT_PITCH)
         Byte = VARIABLE_PITCH;
-    if ((Byte & FIXED_PITCH) || (Byte & MONO_FONT))
+    if (Byte == FIXED_PITCH)
     {
         if (TM->tmPitchAndFamily & _TMPF_VARIABLE_PITCH)
         {
             /* FixedPitch Penalty 15000 */
             /* Requested a fixed pitch font, but the candidate is a
                variable pitch font. */
-            Penalty += 15000;
+            GOT_PENALTY("FixedPitch", 15000);
         }
     }
-    if (Byte & VARIABLE_PITCH)
+    if (Byte == VARIABLE_PITCH)
     {
         if (!(TM->tmPitchAndFamily & _TMPF_VARIABLE_PITCH))
         {
             /* PitchVariable Penalty 350 */
             /* Requested a variable pitch font, but the candidate is not a
                variable pitch font. */
-            Penalty += 350;
+            GOT_PENALTY("PitchVariable", 350);
         }
     }
 
@@ -4302,7 +4464,7 @@ GetFontPenalty(const LOGFONTW *               LogFont,
         {
             /* DefaultPitchFixed Penalty 1 */
             /* Requested DEFAULT_PITCH, but the candidate is fixed pitch. */
-            Penalty += 1;
+            GOT_PENALTY("DefaultPitchFixed", 1);
         }
     }
 
@@ -4328,49 +4490,24 @@ GetFontPenalty(const LOGFONTW *               LogFont,
             /* FaceName Penalty 10000 */
             /* Requested a face name, but the candidate's face name
                does not match. */
-            Penalty += 10000;
+            GOT_PENALTY("FaceName", 10000);
         }
     }
 
     Byte = (LogFont->lfPitchAndFamily & 0xF0);
     if (Byte != FF_DONTCARE)
     {
-        if (Byte & FF_MODERN)
-        {
-            if (TM->tmPitchAndFamily & _TMPF_VARIABLE_PITCH)
-            {
-                /* FixedPitch Penalty 15000 */
-                /* Requested a fixed pitch font, but the candidate is a
-                   variable pitch font. */
-                Penalty += 15000;
-            }
-        }
-
-        if ((Byte & FF_ROMAN) || (Byte & FF_SWISS))
-        {
-            if (!(TM->tmPitchAndFamily & _TMPF_VARIABLE_PITCH))
-            {
-                /* PitchVariable Penalty 350 */
-                /* Requested a variable pitch font, but the candidate is not a
-                   variable pitch font. */
-                Penalty += 350;
-            }
-        }
-
-#define FF_MASK  (FF_DECORATIVE | FF_SCRIPT | FF_SWISS)
-        if ((Byte & FF_MASK) != (TM->tmPitchAndFamily & FF_MASK))
+        if (Byte != (TM->tmPitchAndFamily & 0xF0))
         {
             /* Family Penalty 9000 */
             /* Requested a family, but the candidate's family is different. */
-            Penalty += 9000;
+            GOT_PENALTY("Family", 9000);
         }
-#undef FF_MASK
-
         if ((TM->tmPitchAndFamily & 0xF0) == FF_DONTCARE)
         {
             /* FamilyUnknown Penalty 8000 */
             /* Requested a family, but the candidate has no family. */
-            Penalty += 8000;
+            GOT_PENALTY("FamilyUnknown", 8000);
         }
     }
 
@@ -4385,11 +4522,11 @@ GetFontPenalty(const LOGFONTW *               LogFont,
                 /* HeightBigger Penalty 600 */
                 /* The candidate is a nonvector font and is bigger than the
                    requested height. */
-                Penalty += 600;
+                GOT_PENALTY("HeightBigger", 600);
                 /* HeightBiggerDifference Penalty 150 */
                 /* The candidate is a raster font and is larger than the
                    requested height. Penalty * height difference */
-                Penalty += 150 * labs(TM->tmHeight - labs(LogFont->lfHeight));
+                GOT_PENALTY("HeightBiggerDifference", 150 * labs(TM->tmHeight - labs(LogFont->lfHeight)));
 
                 fNeedScaling = TRUE;
             }
@@ -4398,7 +4535,7 @@ GetFontPenalty(const LOGFONTW *               LogFont,
                 /* HeightSmaller Penalty 150 */
                 /* The candidate is a raster font and is smaller than the
                    requested height. Penalty * height difference */
-                Penalty += 150 * labs(TM->tmHeight - labs(LogFont->lfHeight));
+                GOT_PENALTY("HeightSmaller", 150 * labs(TM->tmHeight - labs(LogFont->lfHeight)));
 
                 fNeedScaling = TRUE;
             }
@@ -4414,7 +4551,7 @@ GetFontPenalty(const LOGFONTW *               LogFont,
                     /* FamilyUnlikely Penalty 50 */
                     /* Requested a roman/modern/swiss family, but the
                        candidate is decorative/script. */
-                    Penalty += 50;
+                    GOT_PENALTY("FamilyUnlikely", 50);
                     break;
                 default:
                     break;
@@ -4427,7 +4564,7 @@ GetFontPenalty(const LOGFONTW *               LogFont,
                     /* FamilyUnlikely Penalty 50 */
                     /* Or requested decorative/script, and the candidate is
                        roman/modern/swiss. */
-                    Penalty += 50;
+                    GOT_PENALTY("FamilyUnlikely", 50);
                     break;
                 default:
                     break;
@@ -4443,7 +4580,7 @@ GetFontPenalty(const LOGFONTW *               LogFont,
             /* Width Penalty 50 */
             /* Requested a nonzero width, but the candidate's width
                doesn't match. Penalty * width difference */
-            Penalty += 50 * labs(LogFont->lfWidth - TM->tmAveCharWidth);
+            GOT_PENALTY("Width", 50 * labs(LogFont->lfWidth - TM->tmAveCharWidth));
 
             if (!(TM->tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)))
                 fNeedScaling = TRUE;
@@ -4454,7 +4591,7 @@ GetFontPenalty(const LOGFONTW *               LogFont,
     {
         /* SizeSynth Penalty 50 */
         /* The candidate is a raster font that needs scaling by GDI. */
-        Penalty += 50;
+        GOT_PENALTY("SizeSynth", 50);
     }
 
     if (!!LogFont->lfItalic != !!TM->tmItalic)
@@ -4465,14 +4602,14 @@ GetFontPenalty(const LOGFONTW *               LogFont,
             /* Requested font and candidate font do not agree on italic status,
                and the desired result cannot be simulated. */
             /* Adjusted to 40 to satisfy (Oblique Penalty > Book Penalty). */
-            Penalty += 40;
+            GOT_PENALTY("Italic", 40);
         }
         else if (LogFont->lfItalic && !ItalicFromStyle(style_name))
         {
             /* ItalicSim Penalty 1 */
             /* Requested italic font but the candidate is not italic,
                although italics can be simulated. */
-            Penalty += 1;
+            GOT_PENALTY("ItalicSim", 1);
         }
     }
 
@@ -4483,7 +4620,7 @@ GetFontPenalty(const LOGFONTW *               LogFont,
             /* NotTrueType Penalty 4 */
             /* Requested OUT_TT_PRECIS, but the candidate is not a
                TrueType font. */
-            Penalty += 4;
+            GOT_PENALTY("NotTrueType", 4);
         }
     }
 
@@ -4495,7 +4632,7 @@ GetFontPenalty(const LOGFONTW *               LogFont,
         /* Weight Penalty 3 */
         /* The candidate's weight does not match the requested weight. 
            Penalty * (weight difference/10) */
-        Penalty += 3 * (labs(Long - TM->tmWeight) / 10);
+        GOT_PENALTY("Weight", 3 * (labs(Long - TM->tmWeight) / 10));
     }
 
     if (!LogFont->lfUnderline && TM->tmUnderlined)
@@ -4503,7 +4640,7 @@ GetFontPenalty(const LOGFONTW *               LogFont,
         /* Underline Penalty 3 */
         /* Requested font has no underline, but the candidate is
            underlined. */
-        Penalty += 3;
+        GOT_PENALTY("Underline", 3);
     }
 
     if (!LogFont->lfStrikeOut && TM->tmStruckOut)
@@ -4511,7 +4648,7 @@ GetFontPenalty(const LOGFONTW *               LogFont,
         /* StrikeOut Penalty 3 */
         /* Requested font has no strike-out, but the candidate is
            struck out. */
-        Penalty += 3;
+        GOT_PENALTY("StrikeOut", 3);
     }
 
     /* Is the candidate a non-vector font? */
@@ -4522,14 +4659,14 @@ GetFontPenalty(const LOGFONTW *               LogFont,
             /* VectorHeightSmaller Penalty 2 */
             /* Candidate is a vector font that is smaller than the
                requested height. Penalty * height difference */
-            Penalty += 2 * labs(TM->tmHeight - LogFont->lfHeight);
+            GOT_PENALTY("VectorHeightSmaller", 2 * labs(TM->tmHeight - LogFont->lfHeight));
         }
         if (LogFont->lfHeight != 0 && TM->tmHeight > LogFont->lfHeight)
         {
             /* VectorHeightBigger Penalty 1 */
             /* Candidate is a vector font that is bigger than the
                requested height. Penalty * height difference */
-            Penalty += 1 * labs(TM->tmHeight - LogFont->lfHeight);
+            GOT_PENALTY("VectorHeightBigger", 1 * labs(TM->tmHeight - LogFont->lfHeight));
         }
     }
 
@@ -4537,7 +4674,7 @@ GetFontPenalty(const LOGFONTW *               LogFont,
     {
         /* DeviceFavor Penalty 2 */
         /* Extra penalty for all nondevice fonts. */
-        Penalty += 2;
+        GOT_PENALTY("DeviceFavor", 2);
     }
 
     if (TM->tmAveCharWidth >= 5 && TM->tmHeight >= 5)
@@ -4546,13 +4683,13 @@ GetFontPenalty(const LOGFONTW *               LogFont,
         {
             /* Aspect Penalty 30 */
             /* The aspect rate is >= 3. It seems like a bad font. */
-            Penalty += ((TM->tmAveCharWidth / TM->tmHeight) - 2) * 30;
+            GOT_PENALTY("Aspect", ((TM->tmAveCharWidth / TM->tmHeight) - 2) * 30);
         }
         else if (TM->tmHeight / TM->tmAveCharWidth >= 3)
         {
             /* Aspect Penalty 30 */
             /* The aspect rate is >= 3. It seems like a bad font. */
-            Penalty += ((TM->tmHeight / TM->tmAveCharWidth) - 2) * 30;
+            GOT_PENALTY("Aspect", ((TM->tmHeight / TM->tmAveCharWidth) - 2) * 30);
         }
     }
 
@@ -4569,6 +4706,8 @@ GetFontPenalty(const LOGFONTW *               LogFont,
     return Penalty;     /* success */
 }
 
+#undef GOT_PENALTY
+
 static __inline VOID
 FindBestFontFromList(FONTOBJ **FontObj, ULONG *MatchPenalty,
                      const LOGFONTW *LogFont,
@@ -4667,6 +4806,53 @@ IntFontType(PFONTGDI Font)
     }
 }
 
+static BOOL
+MatchFontName(PSHARED_FACE SharedFace, LPCWSTR lfFaceName, FT_UShort NameID, FT_UShort LangID)
+{
+    NTSTATUS Status;
+    UNICODE_STRING Name1, Name2;
+
+    if (lfFaceName[0] == UNICODE_NULL)
+        return FALSE;
+
+    RtlInitUnicodeString(&Name1, lfFaceName);
+
+    RtlInitUnicodeString(&Name2, NULL);
+    Status = IntGetFontLocalizedName(&Name2, SharedFace, NameID, LangID);
+
+    if (NT_SUCCESS(Status))
+    {
+        if (RtlCompareUnicodeString(&Name1, &Name2, TRUE) == 0)
+        {
+            RtlFreeUnicodeString(&Name2);
+            return TRUE;
+        }
+
+        RtlFreeUnicodeString(&Name2);
+    }
+
+    return FALSE;
+}
+
+static BOOL
+MatchFontNames(PSHARED_FACE SharedFace, LPCWSTR lfFaceName)
+{
+    if (MatchFontName(SharedFace, lfFaceName, TT_NAME_ID_FONT_FAMILY, LANG_ENGLISH) ||
+        MatchFontName(SharedFace, lfFaceName, TT_NAME_ID_FULL_NAME, LANG_ENGLISH))
+    {
+        return TRUE;
+    }
+    if (PRIMARYLANGID(gusLanguageID) != LANG_ENGLISH)
+    {
+        if (MatchFontName(SharedFace, lfFaceName, TT_NAME_ID_FONT_FAMILY, gusLanguageID) ||
+            MatchFontName(SharedFace, lfFaceName, TT_NAME_ID_FULL_NAME, gusLanguageID))
+        {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
 NTSTATUS
 FASTCALL
 TextIntRealizeFont(HFONT FontHandle, PTEXTOBJ pTextObj)
@@ -4731,22 +4917,32 @@ TextIntRealizeFont(HFONT FontHandle, PTEXTOBJ pTextObj)
     }
     else
     {
-        UNICODE_STRING FaceName;
+        UNICODE_STRING Name;
         PFONTGDI FontGdi = ObjToGDI(TextObj->Font, FONT);
+        PSHARED_FACE SharedFace = FontGdi->SharedFace;
 
         IntLockFreeType();
         IntRequestFontSize(NULL, FontGdi, pLogFont->lfWidth, pLogFont->lfHeight);
         IntUnLockFreeType();
 
-        RtlInitUnicodeString(&FaceName, NULL);
-        IntGetFontLocalizedName(&FaceName, FontGdi->SharedFace, TT_NAME_ID_FONT_FAMILY, gusLanguageID);
-
-        /* truncated copy */
-        FaceName.Length = (USHORT)min(FaceName.Length, (LF_FACESIZE - 1) * sizeof(WCHAR));
-        FaceName.MaximumLength = (USHORT)(FaceName.Length + sizeof(UNICODE_NULL));
-        RtlCopyMemory(TextObj->FaceName, FaceName.Buffer, FaceName.MaximumLength);
+        TextObj->TextFace[0] = UNICODE_NULL;
+        if (MatchFontNames(SharedFace, SubstitutedLogFont.lfFaceName))
+        {
+            RtlStringCchCopyW(TextObj->TextFace, _countof(TextObj->TextFace), pLogFont->lfFaceName);
+        }
+        else
+        {
+            RtlInitUnicodeString(&Name, NULL);
+            Status = IntGetFontLocalizedName(&Name, SharedFace, TT_NAME_ID_FONT_FAMILY, gusLanguageID);
+            if (NT_SUCCESS(Status))
+            {
+                /* truncated copy */
+                Name.Length = (USHORT)min(Name.Length, (LF_FACESIZE - 1) * sizeof(WCHAR));
+                RtlStringCbCopyNW(TextObj->TextFace, Name.Length + sizeof(WCHAR), Name.Buffer, Name.Length);
 
-        RtlFreeUnicodeString(&FaceName);
+                RtlFreeUnicodeString(&Name);
+            }
+        }
 
         // Need hdev, when freetype is loaded need to create DEVOBJ for
         // Consumer and Producer.
@@ -4954,7 +5150,7 @@ IntGdiGetFontResourceInfo(
 
     /* Free the buffers */
     ExFreePoolWithTag(NameInfo1, TAG_FINF);
-    ExFreePool(NameInfo2);
+    ExFreePoolWithTag(NameInfo2, TAG_FINF);
 
     if (Count == 0 && dwType != 5)
     {
@@ -4988,15 +5184,10 @@ IntGdiGetFontResourceInfo(
     case 1: /* copy the font title */
         /* calculate the required size */
         Size = 0;
-        Size += wcslen(FamInfo[0].EnumLogFontEx.elfLogFont.lfFaceName);
-        if (FamInfo[0].EnumLogFontEx.elfStyle[0] &&
-            _wcsicmp(FamInfo[0].EnumLogFontEx.elfStyle, L"Regular") != 0)
-        {
-            Size += 1 + wcslen(FamInfo[0].EnumLogFontEx.elfStyle);
-        }
-        for (i = 1; i < Count; ++i)
+        for (i = 0; i < Count; ++i)
         {
-            Size += 3;  /* " & " */
+            if (i > 0)
+                Size += 3;  /* " & " */
             Size += wcslen(FamInfo[i].EnumLogFontEx.elfLogFont.lfFaceName);
             if (FamInfo[i].EnumLogFontEx.elfStyle[0] &&
                 _wcsicmp(FamInfo[i].EnumLogFontEx.elfStyle, L"Regular") != 0)
@@ -5019,10 +5210,10 @@ IntGdiGetFontResourceInfo(
                 /* store font title to buffer */
                 WCHAR *psz = pBuffer;
                 *psz = 0;
-                IntAddNameFromFamInfo(psz, &FamInfo[0]);
-                for (i = 1; i < Count; ++i)
+                for (i = 0; i < Count; ++i)
                 {
-                    wcscat(psz, L" & ");
+                    if (i > 0)
+                        wcscat(psz, L" & ");
                     IntAddNameFromFamInfo(psz, &FamInfo[i]);
                 }
                 psz[wcslen(psz) + 1] = UNICODE_NULL;