static void
RemoveCacheEntries(FT_Face Face)
{
- PLIST_ENTRY CurrentEntry;
+ PLIST_ENTRY CurrentEntry, NextEntry;
PFONT_CACHE_ENTRY FontEntry;
ASSERT_FREETYPE_LOCK_HELD();
- CurrentEntry = g_FontCacheListHead.Flink;
- while (CurrentEntry != &g_FontCacheListHead)
+ for (CurrentEntry = g_FontCacheListHead.Flink;
+ CurrentEntry != &g_FontCacheListHead;
+ CurrentEntry = NextEntry)
{
FontEntry = CONTAINING_RECORD(CurrentEntry, FONT_CACHE_ENTRY, ListEntry);
- CurrentEntry = CurrentEntry->Flink;
+ NextEntry = CurrentEntry->Flink;
if (FontEntry->Face == Face)
{
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
IntLoadSystemFonts();
IntLoadFontSubstList(&g_FontSubstListHead);
+#if DBG
+ DumpFontInfo(TRUE);
+#endif
+
return TRUE;
}
PPROCESSINFO Win32Process = PsGetCurrentProcessWin32Process();
IntLockProcessPrivateFonts(Win32Process);
- Entry = Win32Process->PrivateMemFontListHead.Flink;
- while (Entry != &Win32Process->PrivateMemFontListHead)
+ for (Entry = Win32Process->PrivateMemFontListHead.Flink;
+ Entry != &Win32Process->PrivateMemFontListHead;
+ Entry = Entry->Flink)
{
CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY_COLL_MEM, ListEntry);
UnlinkFontMemCollection(CurrentEntry);
break;
}
-
- Entry = Entry->Flink;
}
IntUnLockProcessPrivateFonts(Win32Process);
Index++;
}
break;
+ case TCI_SRCLOCALE:
+ UNIMPLEMENTED;
+ return FALSE;
default:
return FALSE;
}
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)
{
Penalty += 15000;
}
}
- if (Byte & VARIABLE_PITCH)
+ if (Byte == VARIABLE_PITCH)
{
if (!(TM->tmPitchAndFamily & _TMPF_VARIABLE_PITCH))
{
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;
}
-#undef FF_MASK
-
if ((TM->tmPitchAndFamily & 0xF0) == FF_DONTCARE)
{
/* FamilyUnknown Penalty 8000 */
}
}
+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)
}
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.