ReactOS 0.4.16-dev-2332-g4cba65d
freetype.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: FreeType font engine interface
5 * PROGRAMMERS: Copyright 2001 Huw D M Davies for CodeWeavers.
6 * Copyright 2006 Dmitry Timoshkov for CodeWeavers.
7 * Copyright 2016-2026 Katayama Hirofumi MZ.
8 */
9
10#include <win32k.h>
11
12#include FT_GLYPH_H
13#include FT_TYPE1_TABLES_H
14#include FT_TRUETYPE_TABLES_H
15#include FT_TRUETYPE_TAGS_H
16#include FT_TRIGONOMETRY_H
17#include FT_BITMAP_H
18#include FT_OUTLINE_H
19#include FT_WINFONTS_H
20#include FT_SFNT_NAMES_H
21#include FT_SYNTHESIS_H
22#include FT_TRUETYPE_IDS_H
23#include FT_MODULE_H
24#include <freetype/internal/ftcalc.h> // INT_TO_FIXED
25
26#include <gdi/eng/floatobj.h>
27#include "font.h"
28#include "utils.h"
29
30#define NDEBUG
31#include <debug.h>
32// DBG_DEFAULT_CHANNEL(GdiFont); // TODO: Re-enable when using TRACE/ERR...
33
34typedef struct _FONTLINK
35{
36 LIST_ENTRY ListEntry; //< Entry in the FONTLINK_CHAIN::FontLinkList
41
42typedef struct _FONTLINK_CHAIN
43{
44 LIST_ENTRY FontLinkList; //< List of FONTLINK's
50
51typedef struct _FONTLINK_CACHE
52{
57
58#define FONTLINK_DEFAULT_CHAR 0x30FB // U+30FB (KATAKANA MIDDLE DOT)
59
66
67#define MAX_FONTLINK_CACHE 128
68static RTL_STATIC_LIST_HEAD(g_FontLinkCache); // The list of FONTLINK_CACHE
70
71static inline NTSTATUS
73{
75 HKEY hKey;
76 DWORD cbData, dwValue;
77
78 // Set the default values
80
81 // Open the registry key
83 L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\FontLink",
84 &hKey);
85 if (!NT_SUCCESS(Status))
86 return Status;
87
88 cbData = sizeof(dwValue);
89 Status = RegQueryValue(hKey, L"FontLinkDefaultChar", REG_DWORD, &dwValue, &cbData);
90 if (NT_SUCCESS(Status) && cbData == sizeof(dwValue))
92
93 ZwClose(hKey); // Close the registry key
94 return STATUS_SUCCESS;
95}
96
97static inline NTSTATUS
99{
101 HKEY hKey;
103 WCHAR szValue[MAX_PATH];
104
105 // Set the default values
107
108 // Open the registry key
110 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\FontAssoc\\Associated DefaultFonts",
111 &hKey);
112 if (!NT_SUCCESS(Status))
113 return Status;
114
115 cbData = sizeof(szValue);
116 Status = RegQueryValue(hKey, L"AssocSystemFont", REG_SZ, szValue, &cbData);
117 if (NT_SUCCESS(Status))
118 {
119 szValue[_countof(szValue) - 1] = UNICODE_NULL; // Avoid buffer overrun
121 }
122
123 cbData = sizeof(szValue);
124 Status = RegQueryValue(hKey, L"FontPackage", REG_SZ, szValue, &cbData);
125 if (NT_SUCCESS(Status))
126 {
127 szValue[_countof(szValue) - 1] = UNICODE_NULL; // Avoid buffer overrun
129 }
130
131 ZwClose(hKey); // Close the registry key
132 return STATUS_SUCCESS;
133}
134
135static inline NTSTATUS
137{
139 HKEY hKey;
141 WCHAR szValue[8];
142
143 // Set the default values
145
146 // Open the registry key
148 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\FontAssoc\\Associated Charset",
149 &hKey);
150 if (!NT_SUCCESS(Status))
151 return Status;
152
153 cbData = sizeof(szValue);
154 Status = RegQueryValue(hKey, L"ANSI(00)", REG_SZ, szValue, &cbData);
155 if (NT_SUCCESS(Status))
156 {
157 szValue[_countof(szValue) - 1] = UNICODE_NULL; // Avoid buffer overrun
158 s_fFontLinkUseAnsi = !_wcsicmp(szValue, L"YES");
159 }
160
161 cbData = sizeof(szValue);
162 Status = RegQueryValue(hKey, L"OEM(FF)", REG_SZ, szValue, &cbData);
163 if (NT_SUCCESS(Status))
164 {
165 szValue[_countof(szValue) - 1] = UNICODE_NULL; // Avoid buffer overrun
166 s_fFontLinkUseOem = !_wcsicmp(szValue, L"YES");
167 }
168
169 cbData = sizeof(szValue);
170 Status = RegQueryValue(hKey, L"SYMBOL(02)", REG_SZ, szValue, &cbData);
171 if (NT_SUCCESS(Status))
172 {
173 szValue[_countof(szValue) - 1] = UNICODE_NULL; // Avoid buffer overrun
174 s_fFontLinkUseSymbol = !_wcsicmp(szValue, L"YES");
175 }
176
177 ZwClose(hKey); // Close the registry key
178 return STATUS_SUCCESS;
179}
180
181static inline VOID
183{
185}
186
187static inline BOOL
189{
190 return pChain->LogFont.lfFaceName[0];
191}
192
193static VOID
196{
198 PFONTLINK pLink;
199
200 if (!FontLink_Chain_IsPopulated(pChain)) // The chain is not populated yet
201 return;
202
203 if (pChain->pszzFontLink)
204 ExFreePoolWithTag(pChain->pszzFontLink, TAG_FONT);
205
206 while (!IsListEmpty(&pChain->FontLinkList))
207 {
208 Entry = RemoveHeadList(&pChain->FontLinkList);
209 pLink = CONTAINING_RECORD(Entry, FONTLINK, ListEntry);
210 FontLink_Destroy(pLink);
211 }
212}
213
214static inline VOID
216 _In_ PFONTLINK_CACHE pCache)
217{
219
220 /* Add the new cache entry to the top of the cache list */
222 InsertHeadList(&g_FontLinkCache, &pCache->ListEntry);
223
224 /* If there are too many cache entries in the list, remove the oldest one at the bottom */
226 {
227 ASSERT(!IsListEmpty(&g_FontLinkCache));
228 Entry = RemoveTailList(&g_FontLinkCache);
230 pCache = CONTAINING_RECORD(Entry, FONTLINK_CACHE, ListEntry);
231 FontLink_Chain_Free(&pCache->Chain);
233 }
234}
235
238static inline VOID
241{
242 PFONTLINK_CACHE pCache;
243
244 if (!FontLink_Chain_IsPopulated(pChain))
245 return; // The chain is not populated yet
246
248 if (!pCache)
249 return; // Out of memory
250
251 pCache->LogFont = pChain->LogFont;
252 pCache->Chain = *pChain;
253 IntRebaseList(&pCache->Chain.FontLinkList, &pChain->FontLinkList);
254
255 FontLink_AddCache(pCache);
256}
257
258static inline PFONTLINK_CACHE
260 _In_ const LOGFONTW* pLogFont)
261{
263 PFONTLINK_CACHE pLinkCache;
264 for (Entry = g_FontLinkCache.Flink; Entry != &g_FontLinkCache; Entry = Entry->Flink)
265 {
266 pLinkCache = CONTAINING_RECORD(Entry, FONTLINK_CACHE, ListEntry);
267 if (RtlEqualMemory(&pLinkCache->LogFont, pLogFont, sizeof(LOGFONTW)))
268 return pLinkCache;
269 }
270 return NULL;
271}
272
273static inline VOID
275{
277 PFONTLINK_CACHE pLinkCache;
278
279 while (!IsListEmpty(&g_FontLinkCache))
280 {
281 Entry = RemoveHeadList(&g_FontLinkCache);
282 pLinkCache = CONTAINING_RECORD(Entry, FONTLINK_CACHE, ListEntry);
283 FontLink_Chain_Free(&pLinkCache->Chain);
284 ExFreePoolWithTag(pLinkCache, TAG_FONT);
285 }
286
288}
289
290typedef struct _FONT_LOOKUP_CACHE
291{
297
298static RTL_STATIC_LIST_HEAD(s_FontLookupCacheList); // The list of FONT_LOOKUP_CACHE
299#define MAX_FONT_LOOKUP_CACHE 64
301
302/* TPMF_FIXED_PITCH is confusing; brain-dead api */
303#ifndef _TMPF_VARIABLE_PITCH
304 #define _TMPF_VARIABLE_PITCH TMPF_FIXED_PITCH
305#endif
306
307/* Is bold emulation necessary? */
308#define EMUBOLD_NEEDED(original, request) \
309 (((request) != FW_DONTCARE) && ((request) - (original) >= FW_BOLD - FW_MEDIUM))
310
312extern const MATRIX gmxWorldToPageDefault;
313static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
314
315/* HACK!! Fix XFORMOBJ then use 1:16 / 16:1 */
316#define gmxWorldToDeviceDefault gmxWorldToPageDefault
317
319
320/* registry */
322 RTL_CONSTANT_STRING(L"\\REGISTRY\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts");
323
324/* The FreeType library is not thread safe, so we have
325 to serialize access to it */
327
328static RTL_STATIC_LIST_HEAD(g_FontListHead);
330
331#define ASSERT_FREETYPE_LOCK_HELD() \
332 ASSERT(g_FreeTypeLock->Owner == KeGetCurrentThread())
333
334#define ASSERT_FREETYPE_LOCK_NOT_HELD() \
335 ASSERT(g_FreeTypeLock->Owner != KeGetCurrentThread())
336
337#define IntLockFreeType() \
338do { \
339 ASSERT_FREETYPE_LOCK_NOT_HELD(); \
340 ExEnterCriticalRegionAndAcquireFastMutexUnsafe(g_FreeTypeLock); \
341} while (0)
342
343#define IntUnLockFreeType() \
344do { \
345 ASSERT_FREETYPE_LOCK_HELD(); \
346 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(g_FreeTypeLock); \
347} while(0)
348
349#define MAX_FONT_CACHE 256
350
351static RTL_STATIC_LIST_HEAD(g_FontCacheListHead);
353
354static PWCHAR g_ElfScripts[32] = /* These are in the order of the fsCsb[0] bits */
355{
356 L"Western", /* 00 */
357 L"Central_European",
358 L"Cyrillic",
359 L"Greek",
360 L"Turkish",
361 L"Hebrew",
362 L"Arabic",
363 L"Baltic",
364 L"Vietnamese", /* 08 */
365 NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 15 */
366 L"Thai",
367 L"Japanese",
368 L"CHINESE_GB2312",
369 L"Hangul",
370 L"CHINESE_BIG5",
371 L"Hangul(Johab)",
372 NULL, NULL, /* 23 */
374 L"Symbol" /* 31 */
375};
376
377/*
378 * For TranslateCharsetInfo
379 */
380#define CP_SYMBOL 42
381#define MAXTCIINDEX 32
383{
384 /* ANSI */
385 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
386 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
387 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
388 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
389 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
390 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
391 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
392 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
393 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
394 /* reserved by ANSI */
395 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
396 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
397 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
398 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
399 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
400 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
401 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
402 /* ANSI and OEM */
403 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
404 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
405 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
406 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
407 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
408 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
409 /* Reserved for alternate ANSI and OEM */
410 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
411 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
412 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
413 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
414 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
415 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
416 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
417 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
418 /* Reserved for system */
419 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
420 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
421};
422
423#ifndef CP_OEMCP
424 #define CP_OEMCP 1
425 #define CP_MACCP 2
426#endif
427
428/* Get charset from specified codepage.
429 g_FontTci is used also in TranslateCharsetInfo. */
431{
432 UINT i;
433
434 if (uCodePage == CP_OEMCP)
435 return OEM_CHARSET;
436
437 if (uCodePage == CP_MACCP)
438 return MAC_CHARSET;
439
440 for (i = 0; i < MAXTCIINDEX; ++i)
441 {
442 if (g_FontTci[i].ciACP == 0)
443 continue;
444
445 if (g_FontTci[i].ciACP == uCodePage)
446 return g_FontTci[i].ciCharset;
447 }
448
449 return DEFAULT_CHARSET;
450}
451
452static __inline VOID
453FindBestFontFromList(FONTOBJ **FontObj, ULONG *MatchPenalty,
454 const LOGFONTW *LogFont,
455 const PLIST_ENTRY Head);
456
458
459static BOOL
461 _Inout_ PFONTLINK pFontLink)
462{
464
465 if (pFontLink->bIgnore)
466 return FALSE;
467 if (pFontLink->SharedFace)
468 return TRUE;
469
470 PSHARED_FACE SharedFace = IntRealizeFont(&pFontLink->LogFont, NULL);
471 if (!SharedFace) // Not found?
472 {
473 pFontLink->bIgnore = TRUE;
474 return FALSE;
475 }
476
477 pFontLink->SharedFace = SharedFace;
478 return TRUE;
479}
480
481/* list head */
482static RTL_STATIC_LIST_HEAD(g_FontSubstListHead);
483
484static void
486{
488
489 ++Ptr->RefCount;
490}
491
492static void
494{
495 Cache->OutlineRequiredSize = 0;
496 RtlInitUnicodeString(&Cache->FontFamily, NULL);
497 RtlInitUnicodeString(&Cache->FullName, NULL);
498}
499
500static PSHARED_FACE
502{
505 if (Ptr)
506 {
507 Ptr->Face = Face;
508 Ptr->RefCount = 1;
509 Ptr->Memory = Memory;
510 SharedFaceCache_Init(&Ptr->EnglishUS);
511 SharedFaceCache_Init(&Ptr->UserLanguage);
512
514 DPRINT("Creating SharedFace for %s\n", Face->family_name ? Face->family_name : "<NULL>");
515 }
516 return Ptr;
517}
518
519static PSHARED_MEM
521{
524 if (Ptr)
525 {
526 Ptr->Buffer = Buffer;
527 Ptr->BufferSize = BufferSize;
528 Ptr->RefCount = 1;
529 Ptr->IsMapping = IsMapping;
530 DPRINT("Creating SharedMem for %p (%i, %p)\n", Buffer, IsMapping, Ptr);
531 }
532 return Ptr;
533}
534
535static void
537{
539
540 ++Ptr->RefCount;
541}
542
543static void
545{
547
548 FT_Done_Glyph((FT_Glyph)Entry->BitmapGlyph);
549 RemoveEntryList(&Entry->ListEntry);
553}
554
555static void
557{
558 PLIST_ENTRY CurrentEntry, NextEntry;
559 PFONT_CACHE_ENTRY FontEntry;
560
562
563 for (CurrentEntry = g_FontCacheListHead.Flink;
564 CurrentEntry != &g_FontCacheListHead;
565 CurrentEntry = NextEntry)
566 {
567 FontEntry = CONTAINING_RECORD(CurrentEntry, FONT_CACHE_ENTRY, ListEntry);
568 NextEntry = CurrentEntry->Flink;
569
570 if (FontEntry->Hashed.Face == Face)
571 {
572 RemoveCachedEntry(FontEntry);
573 }
574 }
575}
576
578{
580 ASSERT(Ptr->RefCount > 0);
581
582 if (Ptr->RefCount <= 0)
583 return;
584
585 --Ptr->RefCount;
586 if (Ptr->RefCount == 0)
587 {
588 DPRINT("Releasing SharedMem for %p (%i, %p)\n", Ptr->Buffer, Ptr->IsMapping, Ptr);
589 if (Ptr->IsMapping)
591 else
594 }
595}
596
597static void
599{
600 RtlFreeUnicodeString(&Cache->FontFamily);
601 RtlFreeUnicodeString(&Cache->FullName);
602}
603
604static void
606{
607 if (bDoLock)
609
610 ASSERT(Ptr->RefCount > 0);
611
612 if (Ptr->RefCount <= 0)
613 return;
614
615 --Ptr->RefCount;
616 if (Ptr->RefCount == 0)
617 {
618 DPRINT("Releasing SharedFace for %s\n", Ptr->Face->family_name ? Ptr->Face->family_name : "<NULL>");
619 RemoveCacheEntries(Ptr->Face);
620 FT_Done_Face(Ptr->Face);
621 SharedMem_Release(Ptr->Memory);
622 SharedFaceCache_Release(&Ptr->EnglishUS);
623 SharedFaceCache_Release(&Ptr->UserLanguage);
625 }
626
627 if (bDoLock)
629}
630
631
632static VOID FASTCALL
634{
635 // PFONTGDI FontGDI = FontEntry->Font;
636 PSHARED_FACE SharedFace = FontGDI->SharedFace;
637
638 if (FontGDI->Filename)
640
641 if (FontEntry->StyleName.Buffer)
642 RtlFreeUnicodeString(&FontEntry->StyleName);
643
644 if (FontEntry->FaceName.Buffer)
645 RtlFreeUnicodeString(&FontEntry->FaceName);
646
647 EngFreeMem(FontGDI);
648 SharedFace_Release(SharedFace, TRUE);
649 ExFreePoolWithTag(FontEntry, TAG_FONT);
650}
651
654{
655 CleanupFontEntryEx(FontEntry, FontEntry->Font);
656}
657
659{
660 pt->x.value = vec->x >> 6;
661 pt->x.fract = (vec->x & 0x3f) << 10;
662 pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
663 pt->y.value = vec->y >> 6;
664 pt->y.fract = (vec->y & 0x3f) << 10;
665 pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
666}
667
668/*
669 This function builds an FT_Fixed from a FIXED. It simply put f.value
670 in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed.
671*/
673{
674 return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract);
675}
676
677#if DBG
678VOID DumpFontEntry(PFONT_ENTRY FontEntry)
679{
680 const char *family_name;
681 const char *style_name;
682 FT_Face Face;
683 PFONTGDI FontGDI = FontEntry->Font;
684
685 if (!FontGDI)
686 {
687 DPRINT("FontGDI NULL\n");
688 return;
689 }
690
691 Face = (FontGDI->SharedFace ? FontGDI->SharedFace->Face : NULL);
692 if (Face)
693 {
694 family_name = Face->family_name;
695 style_name = Face->style_name;
696 }
697 else
698 {
699 family_name = "<invalid>";
700 style_name = "<invalid>";
701 }
702
703 DPRINT("family_name '%s', style_name '%s', FaceName '%wZ', StyleName '%wZ', FontGDI %p, "
704 "FontObj %p, iUnique %lu, SharedFace %p, Face %p, CharSet %u, Filename '%S'\n",
706 style_name,
707 &FontEntry->FaceName,
708 &FontEntry->StyleName,
709 FontGDI,
710 &FontGDI->FontObj,
711 FontGDI->iUnique,
712 FontGDI->SharedFace,
713 Face,
714 FontGDI->CharSet,
715 FontGDI->Filename);
716}
717
718VOID DumpFontList(PLIST_ENTRY Head)
719{
721 PFONT_ENTRY CurrentEntry;
722
723 DPRINT("## DumpFontList(%p)\n", Head);
724
725 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
726 {
727 CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
728 DumpFontEntry(CurrentEntry);
729 }
730}
731
732VOID DumpFontSubstEntry(PFONTSUBST_ENTRY pSubstEntry)
733{
734 DPRINT("%wZ,%u -> %wZ,%u\n",
735 &pSubstEntry->FontNames[FONTSUBST_FROM],
736 pSubstEntry->CharSets[FONTSUBST_FROM],
737 &pSubstEntry->FontNames[FONTSUBST_TO],
738 pSubstEntry->CharSets[FONTSUBST_TO]);
739}
740
741VOID DumpFontSubstList(VOID)
742{
743 PLIST_ENTRY pHead = &g_FontSubstListHead;
744 PLIST_ENTRY pListEntry;
745 PFONTSUBST_ENTRY pSubstEntry;
746
747 DPRINT("## DumpFontSubstList\n");
748
749 for (pListEntry = pHead->Flink;
750 pListEntry != pHead;
751 pListEntry = pListEntry->Flink)
752 {
753 pSubstEntry = CONTAINING_RECORD(pListEntry, FONTSUBST_ENTRY, ListEntry);
754 DumpFontSubstEntry(pSubstEntry);
755 }
756}
757
758VOID DumpPrivateFontList(BOOL bDoLock)
759{
761
762 if (!Win32Process)
763 return;
764
765 if (bDoLock)
766 {
768 IntLockProcessPrivateFonts(Win32Process);
769 }
770
771 DumpFontList(&Win32Process->PrivateFontListHead);
772
773 if (bDoLock)
774 {
775 IntUnLockProcessPrivateFonts(Win32Process);
777 }
778}
779
780VOID DumpGlobalFontList(BOOL bDoLock)
781{
782 if (bDoLock)
784
785 DumpFontList(&g_FontListHead);
786
787 if (bDoLock)
789}
790
791VOID DumpFontInfo(BOOL bDoLock)
792{
793 DumpGlobalFontList(bDoLock);
794 DumpPrivateFontList(bDoLock);
795 DumpFontSubstList();
796}
797#endif
798
799/*
800 * IntLoadFontSubstList --- loads the list of font substitutes
801 */
804{
808 KEY_FULL_INFORMATION KeyFullInfo;
809 ULONG i, Length;
810 UNICODE_STRING FromW, ToW;
811 BYTE InfoBuffer[128];
813 BYTE CharSets[FONTSUBST_FROM_AND_TO];
814 LPWSTR pch;
816
817 /* the FontSubstitutes registry key */
818 static UNICODE_STRING FontSubstKey =
819 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\"
820 L"Microsoft\\Windows NT\\CurrentVersion\\"
821 L"FontSubstitutes");
822
823 /* open registry key */
826 NULL, NULL);
827 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
828 if (!NT_SUCCESS(Status))
829 {
830 DPRINT("ZwOpenKey failed: 0x%08X\n", Status);
831 return FALSE; /* failure */
832 }
833
834 /* query count of values */
835 Status = ZwQueryKey(KeyHandle, KeyFullInformation,
836 &KeyFullInfo, sizeof(KeyFullInfo), &Length);
837 if (!NT_SUCCESS(Status))
838 {
839 DPRINT("ZwQueryKey failed: 0x%08X\n", Status);
841 return FALSE; /* failure */
842 }
843
844 /* for each value */
845 for (i = 0; i < KeyFullInfo.Values; ++i)
846 {
847 /* get value name */
848 Status = ZwEnumerateValueKey(KeyHandle, i, KeyValueFullInformation,
849 InfoBuffer, sizeof(InfoBuffer), &Length);
850 if (!NT_SUCCESS(Status))
851 {
852 DPRINT("ZwEnumerateValueKey failed: 0x%08X\n", Status);
853 break; /* failure */
854 }
855
856 /* create FromW string */
857 pInfo = (PKEY_VALUE_FULL_INFORMATION)InfoBuffer;
858 Length = pInfo->NameLength / sizeof(WCHAR);
859 pInfo->Name[Length] = UNICODE_NULL; /* truncate */
860 if (!RtlCreateUnicodeString(&FromW, pInfo->Name))
861 {
863 DPRINT("RtlCreateUnicodeString failed\n");
864 break; /* failure */
865 }
866
867 /* query value */
868 Status = ZwQueryValueKey(KeyHandle, &FromW, KeyValueFullInformation,
869 InfoBuffer, sizeof(InfoBuffer), &Length);
870 pInfo = (PKEY_VALUE_FULL_INFORMATION)InfoBuffer;
871 if (!NT_SUCCESS(Status) || !pInfo->DataLength)
872 {
873 DPRINT("ZwQueryValueKey failed: 0x%08X\n", Status);
874 RtlFreeUnicodeString(&FromW);
875 break; /* failure */
876 }
877
878 /* create ToW string */
879 pch = (LPWSTR)((PUCHAR)pInfo + pInfo->DataOffset);
880 Length = pInfo->DataLength / sizeof(WCHAR);
881 pch[Length] = UNICODE_NULL; /* truncate */
882 if (!RtlCreateUnicodeString(&ToW, pch))
883 {
885 DPRINT("RtlCreateUnicodeString failed\n");
886 RtlFreeUnicodeString(&FromW);
887 break; /* failure */
888 }
889
890 /* does charset exist? (from) */
892 pch = wcsrchr(FromW.Buffer, L',');
893 if (pch)
894 {
895 /* truncate */
896 *pch = UNICODE_NULL;
897 FromW.Length = (pch - FromW.Buffer) * sizeof(WCHAR);
898 /* parse charset number */
899 CharSets[FONTSUBST_FROM] = (BYTE)_wtoi(pch + 1);
900 }
901
902 /* does charset exist? (to) */
903 CharSets[FONTSUBST_TO] = DEFAULT_CHARSET;
904 pch = wcsrchr(ToW.Buffer, L',');
905 if (pch)
906 {
907 /* truncate */
908 *pch = UNICODE_NULL;
909 ToW.Length = (pch - ToW.Buffer) * sizeof(WCHAR);
910 /* parse charset number */
911 CharSets[FONTSUBST_TO] = (BYTE)_wtoi(pch + 1);
912 }
913
914 /* is it identical? */
915 if (RtlEqualUnicodeString(&FromW, &ToW, TRUE) &&
916 CharSets[FONTSUBST_FROM] == CharSets[FONTSUBST_TO])
917 {
918 RtlFreeUnicodeString(&FromW);
920 continue;
921 }
922
923 /* allocate an entry */
925 if (pEntry == NULL)
926 {
927 DPRINT("ExAllocatePoolWithTag failed\n");
928 RtlFreeUnicodeString(&FromW);
930 break; /* failure */
931 }
932
933 /* store to *pEntry */
934 pEntry->FontNames[FONTSUBST_FROM] = FromW;
935 pEntry->FontNames[FONTSUBST_TO] = ToW;
936 pEntry->CharSets[FONTSUBST_FROM] = CharSets[FONTSUBST_FROM];
937 pEntry->CharSets[FONTSUBST_TO] = CharSets[FONTSUBST_TO];
938
939 /* insert pEntry to *pHead */
940 InsertTailList(pHead, &pEntry->ListEntry);
941 }
942
943 /* close now */
945
946 return NT_SUCCESS(Status);
947}
948
949static void
951{
955}
956
957static void
959 _In_ BOOL bDoLock,
960 _Inout_opt_ PSHARED_FACE SharedFace)
961{
962 if (bDoLock)
964
965 PLIST_ENTRY pHead = &s_FontLookupCacheList, pEntry;
966 PFONT_LOOKUP_CACHE pCache;
967
968 if (SharedFace)
969 {
970 for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink)
971 {
972 pCache = CONTAINING_RECORD(pEntry, FONT_LOOKUP_CACHE, ListEntry);
973 if (pCache->SharedFace == SharedFace)
974 {
975 RemoveEntryList(&pCache->ListEntry);
976 FontLookUp_Destroy(pCache);
978 }
979 }
980 }
981 else
982 {
983 while (!IsListEmpty(pHead))
984 {
985 pEntry = RemoveHeadList(pHead);
986 pCache = CONTAINING_RECORD(pEntry, FONT_LOOKUP_CACHE, ListEntry);
987 FontLookUp_Destroy(pCache);
988 }
990 }
991
992 if (bDoLock)
994}
995
998{
999 ULONG ulError;
1000
1002
1004 if (g_FreeTypeLock == NULL)
1005 {
1006 return FALSE;
1007 }
1009
1011 if (ulError)
1012 {
1013 DPRINT1("FT_Init_FreeType failed with error code 0x%x\n", ulError);
1014 return FALSE;
1015 }
1016
1018 {
1019 DPRINT1("Fonts registry is empty.\n");
1020
1021 /* Load font(s) with writing registry */
1023 }
1024
1025 IntLoadFontSubstList(&g_FontSubstListHead);
1026
1027#if 0
1028 DumpFontInfo(TRUE);
1029#endif
1030
1034
1035 return TRUE;
1036}
1037
1040{
1041 PLIST_ENTRY pHead, pEntry;
1042 PFONT_CACHE_ENTRY pFontCache;
1043 PFONTSUBST_ENTRY pSubstEntry;
1044 PFONT_ENTRY pFontEntry;
1045
1046 // Cleanup the FontLink cache
1048
1049 // Cleanup FONT_LOOKUP_CACHE
1051
1052 // Free font cache list
1053 pHead = &g_FontCacheListHead;
1054 while (!IsListEmpty(pHead))
1055 {
1056 pEntry = RemoveHeadList(pHead);
1057 pFontCache = CONTAINING_RECORD(pEntry, FONT_CACHE_ENTRY, ListEntry);
1058 RemoveCachedEntry(pFontCache);
1059 }
1060
1061 // Free font subst list
1062 pHead = &g_FontSubstListHead;
1063 while (!IsListEmpty(pHead))
1064 {
1065 pEntry = RemoveHeadList(pHead);
1066 pSubstEntry = CONTAINING_RECORD(pEntry, FONTSUBST_ENTRY, ListEntry);
1067 ExFreePoolWithTag(pSubstEntry, TAG_FONT);
1068 }
1069
1070 // Free font list
1071 pHead = &g_FontListHead;
1072 while (!IsListEmpty(pHead))
1073 {
1074 pEntry = RemoveHeadList(pHead);
1075 pFontEntry = CONTAINING_RECORD(pEntry, FONT_ENTRY, ListEntry);
1076 CleanupFontEntry(pFontEntry);
1077 }
1078
1080 {
1083 }
1084
1087}
1088
1089static VOID FASTCALL IntEscapeMatrix(FT_Matrix *pmat, LONG lfEscapement)
1090{
1091 FT_Vector vecAngle;
1092 /* Convert the angle in tenths of degrees into degrees as a 16.16 fixed-point value */
1093 FT_Angle angle = INT_TO_FIXED(lfEscapement) / 10;
1094 FT_Vector_Unit(&vecAngle, angle);
1095 pmat->xx = vecAngle.x;
1096 pmat->xy = -vecAngle.y;
1097 pmat->yx = -pmat->xy;
1098 pmat->yy = pmat->xx;
1099}
1100
1101static VOID FASTCALL
1103{
1104 FLOATOBJ ef;
1105
1106 /* Create a freetype matrix, by converting to 16.16 fixpoint format */
1107 ef = pmx->efM11;
1108 FLOATOBJ_MulLong(&ef, 0x00010000);
1109 pmat->xx = FLOATOBJ_GetLong(&ef);
1110
1111 ef = pmx->efM21;
1112 FLOATOBJ_MulLong(&ef, 0x00010000);
1113 pmat->xy = -FLOATOBJ_GetLong(&ef); /* (*1) See below */
1114
1115 ef = pmx->efM12;
1116 FLOATOBJ_MulLong(&ef, 0x00010000);
1117 pmat->yx = -FLOATOBJ_GetLong(&ef); /* (*1) See below */
1118
1119 ef = pmx->efM22;
1120 FLOATOBJ_MulLong(&ef, 0x00010000);
1121 pmat->yy = FLOATOBJ_GetLong(&ef);
1122
1123 // (*1): Y direction is mirrored as follows:
1124 //
1125 // [ M11 -M12 ] [ X ] [ M11*X + M12*Y ]
1126 // [ ] * [ ] == [ ]
1127 // [ -M21 M22 ] [ -Y ] [ -(M21*X + M22*Y) ].
1128}
1129
1130static BOOL
1132 PUNICODE_STRING pOutputName,
1133 PUNICODE_STRING pInputName,
1134 BYTE RequestedCharSet,
1135 BYTE CharSetMap[FONTSUBST_FROM_AND_TO])
1136{
1137 PLIST_ENTRY pListEntry;
1138 PFONTSUBST_ENTRY pSubstEntry;
1139 BYTE CharSets[FONTSUBST_FROM_AND_TO];
1140
1141 CharSetMap[FONTSUBST_FROM] = DEFAULT_CHARSET;
1142 CharSetMap[FONTSUBST_TO] = RequestedCharSet;
1143
1144 /* for each list entry */
1145 for (pListEntry = pHead->Flink;
1146 pListEntry != pHead;
1147 pListEntry = pListEntry->Flink)
1148 {
1149 pSubstEntry = CONTAINING_RECORD(pListEntry, FONTSUBST_ENTRY, ListEntry);
1150
1151 CharSets[FONTSUBST_FROM] = pSubstEntry->CharSets[FONTSUBST_FROM];
1152
1153 if (CharSets[FONTSUBST_FROM] != DEFAULT_CHARSET &&
1154 CharSets[FONTSUBST_FROM] != RequestedCharSet)
1155 {
1156 continue; /* not matched */
1157 }
1158
1159 /* does charset number exist? (to) */
1160 if (pSubstEntry->CharSets[FONTSUBST_TO] != DEFAULT_CHARSET)
1161 {
1162 CharSets[FONTSUBST_TO] = pSubstEntry->CharSets[FONTSUBST_TO];
1163 }
1164 else
1165 {
1166 CharSets[FONTSUBST_TO] = RequestedCharSet;
1167 }
1168
1169 /* does font name match? */
1171 pInputName, TRUE))
1172 {
1173 continue; /* not matched */
1174 }
1175
1176 /* update *pOutputName */
1177 *pOutputName = pSubstEntry->FontNames[FONTSUBST_TO];
1178
1179 if (CharSetMap[FONTSUBST_FROM] == DEFAULT_CHARSET)
1180 {
1181 /* update CharSetMap */
1182 CharSetMap[FONTSUBST_FROM] = CharSets[FONTSUBST_FROM];
1183 CharSetMap[FONTSUBST_TO] = CharSets[FONTSUBST_TO];
1184 }
1185 return TRUE; /* success */
1186 }
1187
1188 return FALSE;
1189}
1190
1191static BOOL
1193{
1194 UINT RecurseCount = 5;
1195 UNICODE_STRING OutputNameW = { 0 };
1196 BYTE CharSetMap[FONTSUBST_FROM_AND_TO];
1197 BOOL Found;
1198 UNICODE_STRING InputNameW;
1199
1200 if (pLogFont->lfFaceName[0] == UNICODE_NULL)
1201 return FALSE;
1202
1203 RtlInitUnicodeString(&InputNameW, pLogFont->lfFaceName);
1204
1205 while (RecurseCount-- > 0)
1206 {
1207 Found = SubstituteFontByList(&g_FontSubstListHead,
1208 &OutputNameW, &InputNameW,
1209 pLogFont->lfCharSet, CharSetMap);
1210 if (!Found)
1211 break;
1212
1213 IntUnicodeStringToBuffer(pLogFont->lfFaceName, sizeof(pLogFont->lfFaceName), &OutputNameW);
1214 RtlInitUnicodeString(&InputNameW, pLogFont->lfFaceName);
1215
1216 if (CharSetMap[FONTSUBST_FROM] == DEFAULT_CHARSET ||
1217 CharSetMap[FONTSUBST_FROM] == pLogFont->lfCharSet)
1218 {
1219 pLogFont->lfCharSet = CharSetMap[FONTSUBST_TO];
1220 }
1221 }
1222
1223 return TRUE; /* success */
1224}
1225
1226// Quickly initialize a FONTLINK_CHAIN
1227static inline VOID
1229 _Out_ PFONTLINK_CHAIN pChain,
1230 _Inout_ PTEXTOBJ pTextObj,
1232{
1233 RtlZeroMemory(pChain, sizeof(*pChain));
1234 pChain->pBaseTextObj = pTextObj;
1235 pChain->pDefFace = face;
1237}
1238
1239// The default FontLink data
1240static const WCHAR s_szzDefFontLink[] =
1241 L"tahoma.ttf,Tahoma\0"
1242 L"msgothic.ttc,MS UI Gothic\0"
1243 L"mingliu.ttc,PMingLiU\0"
1244 L"simsun.ttc,SimSun\0"
1245 L"gulim.ttc,Gulim\0"
1246 L"\0";
1247// The default fixed-pitch FontLink data
1249 L"cour.ttf,Courier New\0"
1250 L"msgothic.ttc,MS Gothic\0"
1251 L"mingliu.ttc,MingLiU\0"
1252 L"simsun.ttc,NSimSun\0"
1253 L"gulim.ttc,GulimChe\0"
1254 L"\0";
1255
1256static NTSTATUS
1258 _Inout_ PFONTLINK_CHAIN pChain,
1259 _Inout_ PLOGFONTW pLF)
1260{
1262 HKEY hKey;
1263 DWORD cbData;
1264 WCHAR szzFontLink[512];
1265 SIZE_T FontLinkSize;
1266 PZZWSTR pszzFontLink = NULL;
1267
1268 ASSERT(pLF->lfFaceName[0]);
1269
1270 // Open the registry key
1272 L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",
1273 &hKey);
1274 if (!NT_SUCCESS(Status))
1275 return Status;
1276
1277 // Load the FontLink entry
1278 cbData = sizeof(szzFontLink);
1279 Status = RegQueryValue(hKey, pLF->lfFaceName, REG_MULTI_SZ, szzFontLink, &cbData);
1280 if (!NT_SUCCESS(Status) &&
1282 {
1283 // Retry with substituted
1285 cbData = sizeof(szzFontLink);
1286 Status = RegQueryValue(hKey, pLF->lfFaceName, REG_MULTI_SZ, szzFontLink, &cbData);
1287 }
1288
1290 {
1291 // Buffer is too small. Retry with larger buffer
1292 if (cbData >= 2 * sizeof(WCHAR)) // Sanity check
1293 {
1294 FontLinkSize = cbData;
1295 pszzFontLink = ExAllocatePoolWithTag(PagedPool, FontLinkSize, TAG_FONT);
1296 if (!pszzFontLink)
1297 {
1298 ZwClose(hKey); // Close the registry key
1299 return STATUS_NO_MEMORY;
1300 }
1301 Status = RegQueryValue(hKey, pLF->lfFaceName, REG_MULTI_SZ, pszzFontLink, &cbData);
1302 if (!NT_SUCCESS(Status))
1303 {
1304 ExFreePoolWithTag(pszzFontLink, TAG_FONT);
1305 pszzFontLink = NULL;
1306 }
1307 }
1308 }
1309
1310 ZwClose(hKey); // Close the registry key
1311
1312 if (!NT_SUCCESS(Status)) // Failed to get registry value
1313 {
1314 // Use default value
1315 ASSERT(sizeof(szzFontLink) >= sizeof(s_szzDefFontLink));
1316 ASSERT(sizeof(szzFontLink) >= sizeof(s_szzDefFixedFontLink));
1317 if (!(pLF->lfPitchAndFamily & FIXED_PITCH))
1318 RtlCopyMemory(szzFontLink, s_szzDefFontLink, sizeof(s_szzDefFontLink));
1319 else
1321 }
1322
1323 if (pszzFontLink)
1324 {
1325 // Ensure double-NUL-terminated
1326 ASSERT(FontLinkSize / sizeof(WCHAR) >= 2);
1327 pszzFontLink[FontLinkSize / sizeof(WCHAR) - 1] = UNICODE_NULL;
1328 pszzFontLink[FontLinkSize / sizeof(WCHAR) - 2] = UNICODE_NULL;
1329 }
1330 else
1331 {
1332 // Ensure double-NUL-terminated
1333 szzFontLink[_countof(szzFontLink) - 1] = UNICODE_NULL;
1334 szzFontLink[_countof(szzFontLink) - 2] = UNICODE_NULL;
1335
1336 FontLinkSize = SZZ_GetSize(szzFontLink);
1337 pszzFontLink = ExAllocatePoolWithTag(PagedPool, FontLinkSize, TAG_FONT);
1338 if (!pszzFontLink)
1339 return STATUS_NO_MEMORY;
1340 RtlCopyMemory(pszzFontLink, szzFontLink, FontLinkSize);
1341 }
1342 pChain->pszzFontLink = pszzFontLink;
1343
1344 return STATUS_SUCCESS;
1345}
1346
1347static inline PFONTLINK
1349 PFONTLINK_CHAIN pChain,
1350 PLOGFONTW plf)
1351{
1352 PLIST_ENTRY Entry, Head = &pChain->FontLinkList;
1353 PFONTLINK pLink;
1354
1355 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
1356 {
1357 pLink = CONTAINING_RECORD(Entry, FONTLINK, ListEntry);
1358 if (RtlEqualMemory(&pLink->LogFont, plf, sizeof(*plf)))
1359 return pLink;
1360 }
1361
1362 return NULL;
1363}
1364
1365static inline PFONTLINK
1367 _Inout_ PFONTLINK_CHAIN pChain,
1368 _In_ const LOGFONTW *plfBase,
1369 _In_ LPCWSTR pszLink)
1370{
1371 LPWSTR pch0, pch1;
1372 LOGFONTW lf;
1373 PFONTLINK pLink;
1374
1375 lf = *plfBase;
1376
1377 // pszLink: "<FontFileName>,<FaceName>[,...]"
1378 pch0 = wcschr(pszLink, L',');
1379 if (!pch0)
1380 {
1381 DPRINT1("%S\n", pszLink);
1382 return NULL; // Invalid FontLink data
1383 }
1384 ++pch0;
1385
1386 pch1 = wcschr(pch0, L',');
1387 if (pch1)
1388 RtlStringCchCopyNW(lf.lfFaceName, _countof(lf.lfFaceName), pch0, pch1 - pch0);
1389 else
1391
1393 DPRINT("lfFaceName: %S\n", lf.lfFaceName);
1394
1395 if (RtlEqualMemory(plfBase, &lf, sizeof(lf)) || FontLink_Chain_FindLink(pChain, &lf))
1396 return NULL; // Already exists
1397
1398 pLink = ExAllocatePoolZero(PagedPool, sizeof(FONTLINK), TAG_FONT);
1399 if (!pLink)
1400 return NULL; // Out of memory
1401
1402 pLink->LogFont = lf;
1403 return pLink;
1404}
1405
1406static NTSTATUS
1408 _Inout_ PFONTLINK_CHAIN pChain)
1409{
1411 PFONTLINK pLink;
1412 LOGFONTW lfBase;
1413 PTEXTOBJ pTextObj = pChain->pBaseTextObj;
1414 PFONTGDI pFontGDI;
1415 PWSTR pszLink;
1416 PFONTLINK_CACHE pLinkCache;
1417 WCHAR szEntry[MAX_PATH];
1418 BOOL bFixCharSet;
1419
1420 InitializeListHead(&pChain->FontLinkList);
1421
1422 lfBase = pTextObj->logfont.elfEnumLogfontEx.elfLogFont;
1423 pFontGDI = ObjToGDI(pTextObj->Font, FONT);
1424 lfBase.lfHeight = pFontGDI->lfHeight;
1425 lfBase.lfWidth = pFontGDI->lfWidth;
1426
1427 // Use pTextObj->TextFace if lfFaceName was empty
1428 if (!lfBase.lfFaceName[0])
1429 {
1430 ASSERT(pTextObj->TextFace[0]);
1431 RtlStringCchCopyW(lfBase.lfFaceName, _countof(lfBase.lfFaceName), pTextObj->TextFace);
1432 }
1433
1434 // Fix lfCharSet
1435 switch (lfBase.lfCharSet)
1436 {
1437 case ANSI_CHARSET: bFixCharSet = !s_fFontLinkUseAnsi; break;
1438 case OEM_CHARSET: bFixCharSet = !s_fFontLinkUseOem; break;
1439 case SYMBOL_CHARSET: bFixCharSet = !s_fFontLinkUseSymbol; break;
1440 default: bFixCharSet = TRUE; break;
1441 }
1442 if (bFixCharSet)
1443 lfBase.lfCharSet = DEFAULT_CHARSET;
1444
1445 // Use cache if any
1446 pLinkCache = FontLink_FindCache(&lfBase);
1447 if (pLinkCache)
1448 {
1449 RemoveEntryList(&pLinkCache->ListEntry);
1450 *pChain = pLinkCache->Chain;
1451 IntRebaseList(&pChain->FontLinkList, &pLinkCache->Chain.FontLinkList);
1452 ExFreePoolWithTag(pLinkCache, TAG_FONT);
1453 return STATUS_SUCCESS;
1454 }
1455
1456 pChain->LogFont = lfBase;
1457
1458 // Load FontLink entry from registry
1459 Status = FontLink_Chain_LoadReg(pChain, &pChain->LogFont);
1460 if (!NT_SUCCESS(Status))
1461 return Status;
1462
1463 pszLink = pChain->pszzFontLink;
1464 while (*pszLink)
1465 {
1466 DPRINT("pszLink: '%S'\n", pszLink);
1467 pLink = FontLink_Create(pChain, &lfBase, pszLink);
1468 if (pLink)
1469 InsertTailList(&pChain->FontLinkList, &pLink->ListEntry);
1470 pszLink += wcslen(pszLink) + 1;
1471 }
1472
1473 // Use default settings (if any)
1475 {
1477 RtlStringCchCatW(szEntry, _countof(szEntry), L",");
1479 DPRINT("szEntry: '%S'\n", szEntry);
1480 pLink = FontLink_Create(pChain, &lfBase, szEntry);
1481 if (pLink)
1482 InsertTailList(&pChain->FontLinkList, &pLink->ListEntry);
1483 }
1484
1486 return Status;
1487}
1488
1489/*
1490 * IntLoadSystemFonts
1491 *
1492 * Search the system font directory and adds each font found.
1493 */
1496{
1498 UNICODE_STRING Directory, FileName, TempString;
1500 HANDLE hDirectory;
1501 BYTE *DirInfoBuffer;
1503 BOOLEAN bRestartScan = TRUE;
1505 INT i;
1506 static UNICODE_STRING SearchPatterns[] =
1507 {
1508 RTL_CONSTANT_STRING(L"*.ttf"),
1509 RTL_CONSTANT_STRING(L"*.ttc"),
1510 RTL_CONSTANT_STRING(L"*.otf"),
1511 RTL_CONSTANT_STRING(L"*.otc"),
1512 RTL_CONSTANT_STRING(L"*.fon"),
1513 RTL_CONSTANT_STRING(L"*.fnt")
1514 };
1515 static UNICODE_STRING IgnoreFiles[] =
1516 {
1519 };
1520
1521 RtlInitUnicodeString(&Directory, L"\\SystemRoot\\Fonts\\");
1522
1525 &Directory,
1527 NULL,
1528 NULL);
1529
1531 &hDirectory,
1534 &Iosb,
1537
1538 if (NT_SUCCESS(Status))
1539 {
1540 for (i = 0; i < _countof(SearchPatterns); ++i)
1541 {
1542 DirInfoBuffer = ExAllocatePoolWithTag(PagedPool, 0x4000, TAG_FONT);
1543 if (DirInfoBuffer == NULL)
1544 {
1545 ZwClose(hDirectory);
1546 return;
1547 }
1548
1550 if (FileName.Buffer == NULL)
1551 {
1552 ExFreePoolWithTag(DirInfoBuffer, TAG_FONT);
1553 ZwClose(hDirectory);
1554 return;
1555 }
1556 FileName.Length = 0;
1557 FileName.MaximumLength = MAX_PATH * sizeof(WCHAR);
1558
1559 while (1)
1560 {
1561 Status = ZwQueryDirectoryFile(
1562 hDirectory,
1563 NULL,
1564 NULL,
1565 NULL,
1566 &Iosb,
1567 DirInfoBuffer,
1568 0x4000,
1570 FALSE,
1571 &SearchPatterns[i],
1572 bRestartScan);
1573
1575 {
1576 break;
1577 }
1578
1579 DirInfo = (PFILE_DIRECTORY_INFORMATION)DirInfoBuffer;
1580 while (1)
1581 {
1582 SIZE_T ign;
1583
1584 TempString.Buffer = DirInfo->FileName;
1585 TempString.Length = TempString.MaximumLength = DirInfo->FileNameLength;
1586
1587 /* Should we ignore this file? */
1588 for (ign = 0; ign < _countof(IgnoreFiles); ++ign)
1589 {
1590 /* Yes.. */
1591 if (RtlEqualUnicodeString(IgnoreFiles + ign, &TempString, FALSE))
1592 break;
1593 }
1594
1595 /* If we tried all Ignore patterns and there was no match, try to create a font */
1596 if (ign == _countof(IgnoreFiles))
1597 {
1601 DPRINT1("ERR: Failed to load %wZ\n", &FileName);
1602 }
1603
1604 if (DirInfo->NextEntryOffset == 0)
1605 break;
1606
1607 DirInfo = (PFILE_DIRECTORY_INFORMATION)((ULONG_PTR)DirInfo + DirInfo->NextEntryOffset);
1608 }
1609
1610 bRestartScan = FALSE;
1611 }
1612
1614 ExFreePoolWithTag(DirInfoBuffer, TAG_FONT);
1615 }
1616 ZwClose(hDirectory);
1617 }
1618}
1619
1620/* NOTE: If nIndex < 0 then return the number of charsets. */
1621UINT FASTCALL IntGetCharSet(INT nIndex, FT_ULong CodePageRange1)
1622{
1623 UINT BitIndex, CharSet;
1624 UINT nCount = 0;
1625
1626 if (CodePageRange1 == 0)
1627 return (nIndex < 0) ? 1 : DEFAULT_CHARSET;
1628
1629 for (BitIndex = 0; BitIndex < MAXTCIINDEX; ++BitIndex)
1630 {
1631 if (CodePageRange1 & (1 << BitIndex))
1632 {
1633 CharSet = g_FontTci[BitIndex].ciCharset;
1634 if ((nIndex >= 0) && (nCount == (UINT)nIndex))
1635 {
1636 return CharSet;
1637 }
1638 ++nCount;
1639 }
1640 }
1641
1642 return (nIndex < 0) ? nCount : ANSI_CHARSET;
1643}
1644
1645/* pixels to points */
1646#define PX2PT(pixels) FT_MulDiv((pixels), 72, 96)
1647
1648static INT FASTCALL
1650 PSHARED_FACE SharedFace, FT_Long FontIndex, INT CharSetIndex)
1651{
1654 FONT_ENTRY_MEM* PrivateEntry = NULL;
1655 FONTGDI * FontGDI;
1657 FT_Face Face;
1659 FT_WinFNT_HeaderRec WinFNT;
1660 INT FaceCount = 0, CharSetCount = 0;
1661 PUNICODE_STRING pFileName = pLoadFont->pFileName;
1662 DWORD Characteristics = pLoadFont->Characteristics;
1663 PUNICODE_STRING pValueName = &pLoadFont->RegValueName;
1664 TT_OS2 * pOS2;
1665 INT BitIndex;
1666 FT_UShort os2_version;
1667 FT_ULong os2_ulCodePageRange1;
1668 FT_UShort os2_usWeightClass;
1669
1670 ASSERT(SharedFace != NULL);
1671 ASSERT(FontIndex != -1);
1672
1674 Face = SharedFace->Face;
1675 SharedFace_AddRef(SharedFace);
1677
1678 /* allocate a FONT_ENTRY */
1680 if (!Entry)
1681 {
1682 SharedFace_Release(SharedFace, TRUE);
1684 return 0; /* failure */
1685 }
1686
1687 /* allocate a FONTGDI */
1688 FontGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(FONTGDI), GDITAG_RFONT);
1689 if (!FontGDI)
1690 {
1691 SharedFace_Release(SharedFace, TRUE);
1694 return 0; /* failure */
1695 }
1696
1697 /* set file name */
1698 if (pFileName)
1699 {
1701 pFileName->Length + sizeof(UNICODE_NULL),
1702 GDITAG_PFF);
1703 if (FontGDI->Filename == NULL)
1704 {
1705 EngFreeMem(FontGDI);
1706 SharedFace_Release(SharedFace, TRUE);
1709 return 0; /* failure */
1710 }
1711
1712 RtlCopyMemory(FontGDI->Filename, pFileName->Buffer, pFileName->Length);
1713 FontGDI->Filename[pFileName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1714 }
1715 else
1716 {
1717 FontGDI->Filename = NULL;
1718
1719 PrivateEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY_MEM), TAG_FONT);
1720 if (!PrivateEntry)
1721 {
1722 if (FontGDI->Filename)
1724 EngFreeMem(FontGDI);
1725 SharedFace_Release(SharedFace, TRUE);
1728 return 0; /* failure */
1729 }
1730
1731 PrivateEntry->Entry = Entry;
1732 if (pLoadFont->PrivateEntry)
1733 {
1734 InsertTailList(&pLoadFont->PrivateEntry->ListEntry, &PrivateEntry->ListEntry);
1735 }
1736 else
1737 {
1738 InitializeListHead(&PrivateEntry->ListEntry);
1739 pLoadFont->PrivateEntry = PrivateEntry;
1740 }
1741 }
1742
1743 /* set face */
1744 FontGDI->SharedFace = SharedFace;
1745 FontGDI->CharSet = ANSI_CHARSET;
1746 FontGDI->OriginalItalic = FALSE;
1747 FontGDI->RequestItalic = FALSE;
1748 FontGDI->OriginalWeight = FW_DONTCARE;
1749 FontGDI->RequestWeight = FW_NORMAL;
1750
1752 pOS2 = (TT_OS2 *)FT_Get_Sfnt_Table(Face, FT_SFNT_OS2);
1753 if (pOS2)
1754 {
1755 FontGDI->OriginalItalic = !!(pOS2->fsSelection & 0x1);
1756 FontGDI->OriginalWeight = pOS2->usWeightClass;
1757 }
1758 else
1759 {
1760 Error = FT_Get_WinFNT_Header(Face, &WinFNT);
1761 if (!Error)
1762 {
1763 FontGDI->OriginalItalic = !!WinFNT.italic;
1764 FontGDI->OriginalWeight = WinFNT.weight;
1765 }
1766 }
1768
1771 if (NT_SUCCESS(Status))
1772 {
1773 if (Face->style_name && Face->style_name[0] &&
1774 strcmp(Face->style_name, "Regular") != 0)
1775 {
1778 if (!NT_SUCCESS(Status))
1779 {
1780 RtlFreeUnicodeString(&Entry->FaceName);
1781 }
1782 }
1783 else
1784 {
1785 RtlInitUnicodeString(&Entry->StyleName, NULL);
1786 }
1787 }
1788 if (!NT_SUCCESS(Status))
1789 {
1790 if (PrivateEntry)
1791 {
1792 if (pLoadFont->PrivateEntry == PrivateEntry)
1793 {
1794 pLoadFont->PrivateEntry = NULL;
1795 }
1796 else
1797 {
1798 RemoveEntryList(&PrivateEntry->ListEntry);
1799 }
1800 ExFreePoolWithTag(PrivateEntry, TAG_FONT);
1801 }
1802 if (FontGDI->Filename)
1804 EngFreeMem(FontGDI);
1805 SharedFace_Release(SharedFace, TRUE);
1807 return 0;
1808 }
1809
1810 os2_version = 0;
1812 pOS2 = (TT_OS2 *)FT_Get_Sfnt_Table(Face, FT_SFNT_OS2);
1813 if (pOS2)
1814 {
1815 os2_version = pOS2->version;
1816 os2_ulCodePageRange1 = pOS2->ulCodePageRange1;
1817 os2_usWeightClass = pOS2->usWeightClass;
1818 }
1820
1821 if (pOS2 && os2_version >= 1)
1822 {
1823 /* get charset and weight from OS/2 header */
1824
1825 /* Make sure we do not use this pointer anymore */
1826 pOS2 = NULL;
1827
1828 for (BitIndex = 0; BitIndex < MAXTCIINDEX; ++BitIndex)
1829 {
1830 if (os2_ulCodePageRange1 & (1 << BitIndex))
1831 {
1832 if (g_FontTci[BitIndex].ciCharset == DEFAULT_CHARSET)
1833 continue;
1834
1835 if ((CharSetIndex == -1 && CharSetCount == 0) ||
1836 CharSetIndex == CharSetCount)
1837 {
1838 FontGDI->CharSet = g_FontTci[BitIndex].ciCharset;
1839 }
1840
1841 ++CharSetCount;
1842 }
1843 }
1844
1845 /* set actual weight */
1846 FontGDI->OriginalWeight = os2_usWeightClass;
1847 }
1848 else
1849 {
1850 /* get charset from WinFNT header */
1852 Error = FT_Get_WinFNT_Header(Face, &WinFNT);
1853 if (!Error)
1854 {
1855 FontGDI->CharSet = WinFNT.charset;
1856 }
1858 }
1859
1860 ++FaceCount;
1861 DPRINT("Font loaded: %s (%s)\n",
1862 Face->family_name ? Face->family_name : "<NULL>",
1863 Face->style_name ? Face->style_name : "<NULL>");
1864 DPRINT("Num glyphs: %d\n", Face->num_glyphs);
1865 DPRINT("CharSet: %d\n", FontGDI->CharSet);
1866
1867 /* Add this font resource to the font table */
1868 Entry->Font = FontGDI;
1869 Entry->NotEnum = (Characteristics & FR_NOT_ENUM);
1870
1872 if (Characteristics & FR_PRIVATE)
1873 {
1874 /* private font */
1876 IntLockProcessPrivateFonts(Win32Process);
1877 InsertTailList(&Win32Process->PrivateFontListHead, &Entry->ListEntry);
1878 IntUnLockProcessPrivateFonts(Win32Process);
1879 }
1880 else
1881 {
1882 /* global font */
1883 InsertTailList(&g_FontListHead, &Entry->ListEntry);
1884 }
1886
1887 if (CharSetIndex == -1)
1888 {
1889 INT i;
1890 USHORT NameLength = Entry->FaceName.Length;
1891
1892 if (Entry->StyleName.Length)
1893 NameLength += Entry->StyleName.Length + sizeof(WCHAR);
1894
1895 if (pLoadFont->RegValueName.Length == 0)
1896 {
1897 pValueName->Length = 0;
1898 pValueName->MaximumLength = NameLength + sizeof(WCHAR);
1900 pValueName->MaximumLength,
1901 TAG_USTR);
1902 pValueName->Buffer[0] = UNICODE_NULL;
1903 RtlAppendUnicodeStringToString(pValueName, &Entry->FaceName);
1904 }
1905 else
1906 {
1907 UNICODE_STRING NewString;
1908 USHORT Length = pValueName->Length + 3 * sizeof(WCHAR) + NameLength;
1909 NewString.Length = 0;
1910 NewString.MaximumLength = Length + sizeof(WCHAR);
1912 NewString.MaximumLength,
1913 TAG_USTR);
1914 NewString.Buffer[0] = UNICODE_NULL;
1915
1916 RtlAppendUnicodeStringToString(&NewString, pValueName);
1917 RtlAppendUnicodeToString(&NewString, L" & ");
1918 RtlAppendUnicodeStringToString(&NewString, &Entry->FaceName);
1919
1920 RtlFreeUnicodeString(pValueName);
1921 *pValueName = NewString;
1922 }
1923 if (Entry->StyleName.Length)
1924 {
1925 RtlAppendUnicodeToString(pValueName, L" ");
1926 RtlAppendUnicodeStringToString(pValueName, &Entry->StyleName);
1927 }
1928
1929 for (i = 1; i < CharSetCount; ++i)
1930 {
1931 /* Do not count charsets as loaded 'faces' */
1932 IntGdiLoadFontsFromMemory(pLoadFont, SharedFace, FontIndex, i);
1933 }
1934 }
1935
1936 return FaceCount; /* Number of loaded faces */
1937}
1938
1939static INT FASTCALL
1941{
1943 FT_Face Face;
1944 FT_Long iFace, num_faces;
1945 PSHARED_FACE SharedFace;
1946 INT FaceCount = 0;
1947
1949
1950 /* Load a face from memory */
1952 pLoadFont->Memory->Buffer, pLoadFont->Memory->BufferSize,
1953 ((FontIndex == -1) ? 0 : FontIndex), &Face);
1954 if (Error)
1955 {
1956 if (Error == FT_Err_Unknown_File_Format)
1957 DPRINT1("Unknown font file format\n");
1958 else
1959 DPRINT1("Error reading font (error code: %d)\n", Error);
1961 return 0; /* Failure */
1962 }
1963
1964 pLoadFont->IsTrueType = FT_IS_SFNT(Face);
1965 num_faces = Face->num_faces;
1966 SharedFace = SharedFace_Create(Face, pLoadFont->Memory);
1967
1969
1970 if (!SharedFace)
1971 {
1972 DPRINT1("SharedFace_Create failed\n");
1974 return 0; /* Failure */
1975 }
1976
1977 if (FontIndex == -1)
1978 {
1979 for (iFace = 1; iFace < num_faces; ++iFace)
1980 {
1982 }
1983 FontIndex = 0;
1984 }
1985
1986 FaceCount += IntGdiLoadFontsFromMemory(pLoadFont, SharedFace, FontIndex, -1);
1987 return FaceCount;
1988}
1989
1991
1992/* Adds the font resource from the specified file to the system */
1993static INT FASTCALL
1996 _In_ DWORD Characteristics,
1998{
2001 PVOID Buffer = NULL;
2004 SIZE_T ViewSize = 0, Length;
2005 LARGE_INTEGER SectionSize;
2008 INT FontCount;
2010 UNICODE_STRING PathName;
2011 LPWSTR pszBuffer;
2013 static const UNICODE_STRING TrueTypePostfix = RTL_CONSTANT_STRING(L" (TrueType)");
2014
2015 /* Build PathName */
2017 {
2018 Length = DosPathPrefix.Length + FileName->Length + sizeof(UNICODE_NULL);
2020 if (!pszBuffer)
2021 return 0; /* failure */
2022
2023 RtlInitEmptyUnicodeString(&PathName, pszBuffer, Length);
2026 }
2027 else
2028 {
2030 if (!NT_SUCCESS(Status))
2031 return 0; /* failure */
2032 }
2033
2034 /* Open the font file */
2038 &FileHandle,
2041 &Iosb,
2044 if (!NT_SUCCESS(Status))
2045 {
2046 DPRINT1("Could not load font file: %wZ\n", &PathName);
2047 RtlFreeUnicodeString(&PathName);
2048 return 0;
2049 }
2050
2053 if (!NT_SUCCESS(Status))
2054 {
2055 DPRINT1("ObReferenceObjectByHandle failed.\n");
2057 RtlFreeUnicodeString(&PathName);
2058 return 0;
2059 }
2060
2061 SectionSize.QuadPart = 0LL;
2064 NULL, &SectionSize, PAGE_READONLY,
2066 if (!NT_SUCCESS(Status))
2067 {
2068 DPRINT1("Could not map file: %wZ\n", &PathName);
2071 RtlFreeUnicodeString(&PathName);
2072 return 0;
2073 }
2075
2077 if (!NT_SUCCESS(Status))
2078 {
2079 DPRINT1("Could not map file: %wZ\n", &PathName);
2082 RtlFreeUnicodeString(&PathName);
2083 return 0;
2084 }
2085
2086 RtlZeroMemory(&LoadFont, sizeof(LoadFont));
2087 LoadFont.pFileName = &PathName;
2089 LoadFont.Characteristics = Characteristics;
2090 RtlInitUnicodeString(&LoadFont.RegValueName, NULL);
2091 LoadFont.CharSet = DEFAULT_CHARSET;
2092 FontCount = IntGdiLoadFontByIndexFromMemory(&LoadFont, -1);
2093
2094 /* Release our copy */
2098
2100
2102
2103 /* Save the loaded font name into the registry */
2104 if (FontCount > 0 && (dwFlags & AFRX_WRITE_REGISTRY))
2105 {
2106 UNICODE_STRING NewString;
2107 SIZE_T Length;
2108 PWCHAR pszBuffer;
2109 LPCWSTR CharSetName;
2110 if (LoadFont.IsTrueType)
2111 {
2112 /* Append " (TrueType)" */
2113 Length = LoadFont.RegValueName.Length + TrueTypePostfix.Length + sizeof(UNICODE_NULL);
2115 if (pszBuffer)
2116 {
2117 RtlInitEmptyUnicodeString(&NewString, pszBuffer, Length);
2118 NewString.Buffer[0] = UNICODE_NULL;
2119 RtlAppendUnicodeStringToString(&NewString, &LoadFont.RegValueName);
2120 RtlAppendUnicodeStringToString(&NewString, &TrueTypePostfix);
2121 RtlFreeUnicodeString(&LoadFont.RegValueName);
2122 LoadFont.RegValueName = NewString;
2123 }
2124 else
2125 {
2126 // FIXME!
2127 }
2128 }
2129 else if (LoadFont.CharSet != DEFAULT_CHARSET)
2130 {
2131 /* Append " (CharSetName)" */
2132 CharSetName = IntNameFromCharSet(LoadFont.CharSet);
2133 Length = LoadFont.RegValueName.Length +
2134 (wcslen(CharSetName) + 3) * sizeof(WCHAR) +
2135 sizeof(UNICODE_NULL);
2136
2138 if (pszBuffer)
2139 {
2140 RtlInitEmptyUnicodeString(&NewString, pszBuffer, Length);
2141 NewString.Buffer[0] = UNICODE_NULL;
2142 RtlAppendUnicodeStringToString(&NewString, &LoadFont.RegValueName);
2143 RtlAppendUnicodeToString(&NewString, L" (");
2144 RtlAppendUnicodeToString(&NewString, CharSetName);
2145 RtlAppendUnicodeToString(&NewString, L")");
2146 RtlFreeUnicodeString(&LoadFont.RegValueName);
2147 LoadFont.RegValueName = NewString;
2148 }
2149 else
2150 {
2151 // FIXME!
2152 }
2153 }
2154
2157 NULL, NULL);
2158 Status = ZwOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes);
2159 if (NT_SUCCESS(Status))
2160 {
2162 LPWSTR pFileName;
2163
2165 {
2166 pFileName = PathName.Buffer;
2167 }
2168 else
2169 {
2170 pFileName = wcsrchr(PathName.Buffer, L'\\');
2171 }
2172
2173 if (pFileName)
2174 {
2176 {
2177 pFileName++;
2178 }
2179 DataSize = (wcslen(pFileName) + 1) * sizeof(WCHAR);
2180 ZwSetValueKey(KeyHandle, &LoadFont.RegValueName, 0, REG_SZ,
2181 pFileName, DataSize);
2182 }
2184 }
2185 }
2186 RtlFreeUnicodeString(&LoadFont.RegValueName);
2187
2188 RtlFreeUnicodeString(&PathName);
2189 return FontCount;
2190}
2191
2195 _In_ DWORD cFiles,
2196 _In_ DWORD Characteristics,
2198{
2199 PWSTR pchFile = FileName->Buffer;
2200 SIZE_T cchFile;
2201 INT ret = 0;
2202
2203 while (cFiles--)
2204 {
2205 _SEH2_TRY
2206 {
2207 cchFile = wcslen(pchFile);
2208 }
2210 {
2211 _SEH2_YIELD(return FALSE);
2212 }
2213 _SEH2_END;
2214
2215 UNICODE_STRING ustrPathName;
2216 ustrPathName.Length = (USHORT)(cchFile * sizeof(WCHAR));
2217 ustrPathName.MaximumLength = ustrPathName.Length + sizeof(WCHAR);
2218 ustrPathName.Buffer = pchFile;
2219
2220 INT count = IntGdiAddFontResourceSingle(&ustrPathName, Characteristics, dwFlags);
2221 if (!count)
2222 return 0;
2223 ret += count;
2224
2225 pchFile += cchFile + 1;
2226 }
2227
2228 /* Prepare for better LOGFONT-to-face matching */
2230
2231 return ret;
2232}
2233
2234/* Delete registry font entries */
2236{
2238 HKEY hKey;
2239 WCHAR szName[MAX_PATH], szValue[MAX_PATH];
2240 ULONG dwIndex, NameLength, ValueSize, dwType;
2241
2243 if (!NT_SUCCESS(Status))
2244 return;
2245
2246 for (dwIndex = 0;;)
2247 {
2248 NameLength = RTL_NUMBER_OF(szName);
2249 ValueSize = sizeof(szValue);
2250 Status = RegEnumValueW(hKey, dwIndex, szName, &NameLength, &dwType, szValue, &ValueSize);
2251 if (!NT_SUCCESS(Status))
2252 break;
2253
2254 if (dwType != REG_SZ || _wcsicmp(szValue, pszFileName) != 0)
2255 {
2256 ++dwIndex;
2257 continue;
2258 }
2259
2260 /* Delete the found value */
2262 if (!NT_SUCCESS(Status))
2263 break;
2264 }
2265
2266 ZwClose(hKey);
2267}
2268
2269static BOOL FASTCALL
2273{
2274 BOOL ret = FALSE;
2275 UNICODE_STRING PathName;
2276 PLIST_ENTRY CurrentEntry, NextEntry;
2277 PFONT_ENTRY FontEntry;
2278 PFONTGDI FontGDI;
2279 PWSTR pszBuffer, pszFileTitle;
2280 SIZE_T Length;
2282
2283 /* Build PathName */
2285 {
2286 Length = DosPathPrefix.Length + FileName->Length + sizeof(UNICODE_NULL);
2288 if (!pszBuffer)
2289 return FALSE; /* Failure */
2290
2291 RtlInitEmptyUnicodeString(&PathName, pszBuffer, Length);
2294 }
2295 else
2296 {
2298 if (!NT_SUCCESS(Status))
2299 return FALSE; /* Failure */
2300 }
2301
2302 pszFileTitle = PathName.Buffer;
2304 pszFileTitle = PathFindFileNameW(PathName.Buffer);
2305
2306 if (!pszFileTitle || !*pszFileTitle)
2307 {
2308 RtlFreeUnicodeString(&PathName);
2309 return FALSE; /* Failure */
2310 }
2311
2312 /* Delete font entries that matches PathName */
2314 for (CurrentEntry = g_FontListHead.Flink;
2315 CurrentEntry != &g_FontListHead;
2316 CurrentEntry = NextEntry)
2317 {
2318 FontEntry = CONTAINING_RECORD(CurrentEntry, FONT_ENTRY, ListEntry);
2319 NextEntry = CurrentEntry->Flink;
2320
2321 FontGDI = FontEntry->Font;
2322 ASSERT(FontGDI);
2323 if (FontGDI->Filename && _wcsicmp(FontGDI->Filename, pszFileTitle) == 0)
2324 {
2326 RemoveEntryList(&FontEntry->ListEntry);
2327 CleanupFontEntry(FontEntry);
2329 IntDeleteRegFontEntries(pszFileTitle, dwFlags);
2330 ret = TRUE;
2331 }
2332 }
2334
2335 RtlFreeUnicodeString(&PathName);
2336 return ret;
2337}
2338
2342 _In_ DWORD cFiles,
2344{
2345 PWSTR pchFile = FileName->Buffer;
2346 SIZE_T cchFile;
2347
2348 while (cFiles--)
2349 {
2350 _SEH2_TRY
2351 {
2352 cchFile = wcslen(pchFile);
2353 }
2355 {
2356 _SEH2_YIELD(return FALSE);
2357 }
2358 _SEH2_END;
2359
2360 UNICODE_STRING ustrPathName;
2361 ustrPathName.Length = (USHORT)(cchFile * sizeof(WCHAR));
2362 ustrPathName.MaximumLength = ustrPathName.Length + sizeof(WCHAR);
2363 ustrPathName.Buffer = pchFile;
2364
2366 if (!ret)
2367 return FALSE;
2368
2369 pchFile += cchFile + 1;
2370 }
2371
2372 return TRUE;
2373}
2374
2377{
2381 KEY_FULL_INFORMATION KeyFullInfo;
2382 ULONG i, Length;
2383 UNICODE_STRING FontTitleW, FileNameW;
2384 SIZE_T InfoSize;
2385 LPBYTE InfoBuffer;
2387 LPWSTR pchPath;
2389 INT nFontCount = 0;
2390 DWORD dwFlags;
2391
2392 /* open registry key */
2395 NULL, NULL);
2396 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
2397 if (!NT_SUCCESS(Status))
2398 {
2399 DPRINT1("ZwOpenKey failed: 0x%08X\n", Status);
2400 return FALSE; /* failure */
2401 }
2402
2403 /* query count of values */
2404 Status = ZwQueryKey(KeyHandle, KeyFullInformation,
2405 &KeyFullInfo, sizeof(KeyFullInfo), &Length);
2406 if (!NT_SUCCESS(Status))
2407 {
2408 DPRINT1("ZwQueryKey failed: 0x%08X\n", Status);
2410 return FALSE; /* failure */
2411 }
2412
2413 /* allocate buffer */
2414 InfoSize = (MAX_PATH + 256) * sizeof(WCHAR);
2415 InfoBuffer = ExAllocatePoolWithTag(PagedPool, InfoSize, TAG_FONT);
2416 if (!InfoBuffer)
2417 {
2418 DPRINT1("ExAllocatePoolWithTag failed\n");
2420 return FALSE;
2421 }
2422
2423 /* for each value */
2424 for (i = 0; i < KeyFullInfo.Values; ++i)
2425 {
2426 /* get value name */
2427 Status = ZwEnumerateValueKey(KeyHandle, i, KeyValueFullInformation,
2428 InfoBuffer, InfoSize, &Length);
2430 {
2431 /* too short buffer */
2432 ExFreePoolWithTag(InfoBuffer, TAG_FONT);
2433 InfoSize *= 2;
2434 InfoBuffer = ExAllocatePoolWithTag(PagedPool, InfoSize, TAG_FONT);
2435 if (!InfoBuffer)
2436 {
2437 DPRINT1("ExAllocatePoolWithTag failed\n");
2438 break;
2439 }
2440 /* try again */
2441 Status = ZwEnumerateValueKey(KeyHandle, i, KeyValueFullInformation,
2442 InfoBuffer, InfoSize, &Length);
2443 }
2444 if (!NT_SUCCESS(Status))
2445 {
2446 DPRINT1("ZwEnumerateValueKey failed: 0x%08X\n", Status);
2447 break; /* failure */
2448 }
2449
2450 /* create FontTitleW string */
2451 pInfo = (PKEY_VALUE_FULL_INFORMATION)InfoBuffer;
2452 Length = pInfo->NameLength / sizeof(WCHAR);
2453 pInfo->Name[Length] = UNICODE_NULL; /* truncate */
2454 if (!RtlCreateUnicodeString(&FontTitleW, pInfo->Name))
2455 {
2457 DPRINT1("RtlCreateUnicodeString failed\n");
2458 break; /* failure */
2459 }
2460
2461 /* query value */
2462 Status = ZwQueryValueKey(KeyHandle, &FontTitleW, KeyValueFullInformation,
2463 InfoBuffer, InfoSize, &Length);
2465 {
2466 /* too short buffer */
2467 ExFreePoolWithTag(InfoBuffer, TAG_FONT);
2468 InfoSize *= 2;
2469 InfoBuffer = ExAllocatePoolWithTag(PagedPool, InfoSize, TAG_FONT);
2470 if (!InfoBuffer)
2471 {
2472 DPRINT1("ExAllocatePoolWithTag failed\n");
2473 break;
2474 }
2475 /* try again */
2476 Status = ZwQueryValueKey(KeyHandle, &FontTitleW, KeyValueFullInformation,
2477 InfoBuffer, InfoSize, &Length);
2478 }
2479 pInfo = (PKEY_VALUE_FULL_INFORMATION)InfoBuffer;
2480 if (!NT_SUCCESS(Status) || !pInfo->DataLength)
2481 {
2482 DPRINT1("ZwQueryValueKey failed: 0x%08X\n", Status);
2483 RtlFreeUnicodeString(&FontTitleW);
2484 break; /* failure */
2485 }
2486
2487 /* Build pchPath */
2488 pchPath = (LPWSTR)((PUCHAR)pInfo + pInfo->DataOffset);
2489 Length = pInfo->DataLength / sizeof(WCHAR);
2490 pchPath[Length] = UNICODE_NULL; /* truncate */
2491
2492 /* Load font(s) without writing registry */
2493 if (PathIsRelativeW(pchPath))
2494 {
2495 dwFlags = 0;
2497 L"\\SystemRoot\\Fonts\\%s", pchPath);
2498 }
2499 else
2500 {
2502 Status = RtlStringCbCopyW(szPath, sizeof(szPath), pchPath);
2503 }
2504
2505 if (NT_SUCCESS(Status))
2506 {
2507 RtlCreateUnicodeString(&FileNameW, szPath);
2508 nFontCount += IntGdiAddFontResourceEx(&FileNameW, 1, 0, dwFlags);
2509 RtlFreeUnicodeString(&FileNameW);
2510 }
2511
2512 RtlFreeUnicodeString(&FontTitleW);
2513 }
2514
2515 /* close now */
2517
2518 /* free memory block */
2519 if (InfoBuffer)
2520 {
2521 ExFreePoolWithTag(InfoBuffer, TAG_FONT);
2522 }
2523
2524 return (KeyFullInfo.Values != 0 && nFontCount != 0);
2525}
2526
2529{
2530 HANDLE Ret = NULL;
2532 PFONT_ENTRY_COLL_MEM EntryCollection;
2533 INT FaceCount;
2534
2536 if (!BufferCopy)
2537 {
2538 *pNumAdded = 0;
2539 return NULL;
2540 }
2541 RtlCopyMemory(BufferCopy, Buffer, dwSize);
2542
2543 RtlZeroMemory(&LoadFont, sizeof(LoadFont));
2544 LoadFont.Memory = SharedMem_Create(BufferCopy, dwSize, FALSE);
2545 LoadFont.Characteristics = FR_PRIVATE | FR_NOT_ENUM;
2546 RtlInitUnicodeString(&LoadFont.RegValueName, NULL);
2548
2549 RtlFreeUnicodeString(&LoadFont.RegValueName);
2550
2551 /* Release our copy */
2555
2556 if (FaceCount > 0)
2557 {
2558 EntryCollection = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY_COLL_MEM), TAG_FONT);
2559 if (EntryCollection)
2560 {
2562 EntryCollection->Entry = LoadFont.PrivateEntry;
2564 IntLockProcessPrivateFonts(Win32Process);
2565 EntryCollection->Handle = ULongToHandle(++Win32Process->PrivateMemFontHandleCount);
2566 InsertTailList(&Win32Process->PrivateMemFontListHead, &EntryCollection->ListEntry);
2567 IntUnLockProcessPrivateFonts(Win32Process);
2569 Ret = EntryCollection->Handle;
2570 }
2571 }
2572 *pNumAdded = FaceCount;
2573
2574 return Ret;
2575}
2576
2579{
2581 PFONT_ENTRY_MEM FontEntry;
2582
2583 while (!IsListEmpty(&Head->ListEntry))
2584 {
2585 Entry = RemoveHeadList(&Head->ListEntry);
2586 FontEntry = CONTAINING_RECORD(Entry, FONT_ENTRY_MEM, ListEntry);
2587
2588 CleanupFontEntry(FontEntry->Entry);
2589 ExFreePoolWithTag(FontEntry, TAG_FONT);
2590 }
2591
2592 CleanupFontEntry(Head->Entry);
2594}
2595
2596static VOID FASTCALL
2598{
2599 PFONT_ENTRY_MEM FontMemEntry = Collection->Entry;
2600 PLIST_ENTRY ListEntry;
2601 RemoveEntryList(&Collection->ListEntry);
2602
2603 do {
2604 /* Also unlink the FONT_ENTRY stuff from the PrivateFontListHead */
2605 RemoveEntryList(&FontMemEntry->Entry->ListEntry);
2606
2607 ListEntry = FontMemEntry->ListEntry.Flink;
2608 FontMemEntry = CONTAINING_RECORD(ListEntry, FONT_ENTRY_MEM, ListEntry);
2609
2610 } while (FontMemEntry != Collection->Entry);
2611}
2612
2615{
2617 PFONT_ENTRY_COLL_MEM CurrentEntry;
2618 PFONT_ENTRY_COLL_MEM EntryCollection = NULL;
2620
2622 IntLockProcessPrivateFonts(Win32Process);
2623 for (Entry = Win32Process->PrivateMemFontListHead.Flink;
2624 Entry != &Win32Process->PrivateMemFontListHead;
2625 Entry = Entry->Flink)
2626 {
2627 CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY_COLL_MEM, ListEntry);
2628
2629 if (CurrentEntry->Handle == hMMFont)
2630 {
2631 EntryCollection = CurrentEntry;
2632 UnlinkFontMemCollection(CurrentEntry);
2633 break;
2634 }
2635 }
2636 IntUnLockProcessPrivateFonts(Win32Process);
2638
2639 if (EntryCollection)
2640 {
2641 IntGdiCleanupMemEntry(EntryCollection->Entry);
2642 ExFreePoolWithTag(EntryCollection, TAG_FONT);
2643 return TRUE;
2644 }
2645 return FALSE;
2646}
2647
2648
2651{
2654 PFONT_ENTRY_COLL_MEM EntryCollection;
2655
2656 DPRINT("IntGdiCleanupPrivateFontsForProcess()\n");
2657 do {
2658 Entry = NULL;
2659 EntryCollection = NULL;
2660
2662 IntLockProcessPrivateFonts(Win32Process);
2663 if (!IsListEmpty(&Win32Process->PrivateMemFontListHead))
2664 {
2665 Entry = Win32Process->PrivateMemFontListHead.Flink;
2666 EntryCollection = CONTAINING_RECORD(Entry, FONT_ENTRY_COLL_MEM, ListEntry);
2667 UnlinkFontMemCollection(EntryCollection);
2668 }
2669 IntUnLockProcessPrivateFonts(Win32Process);
2671
2672 if (EntryCollection)
2673 {
2674 IntGdiCleanupMemEntry(EntryCollection->Entry);
2675 ExFreePoolWithTag(EntryCollection, TAG_FONT);
2676 }
2677 else
2678 {
2679 /* No Mem fonts anymore, see if we have any other private fonts left */
2680 Entry = NULL;
2682 IntLockProcessPrivateFonts(Win32Process);
2683 if (!IsListEmpty(&Win32Process->PrivateFontListHead))
2684 {
2685 Entry = RemoveHeadList(&Win32Process->PrivateFontListHead);
2686 }
2687 IntUnLockProcessPrivateFonts(Win32Process);
2689
2690 if (Entry)
2691 {
2693 }
2694 }
2695
2696 } while (Entry);
2697}
2698
2701{
2702 return (gpsi->BitsPixel > 8) && g_RenderingEnabled;
2703}
2704
2707{
2709}
2710
2713{
2714 switch (logfont->lfQuality)
2715 {
2717 break;
2719 return FT_RENDER_MODE_MONO;
2720 case DRAFT_QUALITY:
2721 return FT_RENDER_MODE_LIGHT;
2722 case CLEARTYPE_QUALITY:
2723 if (!gspv.bFontSmoothing)
2724 break;
2726 break;
2727 return FT_RENDER_MODE_LCD;
2728 }
2729 return FT_RENDER_MODE_NORMAL;
2730}
2731
2734{
2735 PLFONT plfont;
2736 LOGFONTW *plf;
2737
2738 ASSERT(lf);
2739 plfont = LFONT_AllocFontWithHandle();
2740 if (!plfont)
2741 {
2742 return STATUS_NO_MEMORY;
2743 }
2744
2745 ExInitializePushLock(&plfont->lock);
2746 *NewFont = plfont->BaseObject.hHmgr;
2747 plf = &plfont->logfont.elfEnumLogfontEx.elfLogFont;
2748 RtlCopyMemory(plf, lf, sizeof(LOGFONTW));
2749 if (lf->lfEscapement != lf->lfOrientation)
2750 {
2751 /* This should really depend on whether GM_ADVANCED is set */
2752 plf->lfOrientation = plf->lfEscapement;
2753 }
2754 LFONT_UnlockFont(plfont);
2755
2756 return STATUS_SUCCESS;
2757}
2758
2759/*************************************************************************
2760 * TranslateCharsetInfo
2761 *
2762 * Fills a CHARSETINFO structure for a character set, code page, or
2763 * font. This allows making the correspondance between different labelings
2764 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2765 * of the same encoding.
2766 *
2767 * Only one codepage will be set in Cs->fs. If TCI_SRCFONTSIG is used,
2768 * only one codepage should be set in *Src.
2769 *
2770 * RETURNS
2771 * TRUE on success, FALSE on failure.
2772 *
2773 */
2774static BOOLEAN
2776 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2777 if flags == TCI_SRCCHARSET: a character set value
2778 if flags == TCI_SRCCODEPAGE: a code page value */
2779 LPCHARSETINFO Cs, /* [out] structure to receive charset information */
2780 DWORD Flags /* [in] determines interpretation of lpSrc */)
2781{
2782 int Index = 0;
2783
2784 switch (Flags)
2785 {
2786 case TCI_SRCFONTSIG:
2787 while (Index < MAXTCIINDEX && 0 == (*Src >> Index & 0x0001))
2788 {
2789 Index++;
2790 }
2791 break;
2792 case TCI_SRCCODEPAGE:
2793 while (Index < MAXTCIINDEX && *Src != g_FontTci[Index].ciACP)
2794 {
2795 Index++;
2796 }
2797 break;
2798 case TCI_SRCCHARSET:
2799 while (Index < MAXTCIINDEX && *Src != g_FontTci[Index].ciCharset)
2800 {
2801 Index++;
2802 }
2803 break;
2804 case TCI_SRCLOCALE:
2806 return FALSE;
2807 default:
2808 return FALSE;
2809 }
2810
2811 if (Index >= MAXTCIINDEX || DEFAULT_CHARSET == g_FontTci[Index].ciCharset)
2812 {
2813 return FALSE;
2814 }
2815
2816 RtlCopyMemory(Cs, &g_FontTci[Index], sizeof(CHARSETINFO));
2817
2818 return TRUE;
2819}
2820
2822{
2823 int i;
2824
2825 for(i = 0; i < ft_face->num_charmaps; i++)
2826 {
2827 if (ft_face->charmaps[i]->platform_id == TT_PLATFORM_MICROSOFT &&
2828 ft_face->charmaps[i]->encoding == FT_ENCODING_MS_SYMBOL)
2829 {
2830 return TRUE;
2831 }
2832 }
2833 return FALSE;
2834}
2835
2836static void FASTCALL
2838 TT_OS2 *pOS2, TT_HoriHeader *pHori,
2839 FT_WinFNT_HeaderRec *pFNT)
2840{
2841 FT_Fixed XScale, YScale;
2842 int Ascent, Descent;
2843 FT_Face Face = FontGDI->SharedFace->Face;
2844
2846
2847 XScale = Face->size->metrics.x_scale;
2848 YScale = Face->size->metrics.y_scale;
2849
2850 if (pFNT)
2851 {
2852 TM->tmHeight = pFNT->pixel_height;
2853 TM->tmAscent = pFNT->ascent;
2854 TM->tmDescent = TM->tmHeight - TM->tmAscent;
2857 TM->tmAveCharWidth = pFNT->avg_width;
2858 TM->tmMaxCharWidth = pFNT->max_width;
2859 TM->tmOverhang = 0;
2862 TM->tmFirstChar = pFNT->first_char;
2863 TM->tmLastChar = pFNT->last_char;
2864 TM->tmDefaultChar = pFNT->default_char + pFNT->first_char;
2865 TM->tmBreakChar = pFNT->break_char + pFNT->first_char;
2867 TM->tmWeight = FontGDI->RequestWeight;
2868 TM->tmItalic = FontGDI->RequestItalic;
2869 TM->tmUnderlined = FontGDI->RequestUnderline;
2870 TM->tmStruckOut = FontGDI->RequestStrikeOut;
2871 TM->tmCharSet = FontGDI->CharSet;
2872 return;
2873 }
2874
2875 ASSERT(pOS2);
2876 if (!pOS2)
2877 return;
2878
2879 if ((FT_Short)pOS2->usWinAscent + (FT_Short)pOS2->usWinDescent == 0)
2880 {
2881 Ascent = pHori->Ascender;
2882 Descent = -pHori->Descender;
2883 }
2884 else
2885 {
2886 Ascent = (FT_Short)pOS2->usWinAscent;
2887 Descent = (FT_Short)pOS2->usWinDescent;
2888 }
2889
2890 TM->tmAscent = FontGDI->tmAscent;
2891 TM->tmDescent = FontGDI->tmDescent;
2892 TM->tmHeight = TM->tmAscent + TM->tmDescent;
2893 TM->tmInternalLeading = FontGDI->tmInternalLeading;
2894
2895 /* MSDN says:
2896 * el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
2897 */
2898 TM->tmExternalLeading = max(0, (FT_MulFix(pHori->Line_Gap
2899 - ((Ascent + Descent)
2900 - (pHori->Ascender - pHori->Descender)),
2901 YScale) + 32) >> 6);
2902 if (FontGDI->lfWidth != 0)
2903 TM->tmAveCharWidth = FontGDI->lfWidth;
2904 else
2905 TM->tmAveCharWidth = (FT_MulFix(pOS2->xAvgCharWidth, XScale) + 32) >> 6;
2906
2907 if (TM->tmAveCharWidth == 0)
2908 TM->tmAveCharWidth = 1;
2909
2910 /* Correct forumla to get the maxcharwidth from unicode and ansi font */
2911 TM->tmMaxCharWidth = (FT_MulFix(Face->max_advance_width, XScale) + 32) >> 6;
2912
2913 if (FontGDI->OriginalWeight != FW_DONTCARE &&
2914 FontGDI->OriginalWeight > FontGDI->RequestWeight)
2915 {
2916 TM->tmWeight = FontGDI->OriginalWeight;
2917 }
2918 else
2919 {
2920 TM->tmWeight = FontGDI->RequestWeight;
2921 }
2922
2923 TM->tmOverhang = 0;
2924 TM->tmDigitizedAspectX = 96;
2925 TM->tmDigitizedAspectY = 96;
2926 if (face_has_symbol_charmap(Face) ||
2927 (pOS2->usFirstCharIndex >= 0xf000 && pOS2->usFirstCharIndex < 0xf100))
2928 {
2929 USHORT cpOEM, cpAnsi;
2930
2931 EngGetCurrentCodePage(&cpOEM, &cpAnsi);
2932 TM->tmFirstChar = 0;
2933 switch(cpAnsi)
2934 {
2935 case 1257: /* Baltic */
2936 TM->tmLastChar = 0xf8fd;
2937 break;
2938 default:
2939 TM->tmLastChar = 0xf0ff;
2940 }
2941 TM->tmBreakChar = 0x20;
2942 TM->tmDefaultChar = 0x1f;
2943 }
2944 else
2945 {
2946 TM->tmFirstChar = pOS2->usFirstCharIndex; /* Should be the first char in the cmap */
2947 TM->tmLastChar = pOS2->usLastCharIndex; /* Should be min(cmap_last, os2_last) */
2948
2949 if(pOS2->usFirstCharIndex <= 1)
2950 TM->tmBreakChar = pOS2->usFirstCharIndex + 2;
2951 else if (pOS2->usFirstCharIndex > 0xff)
2952 TM->tmBreakChar = 0x20;
2953 else
2954 TM->tmBreakChar = pOS2->usFirstCharIndex;
2955 TM->tmDefaultChar = TM->tmBreakChar - 1;
2956 }
2957
2958 if (FontGDI->OriginalItalic || FontGDI->RequestItalic)
2959 {
2960 TM->tmItalic = 0xFF;
2961 }
2962 else
2963 {
2964 TM->tmItalic = 0;
2965 }
2966 TM->tmUnderlined = (FontGDI->RequestUnderline ? 0xFF : 0);
2967 TM->tmStruckOut = (FontGDI->RequestStrikeOut ? 0xFF : 0);
2968
2969 if (!FT_IS_FIXED_WIDTH(Face))
2970 {
2971 switch (pOS2->panose[PAN_PROPORTION_INDEX])
2972 {
2974 TM->tmPitchAndFamily = 0;
2975 break;
2976 default:
2978 break;
2979 }
2980 }
2981 else
2982 {
2983 TM->tmPitchAndFamily = 0;
2984 }
2985
2986 switch (pOS2->panose[PAN_FAMILYTYPE_INDEX])
2987 {
2988 case PAN_FAMILY_SCRIPT:
2990 break;
2993 break;
2994
2995 case PAN_ANY:
2996 case PAN_NO_FIT:
2998 case PAN_FAMILY_PICTORIAL: /* Symbol fonts get treated as if they were text */
2999 /* Which is clearly not what the panose spec says. */
3000 if (TM->tmPitchAndFamily == 0) /* Fixed */
3001 {
3003 }
3004 else
3005 {
3006 switch (pOS2->panose[PAN_SERIFSTYLE_INDEX])
3007 {
3008 case PAN_ANY:
3009 case PAN_NO_FIT:
3010 default:
3012 break;
3013
3014 case PAN_SERIF_COVE:
3018 case PAN_SERIF_SQUARE:
3019 case PAN_SERIF_THIN:
3020 case PAN_SERIF_BONE:
3022 case PAN_SERIF_TRIANGLE:
3024 break;
3025
3029 case PAN_SERIF_FLARED:
3030 case PAN_SERIF_ROUNDED:
3032 break;
3033 }
3034 }
3035 break;
3036 default:
3038 }
3039
3040 if (FT_IS_SCALABLE(Face))
3041 {
3043 }
3044 if (FT_IS_SFNT(Face))
3045 {
3047 }
3048
3049 TM->tmCharSet = FontGDI->CharSet;
3050}
3051
3052static NTSTATUS
3054 FT_UShort NameID, FT_UShort LangID);
3055
3056typedef struct FONT_NAMES
3057{
3058 UNICODE_STRING FamilyNameW; /* family name (TT_NAME_ID_FONT_FAMILY) */
3059 UNICODE_STRING FaceNameW; /* face name (TT_NAME_ID_FULL_NAME) */
3060 UNICODE_STRING StyleNameW; /* style name (TT_NAME_ID_FONT_SUBFAMILY) */
3061 UNICODE_STRING FullNameW; /* unique name (TT_NAME_ID_UNIQUE_ID) */
3062 ULONG OtmSize; /* size of OUTLINETEXTMETRICW with extra data */
3064
3065static __inline void FASTCALL
3067{
3068 ULONG OtmSize;
3069
3070 RtlInitUnicodeString(&Names->FamilyNameW, NULL);
3071 RtlInitUnicodeString(&Names->FaceNameW, NULL);
3072 RtlInitUnicodeString(&Names->StyleNameW, NULL);
3073 RtlInitUnicodeString(&Names->FullNameW, NULL);
3074
3075 /* family name */
3077 /* face name */
3079 /* style name */
3081 /* unique name (full name) */
3083
3084 /* Calculate the size of OUTLINETEXTMETRICW with extra data */
3085 OtmSize = sizeof(OUTLINETEXTMETRICW) +
3086 Names->FamilyNameW.Length + sizeof(UNICODE_NULL) +
3087 Names->FaceNameW.Length + sizeof(UNICODE_NULL) +
3088 Names->StyleNameW.Length + sizeof(UNICODE_NULL) +
3089 Names->FullNameW.Length + sizeof(UNICODE_NULL);
3090 Names->OtmSize = OtmSize;
3091}
3092
3093static inline SIZE_T FASTCALL
3095{
3096 RtlCopyMemory(pb, pName->Buffer, pName->Length);
3097 *(WCHAR*)&pb[pName->Length] = UNICODE_NULL;
3098 return pName->Length + sizeof(UNICODE_NULL);
3099}
3100
3103{
3104 PBYTE pb = (PBYTE)Otm + sizeof(OUTLINETEXTMETRICW);
3105
3106 /* family name */
3107 Otm->otmpFamilyName = (LPSTR)(pb - (BYTE*) Otm);
3108 pb += IntStoreName(&Names->FamilyNameW, pb);
3109
3110 /* face name */
3111 Otm->otmpFaceName = (LPSTR)(pb - (BYTE*) Otm);
3112 pb += IntStoreName(&Names->FaceNameW, pb);
3113
3114 /* style name */
3115 Otm->otmpStyleName = (LPSTR)(pb - (BYTE*) Otm);
3116 pb += IntStoreName(&Names->StyleNameW, pb);
3117
3118 /* unique name (full name) */
3119 Otm->otmpFullName = (LPSTR)(pb - (BYTE*) Otm);
3120 pb += IntStoreName(&Names->FullNameW, pb);
3121
3122 return pb;
3123}
3124
3125static __inline void FASTCALL
3127{
3128 RtlFreeUnicodeString(&Names->FamilyNameW);
3129 RtlFreeUnicodeString(&Names->FaceNameW);
3130 RtlFreeUnicodeString(&Names->StyleNameW);
3131 RtlFreeUnicodeString(&Names->FullNameW);
3132}
3133
3134/*************************************************************
3135 * IntGetOutlineTextMetrics
3136 *
3137 */
3140 UINT Size,
3141 OUTLINETEXTMETRICW *Otm,
3142 BOOL bLocked)
3143{
3144 TT_OS2 *pOS2;
3145 TT_HoriHeader *pHori;
3146 TT_Postscript *pPost;
3147 FT_Fixed XScale, YScale;
3148 FT_WinFNT_HeaderRec WinFNT;
3150 BYTE *pb;
3151 FONT_NAMES FontNames;
3152 PSHARED_FACE SharedFace = FontGDI->SharedFace;
3154 FT_Face Face = SharedFace->Face;
3155
3156 if (bLocked)
3158 else
3160
3162 {
3163 Cache = &SharedFace->EnglishUS;
3164 }
3165 else
3166 {
3167 Cache = &SharedFace->UserLanguage;
3168 }
3169
3170 if (Size == 0 && Cache->OutlineRequiredSize > 0)
3171 {
3172 ASSERT(Otm == NULL);
3173 return Cache->OutlineRequiredSize;
3174 }
3175
3176 if (!bLocked)
3178
3179 IntInitFontNames(&FontNames, SharedFace);
3180 Cache->OutlineRequiredSize = FontNames.OtmSize;
3181
3182 if (Size == 0)
3183 {
3184 ASSERT(Otm == NULL);
3185 IntFreeFontNames(&FontNames);
3186 if (!bLocked)
3188 return Cache->OutlineRequiredSize;
3189 }
3190
3191 ASSERT(Otm != NULL);
3192
3193 if (Size < Cache->OutlineRequiredSize)
3194 {
3195 DPRINT1("Size %u < OutlineRequiredSize %u\n", Size,
3196 Cache->OutlineRequiredSize);
3197 IntFreeFontNames(&FontNames);
3198 if (!bLocked)
3200 return 0; /* failure */
3201 }
3202
3203 XScale = Face->size->metrics.x_scale;
3204 YScale = Face->size->metrics.y_scale;
3205
3206 pOS2 = FT_Get_Sfnt_Table(Face, FT_SFNT_OS2);
3207 pHori = FT_Get_Sfnt_Table(Face, FT_SFNT_HHEA);
3208 pPost = FT_Get_Sfnt_Table(Face, FT_SFNT_POST); /* We can live with this failing */
3209 Error = FT_Get_WinFNT_Header(Face, &WinFNT);
3210
3211 if (pOS2 == NULL && Error)
3212 {
3213 if (!bLocked)
3215 DPRINT1("Can't find OS/2 table - not TT font?\n");
3216 IntFreeFontNames(&FontNames);
3217 return 0;
3218 }
3219
3220 if (pHori == NULL && Error)
3221 {
3222 if (!bLocked)
3224 DPRINT1("Can't find HHEA table - not TT font?\n");
3225 IntFreeFontNames(&FontNames);
3226 return 0;
3227 }
3228
3229 Otm->otmSize = Cache->OutlineRequiredSize;
3230
3231 FillTM(&Otm->otmTextMetrics, FontGDI, pOS2, pHori, (Error ? NULL : &WinFNT));
3232
3233 if (!pOS2)
3234 goto skip_os2;
3235
3236 Otm->otmFiller = 0;
3238 Otm->otmfsSelection = pOS2->fsSelection;
3239 Otm->otmfsType = pOS2->fsType;
3240 Otm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
3241 Otm->otmsCharSlopeRun = pHori->caret_Slope_Run;
3242 Otm->otmItalicAngle = 0; /* POST table */
3243 Otm->otmEMSquare = Face->units_per_EM;
3244
3245#define SCALE_X(value) ((FT_MulFix((value), XScale) + 32) >> 6)
3246#define SCALE_Y(value) ((FT_MulFix((value), YScale) + 32) >> 6)
3247
3248 Otm->otmAscent = SCALE_Y(pOS2->sTypoAscender);
3249 Otm->otmDescent = SCALE_Y(pOS2->sTypoDescender);
3250 Otm->otmLineGap = SCALE_Y(pOS2->sTypoLineGap);
3251 Otm->otmsCapEmHeight = SCALE_Y(pOS2->sCapHeight);
3252 Otm->otmsXHeight = SCALE_Y(pOS2->sxHeight);
3253 Otm->otmrcFontBox.left = SCALE_X(Face->bbox.xMin);
3254 Otm->otmrcFontBox.right = SCALE_X(Face->bbox.xMax);
3255 Otm->otmrcFontBox.top = SCALE_Y(Face->bbox.yMax);
3256 Otm->otmrcFontBox.bottom = SCALE_Y(Face->bbox.yMin);
3259 Otm->otmMacLineGap = Otm->otmLineGap;
3260 Otm->otmusMinimumPPEM = 0; /* TT Header */
3271
3272 if (!pPost)
3273 {
3274 Otm->otmsUnderscoreSize = 0;
3275 Otm->otmsUnderscorePosition = 0;
3276 }
3277 else
3278 {
3281 }
3282
3283#undef SCALE_X
3284#undef SCALE_Y
3285
3286skip_os2:
3287 if (!bLocked)
3289
3290 pb = IntStoreFontNames(&FontNames, Otm);
3291 ASSERT(pb - (BYTE*)Otm == Cache->OutlineRequiredSize);
3292
3293 IntFreeFontNames(&FontNames);
3294
3295 return Cache->OutlineRequiredSize;
3296}
3297
3298static NTSTATUS
3300 FT_UShort NameID, FT_UShort LangID)
3301{
3303 INT i, Count, BestIndex, Score, BestScore;
3306 ANSI_STRING AnsiName;
3308 FT_Face Face = SharedFace->Face;
3309
3310 RtlFreeUnicodeString(pNameW);
3311
3312 /* select cache */
3314 Cache = &SharedFace->EnglishUS;
3315 else
3316 Cache = &SharedFace->UserLanguage;
3317
3318 /* use cache if available */
3319 if (NameID == TT_NAME_ID_FONT_FAMILY && Cache->FontFamily.Buffer)
3320 return IntDuplicateUnicodeString(&Cache->FontFamily, pNameW);
3321 if (NameID == TT_NAME_ID_FULL_NAME && Cache->FullName.Buffer)
3322 return IntDuplicateUnicodeString(&Cache->FullName, pNameW);
3323
3324 BestIndex = -1;
3325 BestScore = 0;
3326
3328 for (i = 0; i < Count; ++i)
3329 {
3330 Error = FT_Get_Sfnt_Name(Face, i, &Name);
3331 if (Error)
3332 continue; /* failure */
3333
3334 if (Name.name_id != NameID)
3335 continue; /* mismatched */
3336
3337 if (Name.platform_id != TT_PLATFORM_MICROSOFT ||
3338 (Name.encoding_id != TT_MS_ID_UNICODE_CS &&
3339 Name.encoding_id != TT_MS_ID_SYMBOL_CS))
3340 {
3341 continue; /* not Microsoft Unicode name */
3342 }
3343
3344 if (Name.string == NULL || Name.string_len == 0 ||
3345 (Name.string[0] == 0 && Name.string[1] == 0))
3346 {
3347 continue; /* invalid string */
3348 }
3349
3350 if (Name.language_id == LangID)
3351 {
3352 Score = 30;
3353 BestIndex = i;
3354 break; /* best match */
3355 }
3356 else if (PRIMARYLANGID(Name.language_id) == PRIMARYLANGID(LangID))
3357 {
3358 Score = 20;
3359 }
3360 else if (PRIMARYLANGID(Name.language_id) == LANG_ENGLISH)
3361 {
3362 Score = 10;
3363 }
3364 else
3365 {
3366 Score = 0;
3367 }
3368
3369 if (Score > BestScore)
3370 {
3371 BestScore = Score;
3372 BestIndex = i;
3373 }
3374 }
3375
3376 if (BestIndex >= 0)
3377 {
3378 /* store the best name */
3379 Error = (Score == 30) ? 0 : FT_Get_Sfnt_Name(Face, BestIndex, &Name);
3380 if (!Error)
3381 {
3382 /* NOTE: Name.string is not null-terminated */
3383 UNICODE_STRING Tmp;
3384 Tmp.Buffer = (PWCH)Name.string;
3385 Tmp.Length = Tmp.MaximumLength = Name.string_len;
3386
3387 pNameW->Length = 0;
3388 pNameW->MaximumLength = Name.string_len + sizeof(WCHAR);
3390
3391 if (pNameW->Buffer)
3392 {
3393 Status = RtlAppendUnicodeStringToString(pNameW, &Tmp);
3394 if (Status == STATUS_SUCCESS)
3395 {
3396 /* Convert UTF-16 big endian to little endian */
3397 IntSwapEndian(pNameW->Buffer, pNameW->Length);
3398 }
3399 }
3400 else
3401 {
3403 }
3404 }
3405 }
3406
3407 if (!NT_SUCCESS(Status))
3408 {
3409 /* defaulted */
3410 if (NameID == TT_NAME_ID_FONT_SUBFAMILY)
3411 {
3412 RtlInitAnsiString(&AnsiName, Face->style_name);
3413 Status = RtlAnsiStringToUnicodeString(pNameW, &AnsiName, TRUE);
3414 }
3415 else
3416 {
3417 RtlInitAnsiString(&AnsiName, Face->family_name);
3418 Status = RtlAnsiStringToUnicodeString(pNameW, &AnsiName, TRUE);
3419 }
3420 }
3421
3422 if (NT_SUCCESS(Status))
3423 {
3424 /* make cache */
3425 if (NameID == TT_NAME_ID_FONT_FAMILY)
3426 {
3428 if (!Cache->FontFamily.Buffer)
3429 IntDuplicateUnicodeString(pNameW, &Cache->FontFamily);
3430 }
3431 else if (NameID == TT_NAME_ID_FULL_NAME)
3432 {
3434 if (!Cache->FullName.Buffer)
3435 IntDuplicateUnicodeString(pNameW, &Cache->FullName);
3436 }
3437 }
3438
3439 return Status;
3440}
3441
3442static void FASTCALL
3444 LPCWSTR FullName, PFONTGDI FontGDI)
3445{
3446 ANSI_STRING StyleA;
3447 UNICODE_STRING StyleW;
3448 TT_OS2 *pOS2;
3450 CHARSETINFO CharSetInfo;
3451 unsigned i, Size;
3452 OUTLINETEXTMETRICW *Otm;
3453 LOGFONTW *Lf;
3454 TEXTMETRICW *TM;
3455 NEWTEXTMETRICW *Ntm;
3456 DWORD fs0;
3458 PSHARED_FACE SharedFace = FontGDI->SharedFace;
3459 FT_Face Face = SharedFace->Face;
3460 UNICODE_STRING NameW;
3461
3462 RtlInitUnicodeString(&NameW, NULL);
3465 Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL, TRUE);
3466 if (!Size)
3467 return;
3469 if (!Otm)
3470 return;
3472 Size = IntGetOutlineTextMetrics(FontGDI, Size, Otm, TRUE);
3473 if (!Size)
3474 {
3476 return;
3477 }
3478
3479 Lf = &Info->EnumLogFontEx.elfLogFont;
3480 TM = &Otm->otmTextMetrics;
3481
3482 Lf->lfHeight = TM->tmHeight;
3483 Lf->lfWidth = TM->tmAveCharWidth;
3484 Lf->lfWeight = TM->tmWeight;
3485 Lf->lfItalic = TM->tmItalic;
3486 Lf->lfPitchAndFamily = (TM->tmPitchAndFamily & 0xf1) + 1;
3487 Lf->lfCharSet = TM->tmCharSet;
3491
3492 Ntm = &Info->NewTextMetricEx.ntmTm;
3493 Ntm->tmHeight = TM->tmHeight;
3494 Ntm->tmAscent = TM->tmAscent;
3495 Ntm->tmDescent = TM->tmDescent;
3498 Ntm->tmAveCharWidth = TM->tmAveCharWidth;
3499 Ntm->tmMaxCharWidth = TM->tmMaxCharWidth;
3500 Ntm->tmWeight = TM->tmWeight;
3501 Ntm->tmOverhang = TM->tmOverhang;
3504 Ntm->tmFirstChar = TM->tmFirstChar;
3505 Ntm->tmLastChar = TM->tmLastChar;
3506 Ntm->tmDefaultChar = TM->tmDefaultChar;
3507 Ntm->tmBreakChar = TM->tmBreakChar;
3508 Ntm->tmItalic = TM->tmItalic;
3509 Ntm->tmUnderlined = TM->tmUnderlined;
3510 Ntm->tmStruckOut = TM->tmStruckOut;
3512 Ntm->tmCharSet = TM->tmCharSet;
3513 Ntm->ntmFlags = TM->tmItalic ? NTM_ITALIC : 0;
3514
3515 if (550 < TM->tmWeight) Ntm->ntmFlags |= NTM_BOLD;
3516
3517 if (0 == Ntm->ntmFlags) Ntm->ntmFlags = NTM_REGULAR;
3518
3519 Info->FontType = (0 != (TM->tmPitchAndFamily & TMPF_TRUETYPE)
3520 ? TRUETYPE_FONTTYPE : 0);
3521
3522 if (0 == (TM->tmPitchAndFamily & TMPF_VECTOR))
3523 Info->FontType |= RASTER_FONTTYPE;
3524
3525
3526 /* face name */
3527 if (!FaceName)
3528 FaceName = (WCHAR*)((ULONG_PTR)Otm + (ULONG_PTR)Otm->otmpFamilyName);
3529
3530 RtlStringCbCopyW(Lf->lfFaceName, sizeof(Lf->lfFaceName), FaceName);
3531
3532 /* full name */
3533 if (!FullName)
3534 FullName = (WCHAR*)((ULONG_PTR) Otm + (ULONG_PTR)Otm->otmpFaceName);
3535
3536 RtlStringCbCopyW(Info->EnumLogFontEx.elfFullName,
3537 sizeof(Info->EnumLogFontEx.elfFullName),
3538 FullName);
3539
3540 RtlInitAnsiString(&StyleA, Face->style_name);
3541 StyleW.Buffer = Info->EnumLogFontEx.elfStyle;
3542 StyleW.MaximumLength = sizeof(Info->EnumLogFontEx.elfStyle);
3543 status = RtlAnsiStringToUnicodeString(&StyleW, &StyleA, FALSE);
3544 if (!NT_SUCCESS(status))
3545 {
3547 return;
3548 }
3549 Info->EnumLogFontEx.elfScript[0] = UNICODE_NULL;
3550
3551 pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
3552
3553 if (!pOS2)
3554 {
3556 return;
3557 }
3558
3559 Ntm->ntmSizeEM = Otm->otmEMSquare;
3561 Ntm->ntmAvgWidth = 0;
3562
3564
3565 fs.fsCsb[0] = pOS2->ulCodePageRange1;
3566 fs.fsCsb[1] = pOS2->ulCodePageRange2;
3567 fs.fsUsb[0] = pOS2->ulUnicodeRange1;
3568 fs.fsUsb[1] = pOS2->ulUnicodeRange2;
3569 fs.fsUsb[2] = pOS2->ulUnicodeRange3;
3570 fs.fsUsb[3] = pOS2->ulUnicodeRange4;
3571
3572 if (0 == pOS2->version)
3573 {
3574 FT_UInt Dummy;
3575
3576 if (FT_Get_First_Char(Face, &Dummy) < 0x100)
3577 fs.fsCsb[0] |= FS_LATIN1;
3578 else
3579 fs.fsCsb[0] |= FS_SYMBOL;
3580 }
3581
3582 if (fs.fsCsb[0] == 0)
3583 {
3584 /* Let's see if we can find any interesting cmaps */
3585 for (i = 0; i < (UINT)Face->num_charmaps; i++)
3586 {
3587 switch (Face->charmaps[i]->encoding)
3588 {
3589 case FT_ENCODING_UNICODE:
3590 case FT_ENCODING_APPLE_ROMAN:
3591 fs.fsCsb[0] |= FS_LATIN1;
3592 break;
3593 case FT_ENCODING_MS_SYMBOL:
3594 fs.fsCsb[0] |= FS_SYMBOL;
3595 break;
3596 default:
3597 break;
3598 }
3599 }
3600 }
3601
3602 for (i = 0; i < MAXTCIINDEX; i++)
3603 {
3604 fs0 = 1L << i;
3605 if (fs.fsCsb[0] & fs0)
3606 {
3607 if (!IntTranslateCharsetInfo(&fs0, &CharSetInfo, TCI_SRCFONTSIG))
3608 {
3609 CharSetInfo.ciCharset = DEFAULT_CHARSET;
3610 }
3611 if (DEFAULT_CHARSET != CharSetInfo.ciCharset)
3612 {
3613 if (g_ElfScripts[i])
3614 wcscpy(Info->EnumLogFontEx.elfScript, g_ElfScripts[i]);
3615 else
3616 {
3617 DPRINT1("Unknown elfscript for bit %u\n", i);
3618 }
3619 }
3620 }
3621 }
3622 Info->NewTextMetricEx.ntmFontSig = fs;
3623}
3624
3625static BOOLEAN FASTCALL
3628 LPCWSTR NominalName,
3629 LONG *pCount,
3630 LONG MaxCount,
3631 PLIST_ENTRY Head)
3632{
3634 PFONT_ENTRY CurrentEntry;
3635 FONTGDI *FontGDI;
3636 FONTFAMILYINFO InfoEntry;
3637 LONG Count = *pCount;
3638
3639 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
3640 {
3641 CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
3642 FontGDI = CurrentEntry->Font;
3643 ASSERT(FontGDI);
3644
3645 if (LogFont->lfCharSet != DEFAULT_CHARSET &&
3646 LogFont->lfCharSet != FontGDI->CharSet)
3647 {
3648 continue; /* charset mismatch */
3649 }
3650
3651 /* get one info entry */
3652 FontFamilyFillInfo(&InfoEntry, NULL, NULL, FontGDI);
3653
3654 if (LogFont->lfFaceName[0] != UNICODE_NULL)
3655 {
3656 /* check name */
3657 if (_wcsnicmp(LogFont->lfFaceName,
3659 RTL_NUMBER_OF(LogFont->lfFaceName) - 1) != 0 &&
3660 _wcsnicmp(LogFont->lfFaceName,
3661 InfoEntry.EnumLogFontEx.elfFullName,
3662 RTL_NUMBER_OF(LogFont->lfFaceName) - 1) != 0)
3663 {
3664 continue;
3665 }
3666 }
3667
3668 if (NominalName)
3669 {
3670 /* store the nominal name */
3672 sizeof(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName),
3673 NominalName);
3674 }
3675
3676 /* store one entry to Info */
3677 if (0 <= Count && Count < MaxCount)
3678 {
3679 RtlCopyMemory(&Info[Count], &InfoEntry, sizeof(InfoEntry));
3680 }
3681 Count++;
3682 }
3683
3684 *pCount = Count;
3685
3686 return TRUE;
3687}
3688
3689static BOOLEAN FASTCALL
3692 LONG *pCount,
3693 LONG MaxCount)
3694{
3695 PLIST_ENTRY pEntry, pHead = &g_FontSubstListHead;
3696 PFONTSUBST_ENTRY pCurrentEntry;
3697 PUNICODE_STRING pFromW, pToW;
3698 LOGFONTW lf = *LogFont;
3700
3701 for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink)
3702 {
3703 pCurrentEntry = CONTAINING_RECORD(pEntry, FONTSUBST_ENTRY, ListEntry);
3704
3705 pFromW = &pCurrentEntry->FontNames[FONTSUBST_FROM];
3706 if (LogFont->lfFaceName[0] != UNICODE_NULL)
3707 {
3708 /* check name */
3709 if (_wcsicmp(LogFont->lfFaceName, pFromW->Buffer) != 0)
3710 continue; /* mismatch */
3711 }
3712
3713 pToW = &pCurrentEntry->FontNames[FONTSUBST_TO];
3714 if (RtlEqualUnicodeString(pFromW, pToW, TRUE) &&
3715 pCurrentEntry->CharSets[FONTSUBST_FROM] ==
3716 pCurrentEntry->CharSets[FONTSUBST_TO])
3717 {
3718 /* identical mapping */
3719 continue;
3720 }
3721
3722 /* substitute and get the real name */
3723 IntUnicodeStringToBuffer(lf.lfFaceName, sizeof(lf.lfFaceName), pFromW);
3725 if (LogFont->lfCharSet != DEFAULT_CHARSET && LogFont->lfCharSet != lf.lfCharSet)
3726 continue;
3727
3728 /* search in global fonts */
3730 GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount, &g_FontListHead);
3731
3732 /* search in private fonts */
3733 IntLockProcessPrivateFonts(Win32Process);
3734 GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount,
3735 &Win32Process->PrivateFontListHead);
3736 IntUnLockProcessPrivateFonts(Win32Process);
3738
3739 if (LogFont->lfFaceName[0] != UNICODE_NULL)
3740 {
3741 /* it's already matched to the exact name and charset if the name
3742 was specified at here, then so don't scan more for another name */
3743 break;
3744 }
3745 }
3746
3747 return TRUE;
3748}
3749
3752{
3753 if ( lprs )
3754 {
3755 lprs->nSize = sizeof(RASTERIZER_STATUS);
3756 lprs->wFlags = TT_AVAILABLE | TT_ENABLED;
3757 lprs->nLanguageID = gusLanguageID;
3758 return TRUE;
3759 }
3761 return FALSE;
3762}
3763
3764static DWORD
3766{
3767 DWORD dwHash = cdw;
3768 const DWORD *pdw = pv;
3769
3770 while (cdw-- > 0)
3771 {
3772 dwHash *= 3;
3773 dwHash ^= *pdw++;
3774 }
3775
3776 return dwHash;
3777}
3778
3779static FT_BitmapGlyph
3781{
3782 PLIST_ENTRY CurrentEntry;
3783 PFONT_CACHE_ENTRY FontEntry;
3784 DWORD dwHash = pCache->dwHash;
3785
3787
3788 for (CurrentEntry = g_FontCacheListHead.Flink;
3789 CurrentEntry != &g_FontCacheListHead;
3790 CurrentEntry = CurrentEntry->Flink)
3791 {
3792 FontEntry = CONTAINING_RECORD(CurrentEntry, FONT_CACHE_ENTRY, ListEntry);
3793 if (FontEntry->dwHash == dwHash &&
3794 FontEntry->Hashed.GlyphIndex == pCache->Hashed.GlyphIndex &&
3795 FontEntry->Hashed.Face == pCache->Hashed.Face &&
3796 FontEntry->Hashed.lfHeight == pCache->Hashed.lfHeight &&
3797 FontEntry->Hashed.lfWidth == pCache->Hashed.lfWidth &&
3798 FontEntry->Hashed.AspectValue == pCache->Hashed.AspectValue &&
3799 memcmp(&FontEntry->Hashed.matTransform, &pCache->Hashed.matTransform,
3800 sizeof(FT_Matrix)) == 0)
3801 {
3802 break;
3803 }
3804 }
3805
3806 if (CurrentEntry == &g_FontCacheListHead)
3807 {
3808 return NULL;
3809 }
3810
3811 RemoveEntryList(CurrentEntry);
3812 InsertHeadList(&g_FontCacheListHead, CurrentEntry);
3813 return FontEntry->BitmapGlyph;
3814}
3815
3816static FT_BitmapGlyph
3819 IN FT_GlyphSlot GlyphSlot)
3820{
3821 FT_Glyph GlyphCopy;
3822 INT error;
3823 PFONT_CACHE_ENTRY NewEntry;
3824 FT_Bitmap AlignedBitmap;
3825 FT_BitmapGlyph BitmapGlyph;
3826
3828
3829 error = FT_Get_Glyph(GlyphSlot, &GlyphCopy);
3830 if (error)
3831 {
3832 DPRINT1("Failure caching glyph.\n");
3833 return NULL;
3834 };
3835
3836 error = FT_Glyph_To_Bitmap(&GlyphCopy, Cache->Hashed.Aspect.RenderMode, 0, 1);
3837 if (error)
3838 {
3839 FT_Done_Glyph(GlyphCopy);
3840 DPRINT1("Failure rendering glyph.\n");
3841 return NULL;
3842 };
3843
3845 if (!NewEntry)
3846 {
3847 DPRINT1("Alloc failure caching glyph.\n");
3848 FT_Done_Glyph(GlyphCopy);
3849 return NULL;
3850 }
3851
3852 BitmapGlyph = (FT_BitmapGlyph)GlyphCopy;
3853 FT_Bitmap_New(&AlignedBitmap);
3854 if (FT_Bitmap_Convert_ReactOS_Hack(GlyphSlot->library, &BitmapGlyph->bitmap,
3855 &AlignedBitmap, 4, TRUE))
3856 {
3857 DPRINT1("Conversion failed\n");
3858 ExFreePoolWithTag(NewEntry, TAG_FONT);
3859 FT_Bitmap_Done(GlyphSlot->library, &AlignedBitmap);
3860 FT_Done_Glyph((FT_Glyph)BitmapGlyph);
3861 return NULL;
3862 }
3863
3864 FT_Bitmap_Done(GlyphSlot->library, &BitmapGlyph->bitmap);
3865 BitmapGlyph->bitmap = AlignedBitmap;
3866
3867 NewEntry->BitmapGlyph = BitmapGlyph;
3868 NewEntry->dwHash = Cache->dwHash;
3869 NewEntry->Hashed = Cache->Hashed;
3870
3871 InsertHeadList(&g_FontCacheListHead, &NewEntry->ListEntry);
3873 {
3874 NewEntry = CONTAINING_RECORD(g_FontCacheListHead.Blink, FONT_CACHE_ENTRY, ListEntry);
3875 RemoveCachedEntry(NewEntry);
3876 }
3877
3878 return BitmapGlyph;
3879}
3880
3881
3882static unsigned int get_native_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
3883{
3884 TTPOLYGONHEADER *pph;
3885 TTPOLYCURVE *ppc;
3886 int needed = 0, point = 0, contour, first_pt;
3887 unsigned int pph_start, cpfx;
3888 DWORD type;
3889
3890 for (contour = 0; contour < outline->n_contours; contour++)
3891 {
3892 /* Ignore contours containing one point */
3893 if (point == outline->contours[contour])
3894 {
3895 point++;
3896 continue;
3897 }
3898
3899 pph_start = needed;
3900 pph = (TTPOLYGONHEADER *)(buf + needed);
3901 first_pt = point;
3902 if (buf)
3903 {
3904 pph->dwType = TT_POLYGON_TYPE;
3905 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
3906 }
3907 needed += sizeof(*pph);
3908 point++;
3909 while (point <= outline->contours[contour])
3910 {
3911 ppc = (TTPOLYCURVE *)(buf + needed);
3912 type = (outline->tags[point] & FT_Curve_Tag_On) ?
3914 cpfx = 0;
3915 do
3916 {
3917 if (buf)
3918 FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3919 cpfx++;
3920 point++;
3921 } while (point <= outline->contours[contour] &&
3922 (outline->tags[point] & FT_Curve_Tag_On) ==
3923 (outline->tags[point-1] & FT_Curve_Tag_On));
3924 /* At the end of a contour Windows adds the start point, but
3925 only for Beziers */
3926 if (point > outline->contours[contour] &&
3927 !(outline->tags[point-1] & FT_Curve_Tag_On))
3928 {
3929 if (buf)
3930 FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
3931 cpfx++;
3932 }
3933 else if (point <= outline->contours[contour] &&
3934 outline->tags[point] & FT_Curve_Tag_On)
3935 {
3936 /* add closing pt for bezier */
3937 if (buf)
3938 FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3939 cpfx++;
3940 point++;
3941 }
3942 if (buf)
3943 {
3944 ppc->wType = type;
3945 ppc->cpfx = cpfx;
3946 }
3947 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
3948 }
3949 if (buf)
3950 pph->cb = needed - pph_start;
3951 }
3952 return needed;
3953}
3954
3955static unsigned int get_bezier_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
3956{
3957 /* Convert the quadratic Beziers to cubic Beziers.
3958 The parametric eqn for a cubic Bezier is, from PLRM:
3959 r(t) = at^3 + bt^2 + ct + r0
3960 with the control points:
3961 r1 = r0 + c/3
3962 r2 = r1 + (c + b)/3
3963 r3 = r0 + c + b + a
3964
3965 A quadratic Bezier has the form:
3966 p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
3967
3968 So equating powers of t leads to:
3969 r1 = 2/3 p1 + 1/3 p0
3970 r2 = 2/3 p1 + 1/3 p2
3971 and of course r0 = p0, r3 = p2
3972 */
3973 int contour, point = 0, first_pt;
3974 TTPOLYGONHEADER *pph;
3975 TTPOLYCURVE *ppc;
3976 DWORD pph_start, cpfx, type;
3977 FT_Vector cubic_control[4];
3978 unsigned int needed = 0;
3979
3980 for (contour = 0; contour < outline->n_contours; contour++)
3981 {
3982 pph_start = needed;
3983 pph = (TTPOLYGONHEADER *)(buf + needed);
3984 first_pt = point;
3985 if (buf)
3986 {
3987 pph->dwType = TT_POLYGON_TYPE;
3988 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
3989 }
3990 needed += sizeof(*pph);
3991 point++;
3992 while (point <= outline->contours[contour])
3993 {
3994 ppc = (TTPOLYCURVE *)(buf + needed);
3995 type = (outline->tags[point] & FT_Curve_Tag_On) ?
3997 cpfx = 0;
3998 do
3999 {
4000 if (type == TT_PRIM_LINE)
4001 {
4002 if (buf)
4003 FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
4004 cpfx++;
4005 point++;
4006 }
4007 else
4008 {
4009 /* Unlike QSPLINEs, CSPLINEs always have their endpoint
4010 so cpfx = 3n */
4011
4012 /* FIXME: Possible optimization in endpoint calculation
4013 if there are two consecutive curves */
4014 cubic_control[0] = outline->points[point-1];
4015 if (!(outline->tags[point-1] & FT_Curve_Tag_On))
4016 {
4017 cubic_control[0].x += outline->points[point].x + 1;
4018 cubic_control[0].y += outline->points[point].y + 1;
4019 cubic_control[0].x >>= 1;
4020 cubic_control[0].y >>= 1;
4021 }
4022 if (point+1 > outline->contours[contour])
4023 cubic_control[3] = outline->points[first_pt];
4024 else
4025 {
4026 cubic_control[3] = outline->points[point+1];
4027 if (!(outline->tags[point+1] & FT_Curve_Tag_On))
4028 {
4029 cubic_control[3].x += outline->points[point].x + 1;
4030 cubic_control[3].y += outline->points[point].y + 1;
4031 cubic_control[3].x >>= 1;
4032 cubic_control[3].y >>= 1;
4033 }
4034 }
4035 /* r1 = 1/3 p0 + 2/3 p1
4036 r2 = 1/3 p2 + 2/3 p1 */
4037 cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
4038 cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
4039 cubic_control[2] = cubic_control[1];
4040 cubic_control[1].x += (cubic_control[0].x + 1) / 3;
4041 cubic_control[1].y += (cubic_control[0].y + 1) / 3;
4042 cubic_control[2].x += (cubic_control[3].x + 1) / 3;
4043 cubic_control[2].y += (cubic_control[3].y + 1) / 3;
4044 if (buf)
4045 {
4046 FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
4047 FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
4048 FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
4049 }
4050 cpfx += 3;
4051 point++;
4052 }
4053 } while (point <= outline->contours[contour] &&
4054 (outline->tags[point] & FT_Curve_Tag_On) ==
4055 (outline->tags[point-1] & FT_Curve_Tag_On));
4056 /* At the end of a contour Windows adds the start point,
4057 but only for Beziers and we've already done that.
4058 */
4059 if (point <= outline->contours[contour] &&
4060 outline->tags[point] & FT_Curve_Tag_On)
4061 {
4062 /* This is the closing pt of a bezier, but we've already
4063 added it, so just inc point and carry on */
4064 point++;
4065 }
4066 if (buf)
4067 {
4068 ppc->wType = type;
4069 ppc->cpfx = cpfx;
4070 }
4071 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
4072 }
4073 if (buf)
4074 pph->cb = needed - pph_start;
4075 }
4076 return needed;
4077}
4078
4079static FT_Error
4080IntRequestFontSize(PDC dc, PFONTGDI FontGDI, LONG lfWidth, LONG lfHeight)
4081{
4084 FT_Face face = FontGDI->SharedFace->Face;
4085 TT_OS2 *pOS2;
4086 TT_HoriHeader *pHori;
4087 FT_WinFNT_HeaderRec WinFNT;
4088 LONG Ascent, Descent, Sum, EmHeight;
4089
4090 lfWidth = abs(lfWidth);
4091 if (lfHeight == 0)
4092 {
4093 if (lfWidth == 0)
4094 {
4095 DPRINT("lfHeight and lfWidth are zero.\n");
4096 lfHeight = -16;
4097 }
4098 else
4099 {
4100 lfHeight = lfWidth;
4101 }
4102 }
4103
4104 if (lfHeight == -1)
4105 lfHeight = -2;
4106
4107 if (FontGDI->Magic == FONTGDI_MAGIC &&
4108 FontGDI->lfHeight == lfHeight &&
4109 FontGDI->lfWidth == lfWidth)
4110 {
4111 return 0; /* Cached */
4112 }
4113
4117
4118 if (!pOS2 || !pHori)
4119 {
4120 error = FT_Get_WinFNT_Header(face, &WinFNT);
4121 if (error)
4122 {
4123 DPRINT1("%s: Failed to request font size.\n", face->family_name);
4124 return error;
4125 }
4126
4127 FontGDI->tmHeight = WinFNT.pixel_height;
4128 FontGDI->tmAscent = WinFNT.ascent;
4129 FontGDI->tmDescent = FontGDI->tmHeight - FontGDI->tmAscent;
4130 FontGDI->tmInternalLeading = WinFNT.internal_leading;
4131 FontGDI->Magic = FONTGDI_MAGIC;
4132 FontGDI->lfHeight = lfHeight;
4133 FontGDI->lfWidth = lfWidth;
4134 return 0;
4135 }
4136
4137 /*
4138 * NOTE: We cast TT_OS2.usWinAscent and TT_OS2.usWinDescent to signed FT_Short.
4139 * Why? See: https://learn.microsoft.com/en-us/typography/opentype/spec/os2#uswindescent
4140 *
4141 * > usWinDescent is "usually" a positive value ...
4142 *
4143 * We can read it as "not always". See CORE-14994.
4144 * See also: https://learn.microsoft.com/en-us/typography/opentype/spec/os2#fsselection
4145 */
4146#define FM_SEL_USE_TYPO_METRICS 0x80
4147 if (lfHeight > 0)
4148 {
4149 /* case (A): lfHeight is positive */
4150 Sum = (FT_Short)pOS2->usWinAscent + (FT_Short)pOS2->usWinDescent;
4151 if (Sum == 0 || (pOS2->fsSelection & FM_SEL_USE_TYPO_METRICS))
4152 {
4153 Ascent = pHori->Ascender;
4154 Descent = -pHori->Descender;
4155 Sum = Ascent + Descent;
4156 }
4157 else
4158 {
4159 Ascent = (FT_Short)pOS2->usWinAscent;
4160 Descent = (FT_Short)pOS2->usWinDescent;
4161 }
4162
4163 FontGDI->tmAscent = FT_MulDiv(lfHeight, Ascent, Sum);
4164 FontGDI->tmDescent = FT_MulDiv(lfHeight, Descent, Sum);
4165 FontGDI->tmHeight = FontGDI->tmAscent + FontGDI->tmDescent;
4166 FontGDI->tmInternalLeading = FontGDI->tmHeight - FT_MulDiv(lfHeight, face->units_per_EM, Sum);
4167 }
4168 else if (lfHeight < 0)
4169 {
4170 /* case (B): lfHeight is negative */
4172 {
4173 FontGDI->tmAscent = FT_MulDiv(-lfHeight, pHori->Ascender, face->units_per_EM);
4174 FontGDI->tmDescent = FT_MulDiv(-lfHeight, -pHori->Descender, face->units_per_EM);
4175 }
4176 else
4177 {
4178 FontGDI->tmAscent = FT_MulDiv(-lfHeight, (FT_Short)pOS2->usWinAscent, face->units_per_EM);
4179 FontGDI->tmDescent = FT_MulDiv(-lfHeight, (FT_Short)pOS2->usWinDescent, face->units_per_EM);
4180 }
4181 FontGDI->tmHeight = FontGDI->tmAscent + FontGDI->tmDescent;
4182 FontGDI->tmInternalLeading = FontGDI->tmHeight + lfHeight;
4183 }
4184#undef FM_SEL_USE_TYPO_METRICS
4185
4186 FontGDI->Magic = FONTGDI_MAGIC;
4187 FontGDI->lfHeight = lfHeight;
4188 FontGDI->lfWidth = lfWidth;
4189
4190 EmHeight = FontGDI->tmHeight - FontGDI->tmInternalLeading;
4191 EmHeight = max(EmHeight, 1);
4192 EmHeight = min(EmHeight, USHORT_MAX);
4193
4194#if 1
4195 /* I think this is wrong implementation but its test result is better. */
4196 if (lfWidth != 0)
4197 req.width = FT_MulDiv(lfWidth, face->units_per_EM, pOS2->xAvgCharWidth) << 6;
4198#else
4199 /* I think this is correct implementation but it is mismatching to the
4200 other metric functions. The test result is bad. */
4201 if (lfWidth != 0)
4202 req.width = (FT_MulDiv(lfWidth, 96 * 5, 72 * 3) << 6); /* ??? FIXME */
4203#endif
4204 else
4205 req.width = 0;
4206
4207 /* HACK: We do not handle small widths well, so just use zero for these. See CORE-19870. */
4208 if (lfWidth < 10)
4209 req.width = 0;
4210
4212 req.height = (EmHeight << 6);
4213 req.horiResolution = 0;
4214 req.vertResolution = 0;
4215 return FT_Request_Size(face, &req);
4216}
4217
4220 PTEXTOBJ TextObj,
4221 PFONTGDI FontGDI,
4222 BOOL bDoLock)
4223{
4224 FT_Face face;
4225 INT error, n;
4226 FT_CharMap charmap, found;
4227 LOGFONTW *plf;
4228
4229 if (bDoLock)
4231
4232 face = FontGDI->SharedFace->Face;
4233 if (face->charmap == NULL)
4234 {
4235 DPRINT("WARNING: No charmap selected!\n");
4236 DPRINT("This font face has %d charmaps\n", face->num_charmaps);
4237
4238 found = NULL;
4239 for (n = 0; n < face->num_charmaps; n++)
4240 {
4241 charmap = face->charmaps[n];
4242 if (charmap->encoding == FT_ENCODING_UNICODE)
4243 {
4244 found = charmap;
4245 break;
4246 }
4247 }
4248 if (!found)
4249 {
4250 for (n = 0; n < face->num_charmaps; n++)
4251 {
4252 charmap = face->charmaps[n];
4253 if (charmap->platform_id == TT_PLATFORM_APPLE_UNICODE)
4254 {
4255 found = charmap;
4256 break;
4257 }
4258 }
4259 }
4260 if (!found)
4261 {
4262 for (n = 0; n < face->num_charmaps; n++)
4263 {
4264 charmap = face->charmaps[n];
4265 if (charmap->encoding == FT_ENCODING_MS_SYMBOL)
4266 {
4267 found = charmap;
4268 break;
4269 }
4270 }
4271 }
4272 if (!found && face->num_charmaps > 0)
4273 {
4274 found = face->charmaps[0];
4275 }
4276 if (!found)
4277 {
4278 DPRINT1("WARNING: Could not find desired charmap!\n");
4279 }
4280 else
4281 {
4282 DPRINT("Found charmap encoding: %i\n", found->encoding);
4283 error = FT_Set_Charmap(face, found);
4284 if (error)
4285 {
4286 DPRINT1("WARNING: Could not set the charmap!\n");
4287 }
4288 }
4289 }
4290
4291 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
4292
4293 error = IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
4294
4295 if (bDoLock)
4297
4298 if (error)
4299 {
4300 DPRINT1("Error in setting pixel sizes: %d\n", error);
4301 return FALSE;
4302 }
4303
4304 return TRUE;
4305}
4306
4307static inline FT_UInt FASTCALL
4309{
4310 FT_UInt ret;
4311
4312 if (glyph < 0x100) glyph += 0xf000;
4313 /* there are a number of old pre-Unicode "broken" TTFs, which
4314 do have symbols at U+00XX instead of U+f0XX */
4315 if (!(ret = FT_Get_Char_Index(ft_face, glyph)))
4316 ret = FT_Get_Char_Index(ft_face, glyph - 0xf000);
4317
4318 return ret;
4319}
4320
4321static inline FT_UInt FASTCALL
4323{
4324 FT_UInt ret;
4325
4326 if (face_has_symbol_charmap(ft_face))
4327 {
4328 ret = get_glyph_index_symbol(ft_face, glyph);
4329 if (ret != 0)
4330 return ret;
4331 }
4332
4333 return FT_Get_Char_Index(ft_face, glyph);
4334}
4335
4336static inline FT_UInt FASTCALL
4338{
4339 return (fCodeAsIndex ? code : get_glyph_index(face, code));
4340}
4341
4342static inline VOID
4344 _In_ PFONTLINK_CHAIN pChain)
4345{
4346#if 0
4347 PLIST_ENTRY Entry, Head;
4348 PFONTLINK pFontLink;
4349 INT iLink = 0;
4350
4351 DPRINT1("%S, %p, %p\n", pChain->LogFont.lfFaceName, pChain->pBaseTextObj, pChain->pDefFace);
4352
4353 Head = &pChain->FontLinkList;
4354 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
4355 {
4356 pFontLink = CONTAINING_RECORD(Entry, FONTLINK, ListEntry);
4357 DPRINT1("FontLink #%d: %p, %d, %S, %p, %p\n",
4358 iLink, pFontLink, pFontLink->bIgnore, pFontLink->LogFont.lfFaceName,
4359 pFontLink->pFontGDI, pFontLink->SharedFace);
4360 ++iLink;
4361 }
4362#endif
4363}
4364
4367static UINT
4369 _Inout_ PFONTLINK_CHAIN pChain,
4370 _Out_ PFONT_CACHE_ENTRY pCache,
4371 _Inout_ FT_Face *pFace,
4372 _In_ UINT code,
4373 _In_ BOOL fCodeAsIndex)
4374{
4375 PFONTLINK pFontLink;
4376 PLIST_ENTRY Entry, Head;
4377 UINT index;
4378 FT_Face face;
4379
4380 // Try the default font at first
4381 index = get_glyph_index_flagged(pChain->pDefFace, code, fCodeAsIndex);
4382 if (index)
4383 {
4384 DPRINT("code: 0x%08X, index: 0x%08X, fCodeAsIndex:%d\n", code, index, fCodeAsIndex);
4385 pCache->Hashed.Face = *pFace = pChain->pDefFace;
4386 return index; // The glyph is found on the default font
4387 }
4388
4389 if (!FontLink_Chain_IsPopulated(pChain)) // The chain is not populated yet
4390 {
4392 FontLink_Chain_Dump(pChain);
4393 }
4394
4395 // Now the chain is populated. Looking for the target glyph...
4396 Head = &pChain->FontLinkList;
4397 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
4398 {
4399 pFontLink = CONTAINING_RECORD(Entry, FONTLINK, ListEntry);
4400 if (!FontLink_PrepareFontInfo(pFontLink))
4401 continue; // This link is not useful, check the next one
4402
4403 face = pFontLink->SharedFace->Face;
4405 if (!index)
4406 continue; // The glyph does not exist, continue searching
4407
4408 // The target glyph is found in the chain
4409 DPRINT("code: 0x%08X, index: 0x%08X\n", code, index);
4410 pCache->Hashed.Face = *pFace = face;
4411 FT_Set_Transform(face, &pCache->Hashed.matTransform, NULL);
4412 return index;
4413 }
4414
4415 // No target glyph found in the chain: use default glyph
4417 index = get_glyph_index(*pFace, code);
4418 DPRINT("code: 0x%08X, index: 0x%08X\n", code, index);
4419 pCache->Hashed.Face = *pFace = pChain->pDefFace;
4420 return index;
4421}
4422
4423/*
4424 * Based on WineEngGetGlyphOutline
4425 */
4426ULONG
4429 PDC dc,
4430 WCHAR wch,
4431 UINT iFormat,
4432 LPGLYPHMETRICS pgm,
4433 ULONG cjBuf,
4434 PVOID pvBuf,
4435 const MAT2 *pmat2,
4436 BOOL bIgnoreRotation)
4437{
4438 PDC_ATTR pdcattr;
4439 PTEXTOBJ TextObj;
4440 PFONTGDI FontGDI;
4441 HFONT hFont = 0;
4442 GLYPHMETRICS gm;
4443 ULONG Size;
4444 FT_Face ft_face;
4445 FT_UInt glyph_index;
4446 DWORD width, height, pitch, needed = 0;
4447 FT_Bitmap ft_bitmap;
4449 INT left, right, top = 0, bottom = 0;
4451 FLOATOBJ eM11, widthRatio, eTemp;
4452 FT_Matrix mat, transMat = identityMat;
4453 BOOL needsTransform = FALSE;
4454 INT orientation;
4455 LONG aveWidth;
4456 INT adv, lsb, bbx; /* These three hold to widths of the unrotated chars */
4457 OUTLINETEXTMETRICW *potm;
4458 XFORMOBJ xo;
4459 XFORML xform;
4460 LOGFONTW *plf;
4461
4462 DPRINT("%u, %08x, %p, %08lx, %p, %p\n", wch, iFormat, pgm,
4463 cjBuf, pvBuf, pmat2);
4464
4465 pdcattr = dc->pdcattr;
4466
4467 XFORMOBJ_vInit(&xo, &dc->pdcattr->mxWorldToDevice);
4468 XFORMOBJ_iGetXform(&xo, &xform);
4469 FLOATOBJ_SetFloat(&eM11, xform.eM11);
4470
4471 hFont = pdcattr->hlfntNew;
4472 TextObj = RealizeFontInit(hFont);
4473
4474 if (!TextObj)
4475 {
4477 return GDI_ERROR;
4478 }
4479 FontGDI = ObjToGDI(TextObj->Font, FONT);
4480 ft_face = FontGDI->SharedFace->Face;
4481
4482 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
4483 aveWidth = FT_IS_SCALABLE(ft_face) ? abs(plf->lfWidth) : 0;
4484 orientation = FT_IS_SCALABLE(ft_face) ? plf->lfOrientation : 0;
4485
4487 Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL, FALSE);
4488 if (!Size)
4489 {
4490 TEXTOBJ_UnlockText(TextObj);
4492 return GDI_ERROR;
4493 }
4495 if (!potm)
4496 {
4497 TEXTOBJ_UnlockText(TextObj);
4499 return GDI_ERROR;
4500 }
4502 Size = IntGetOutlineTextMetrics(FontGDI, Size, potm, FALSE);
4503 if (!Size)
4504 {
4506 TEXTOBJ_UnlockText(TextObj);
4508 return GDI_ERROR;
4509 }
4510
4512 TextIntUpdateSize(dc, TextObj, FontGDI, FALSE);
4514 FT_Set_Transform(ft_face, &mat, NULL);
4515
4516 TEXTOBJ_UnlockText(TextObj);
4517
4518 glyph_index = get_glyph_index_flagged(ft_face, wch, (iFormat & GGO_GLYPH_INDEX));
4519 iFormat &= ~GGO_GLYPH_INDEX;
4520
4521 if (orientation || (iFormat != GGO_METRICS && iFormat != GGO_BITMAP) || aveWidth || pmat2)
4522 load_flags |= FT_LOAD_NO_BITMAP;
4523
4524 if (iFormat & GGO_UNHINTED)
4525 {
4526 load_flags |= FT_LOAD_NO_HINTING;
4527 iFormat &= ~GGO_UNHINTED;
4528 }
4529
4530 error = FT_Load_Glyph(ft_face, glyph_index, load_flags);
4531 if (error)
4532 {
4533 DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
4535 if (potm) ExFreePoolWithTag(potm, GDITAG_TEXT);
4536 return GDI_ERROR;
4537 }
4539
4540 FLOATOBJ_Set1(&widthRatio);
4541 if (aveWidth && potm)
4542 {
4543 // widthRatio = aveWidth * eM11 / potm->otmTextMetrics.tmAveCharWidth
4544 FLOATOBJ_SetLong(&widthRatio, aveWidth);
4545 FLOATOBJ_Mul(&widthRatio, &eM11);
4547 }
4548
4549 //left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64;
4550 FLOATOBJ_SetLong(&eTemp, ft_face->glyph->metrics.horiBearingX);
4551 FLOATOBJ_Mul(&eTemp, &widthRatio);
4552 left = FLOATOBJ_GetLong(&eTemp) & -64;
4553
4554 //right = (INT)((ft_face->glyph->metrics.horiBearingX +
4555 // ft_face->glyph->metrics.width) * widthRatio + 63) & -64;
4556 FLOATOBJ_SetLong(&eTemp, ft_face->glyph->metrics.horiBearingX * ft_face->glyph->metrics.width);
4557 FLOATOBJ_Mul(&eTemp, &widthRatio);
4558 FLOATOBJ_AddLong(&eTemp, 63);
4559 right = FLOATOBJ_GetLong(&eTemp) & -64;
4560
4561 //adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6;
4562 FLOATOBJ_SetLong(&eTemp, ft_face->glyph->metrics.horiAdvance);
4563 FLOATOBJ_Mul(&eTemp, &widthRatio);
4564 FLOATOBJ_AddLong(&eTemp, 63);
4565 adv = FLOATOBJ_GetLong(&eTemp) >> 6;
4566
4567 lsb = left >> 6;
4568 bbx = (right - left) >> 6;
4569
4570 DPRINT("Advance = %d, lsb = %d, bbx = %d\n",adv, lsb, bbx);
4571
4573
4574 /* Width scaling transform */
4575 if (!FLOATOBJ_Equal1(&widthRatio))
4576 {
4577 FT_Matrix scaleMat;
4578
4579 eTemp = widthRatio;
4580 FLOATOBJ_MulLong(&eTemp, 1 << 16);
4581
4582 scaleMat.xx = FLOATOBJ_GetLong(&eTemp);
4583 scaleMat.xy = 0;
4584 scaleMat.yx = 0;
4585 scaleMat.yy = INT_TO_FIXED(1);
4586 FT_Matrix_Multiply(&scaleMat, &transMat);
4587 needsTransform = TRUE;
4588 }
4589
4590 /* World transform */
4591 {
4592 FT_Matrix ftmatrix;
4594
4595 /* Create a freetype matrix, by converting to 16.16 fixpoint format */
4596 IntMatrixFromMx(&ftmatrix, pmx);
4597
4598 if (memcmp(&ftmatrix, &identityMat, sizeof(identityMat)) != 0)
4599 {
4600 FT_Matrix_Multiply(&ftmatrix, &transMat);
4601 needsTransform = TRUE;
4602 }
4603 }
4604
4605 /* Rotation transform */
4606 if (orientation)
4607 {
4608 FT_Matrix rotationMat;
4609 DPRINT("Rotation Trans!\n");
4610 IntEscapeMatrix(&rotationMat, orientation);
4611 FT_Matrix_Multiply(&rotationMat, &transMat);
4612 needsTransform = TRUE;
4613 }
4614
4615 /* Extra transformation specified by caller */
4616 if (pmat2)
4617 {
4618 FT_Matrix extraMat;
4619 DPRINT("MAT2 Matrix Trans!\n");
4620 extraMat.xx = FT_FixedFromFIXED(pmat2->eM11);
4621 extraMat.xy = FT_FixedFromFIXED(pmat2->eM21);
4622 extraMat.yx = FT_FixedFromFIXED(pmat2->eM12);
4623 extraMat.yy = FT_FixedFromFIXED(pmat2->eM22);
4624 FT_Matrix_Multiply(&extraMat, &transMat);
4625 needsTransform = TRUE;
4626 }
4627
4628 if (potm) ExFreePoolWithTag(potm, GDITAG_TEXT); /* It looks like we are finished with potm ATM. */
4629
4630 if (!needsTransform)
4631 {
4632 DPRINT("No Need to be Transformed!\n");
4633 top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
4634 bottom = (ft_face->glyph->metrics.horiBearingY -
4635 ft_face->glyph->metrics.height) & -64;
4636 gm.gmCellIncX = adv;
4637 gm.gmCellIncY = 0;
4638 }
4639 else
4640 {
4641 INT xc, yc;
4642 FT_Vector vec;
4643 for (xc = 0; xc < 2; xc++)
4644 {
4645 for (yc = 0; yc < 2; yc++)
4646 {
4647 vec.x = (ft_face->glyph->metrics.horiBearingX +
4648 xc * ft_face->glyph->metrics.width);
4649 vec.y = ft_face->glyph->metrics.horiBearingY -
4650 yc * ft_face->glyph->metrics.height;
4651 DPRINT("Vec %ld,%ld\n", vec.x, vec.y);
4652 FT_Vector_Transform(&vec, &transMat);
4653 if (xc == 0 && yc == 0)
4654 {
4655 left = right = vec.x;
4656 top = bottom = vec.y;
4657 }
4658 else
4659 {
4660 if (vec.x < left) left = vec.x;
4661 else if (vec.x > right) right = vec.x;
4662 if (vec.y < bottom) bottom = vec.y;
4663 else if (vec.y > top) top = vec.y;
4664 }
4665 }
4666 }
4667 left = left & -64;
4668 right = (right + 63) & -64;
4669 bottom = bottom & -64;
4670 top = (top + 63) & -64;
4671
4672 DPRINT("Transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
4673 vec.x = ft_face->glyph->metrics.horiAdvance;
4674 vec.y = 0;
4675 FT_Vector_Transform(&vec, &transMat);
4676 gm.gmCellIncX = (vec.x+63) >> 6;
4677 gm.gmCellIncY = -((vec.y+63) >> 6);
4678 }
4679 gm.gmBlackBoxX = (right - left) >> 6;
4680 gm.gmBlackBoxY = (top - bottom) >> 6;
4681 gm.gmptGlyphOrigin.x = left >> 6;
4682 gm.gmptGlyphOrigin.y = top >> 6;
4683
4684 DPRINT("CX %d CY %d BBX %u BBY %u GOX %d GOY %d\n",
4685 gm.gmCellIncX, gm.gmCellIncY,
4686 gm.gmBlackBoxX, gm.gmBlackBoxY,
4688
4690
4691 if (iFormat == GGO_METRICS)
4692 {
4693 DPRINT("GGO_METRICS Exit!\n");
4694 *pgm = gm;
4695 return 1; /* FIXME */
4696 }
4697
4698 if (ft_face->glyph->format != ft_glyph_format_outline && iFormat != GGO_BITMAP)
4699 {
4700 DPRINT1("Loaded a bitmap\n");
4701 return GDI_ERROR;
4702 }
4703
4704 switch (iFormat)
4705 {
4706 case GGO_BITMAP:
4707 {
4708 width = gm.gmBlackBoxX;
4709 height = gm.gmBlackBoxY;
4710 pitch = ((width + 31) >> 5) << 2;
4711 needed = pitch * height;
4712
4713 if (!pvBuf || !cjBuf) break;
4714 if (!needed) return GDI_ERROR; /* empty glyph */
4715 if (needed > cjBuf)
4716 return GDI_ERROR;
4717
4718 switch (ft_face->glyph->format)
4719 {
4721 {
4722 BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
4723 INT w = min( pitch, (ft_face->glyph->bitmap.width + 7) >> 3 );
4724 INT h = min( height, ft_face->glyph->bitmap.rows );
4725 while (h--)
4726 {
4728 src += ft_face->glyph->bitmap.pitch;
4729 dst += pitch;
4730 }
4731 break;
4732 }
4733
4735 {
4736 ft_bitmap.width = width;
4737 ft_bitmap.rows = height;
4738 ft_bitmap.pitch = pitch;
4739 ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
4740 ft_bitmap.buffer = pvBuf;
4741
4743 if (needsTransform)
4744 {
4745 FT_Outline_Transform(&ft_face->glyph->outline, &transMat);
4746 }
4747 FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
4748 /* Note: FreeType will only set 'black' bits for us. */
4749 RtlZeroMemory(pvBuf, needed);
4750 FT_Outline_Get_Bitmap(g_FreeTypeLibrary, &ft_face->glyph->outline, &ft_bitmap);
4752 break;
4753 }
4754
4755 default:
4756 DPRINT1("Loaded glyph format %x\n", ft_face->glyph->format);
4757 return GDI_ERROR;
4758 }
4759
4760 break;
4761 }
4762
4763 case GGO_GRAY2_BITMAP:
4764 case GGO_GRAY4_BITMAP:
4765 case GGO_GRAY8_BITMAP:
4766 {
4767 unsigned int mult, row, col;
4768 BYTE *start, *ptr;
4769
4770 width = gm.gmBlackBoxX;
4771 height = gm.gmBlackBoxY;
4772 pitch = (width + 3) / 4 * 4;
4773 needed = pitch * height;
4774
4775 if (!pvBuf || !cjBuf) break;
4776 if (!needed) return GDI_ERROR; /* empty glyph */
4777 if (needed > cjBuf)
4778 return GDI_ERROR;
4779
4780 switch (ft_face->glyph->format)
4781 {
4783 {
4784 BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
4785 INT h = min( height, ft_face->glyph->bitmap.rows );
4786 INT x;
4787 while (h--)
4788 {
4789 for (x = 0; (UINT)x < pitch; x++)
4790 {
4791 if (x < ft_face->glyph->bitmap.width)
4792 dst[x] = (src[x / 8] & (1 << ( (7 - (x % 8))))) ? 0xff : 0;
4793 else
4794 dst[x] = 0;
4795 }
4796 src += ft_face->glyph->bitmap.pitch;
4797 dst += pitch;
4798 }
4799 break;
4800 }
4802 {
4803 ft_bitmap.width = width;
4804 ft_bitmap.rows = height;
4805 ft_bitmap.pitch = pitch;
4806 ft_bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
4807 ft_bitmap.buffer = pvBuf;
4808
4810 if (needsTransform)
4811 {
4812 FT_Outline_Transform(&ft_face->glyph->outline, &transMat);
4813 }
4814 FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
4815 RtlZeroMemory(ft_bitmap.buffer, cjBuf);
4816 FT_Outline_Get_Bitmap(g_FreeTypeLibrary, &ft_face->glyph->outline, &ft_bitmap);
4818
4820 mult = 4;
4821 else if (iFormat == GGO_GRAY4_BITMAP)
4822 mult = 16;
4823 else if (iFormat == GGO_GRAY8_BITMAP)
4824 mult = 64;
4825 else
4826 {
4827 return GDI_ERROR;
4828 }
4829
4830 start = pvBuf;
4831 for (row = 0; row < height; row++)
4832 {
4833 ptr = start;
4834 for (col = 0; col < width; col++, ptr++)
4835 {
4836 *ptr = (((int)*ptr) * mult + 128) / 256;
4837 }
4838 start += pitch;
4839 }
4840
4841 break;
4842 }
4843 default:
4844 DPRINT1("Loaded glyph format %x\n", ft_face->glyph->format);
4845 return GDI_ERROR;
4846 }
4847
4848 break;
4849 }
4850
4851 case GGO_NATIVE:
4852 {
4853 FT_Outline *outline = &ft_face->glyph->outline;
4854
4855 if (cjBuf == 0) pvBuf = NULL; /* This is okay, need cjBuf to allocate. */
4856
4858 if (needsTransform && pvBuf) FT_Outline_Transform(outline, &transMat);
4859
4861
4862 if (!pvBuf || !cjBuf)
4863 {
4865 break;
4866 }
4867 if (needed > cjBuf)
4868 {
4870 return GDI_ERROR;
4871 }
4874 break;
4875 }
4876
4877 case GGO_BEZIER:
4878 {
4879 FT_Outline *outline = &ft_face->glyph->outline;
4880 if (cjBuf == 0) pvBuf = NULL;
4881
4882 if (needsTransform && pvBuf)
4883 {
4885 FT_Outline_Transform(outline, &transMat);
4887 }
4889
4890 if (!pvBuf || !cjBuf)
4891 break;
4892 if (needed > cjBuf)
4893 return GDI_ERROR;
4894
4896 break;
4897 }
4898
4899 default:
4900 DPRINT1("Unsupported format %u\n", iFormat);
4901 return GDI_ERROR;
4902 }
4903
4904 DPRINT("ftGdiGetGlyphOutline END and needed %lu\n", needed);
4905
4906 if (gm.gmBlackBoxX == 0)
4907 gm.gmBlackBoxX = 1;
4908 if (gm.gmBlackBoxY == 0)
4909 gm.gmBlackBoxY = 1;
4910
4911 *pgm = gm;
4912 return needed;
4913}
4914
4915static FT_BitmapGlyph
4918{
4919 INT error;
4920 FT_GlyphSlot glyph;
4921 FT_BitmapGlyph realglyph;
4922
4924
4925 Cache->dwHash = IntGetHash(&Cache->Hashed, sizeof(Cache->Hashed) / sizeof(DWORD));
4926
4927 realglyph = IntFindGlyphCache(Cache);
4928 if (realglyph)
4929 return realglyph;
4930
4931 error = FT_Load_Glyph(Cache->Hashed.Face, Cache->Hashed.GlyphIndex, FT_LOAD_DEFAULT);
4932 if (error)
4933 {
4934 DPRINT1("WARNING: Failed to load and render glyph! [index: %d]\n", Cache->Hashed.GlyphIndex);
4935 return NULL;
4936 }
4937
4938 glyph = Cache->Hashed.Face->glyph;
4939
4940 if (Cache->Hashed.Aspect.Emu.Bold)
4941 FT_GlyphSlot_Embolden(glyph); /* Emulate Bold */
4942
4943 if (Cache->Hashed.Aspect.Emu.Italic)
4944 FT_GlyphSlot_Oblique(glyph); /* Emulate Italic */
4945
4946 realglyph = IntGetBitmapGlyphWithCache(Cache, glyph);
4947
4948 if (!realglyph)
4949 DPRINT1("Failed to render glyph! [index: %d]\n", Cache->Hashed.GlyphIndex);
4950
4951 return realglyph;
4952}
4953
4954BOOL
4957 _In_ PDC dc,
4958 _In_ PTEXTOBJ TextObj,
4960 _In_ INT Count,
4961 _In_ ULONG MaxExtent,
4962 _Out_ PINT Fit,
4963 _Out_writes_to_opt_(Count, *Fit) PINT Dx,
4965 _In_ FLONG fl)
4966{
4967 PFONTGDI FontGDI;
4968 FT_BitmapGlyph realglyph;
4969 INT glyph_index, i, previous, nTenthsOfDegrees;
4970 ULONGLONG TotalWidth64 = 0;
4971 LOGFONTW *plf;
4972 BOOL use_kerning, bVerticalWriting;
4973 LONG ascender, descender;
4975 DWORD ch0, ch1;
4976 FONTLINK_CHAIN Chain;
4977
4978 FontGDI = ObjToGDI(TextObj->Font, FONT);
4979
4980 Cache.Hashed.Face = FontGDI->SharedFace->Face;
4981 if (NULL != Fit)
4982 {
4983 *Fit = 0;
4984 }
4985
4986 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
4987 Cache.Hashed.lfHeight = plf->lfHeight;
4988 Cache.Hashed.lfWidth = plf->lfWidth;
4989 Cache.Hashed.Aspect.Emu.Bold = EMUBOLD_NEEDED(FontGDI->OriginalWeight, plf->lfWeight);
4990 Cache.Hashed.Aspect.Emu.Italic = (plf->lfItalic && !FontGDI->OriginalItalic);
4991
4992 // Check vertical writing (tategaki)
4993 nTenthsOfDegrees = IntNormalizeAngle(plf->lfEscapement - plf->lfOrientation);
4994 bVerticalWriting = ((nTenthsOfDegrees == 90 * 10) || (nTenthsOfDegrees == 270 * 10));
4995
4997 Cache.Hashed.Aspect.RenderMode = (BYTE)IntGetFontRenderMode(plf);
4998 else
4999 Cache.Hashed.Aspect.RenderMode = (BYTE)FT_RENDER_MODE_MONO;
5000
5001 // NOTE: GetTextExtentPoint32 simply ignores lfEscapement and XFORM.
5003 TextIntUpdateSize(dc, TextObj, FontGDI, FALSE);
5004 Cache.Hashed.matTransform = identityMat;
5005 FT_Set_Transform(Cache.Hashed.Face, NULL, NULL);
5006
5007 FontLink_Chain_Init(&Chain, TextObj, Cache.Hashed.Face);
5008
5009 use_kerning = FT_HAS_KERNING(Cache.Hashed.Face);
5010 previous = 0;
5011
5012 for (i = 0; i < Count; i++)
5013 {
5014 ch0 = *String++;
5015 if (IS_HIGH_SURROGATE(ch0))
5016 {
5017 ++i;
5018 if (i >= Count)
5019 break;
5020
5021 ch1 = *String++;
5022 if (IS_LOW_SURROGATE(ch1))
5023 ch0 = Utf32FromSurrogatePair(ch0, ch1);
5024 }
5025
5026 glyph_index = FontLink_Chain_FindGlyph(&Chain, &Cache, &Cache.Hashed.Face, ch0,
5027 (fl & GTEF_INDICES));
5028 Cache.Hashed.GlyphIndex = glyph_index;
5029
5030 realglyph = IntGetRealGlyph(&Cache);
5031 if (!realglyph)
5032 break;
5033
5034 /* Retrieve kerning distance */
5035 if (use_kerning && previous && glyph_index)
5036 {
5037 FT_Vector delta;
5038 FT_Get_Kerning(Cache.Hashed.Face, previous, glyph_index, 0, &delta);
5039 TotalWidth64 += delta.x;
5040 }
5041
5042 TotalWidth64 += realglyph->root.advance.x >> 10;
5043
5044 if (((TotalWidth64 + 32) >> 6) <= MaxExtent && NULL != Fit)
5045 {
5046 *Fit = i + 1;
5047 }
5048 if (NULL != Dx)
5049 {
5050 Dx[i] = (TotalWidth64 + 32) >> 6;
5051 }
5052
5053 previous = glyph_index;
5054 }
5055 ASSERT(FontGDI->Magic == FONTGDI_MAGIC);
5056 ascender = FontGDI->tmAscent; /* Units above baseline */
5057 descender = FontGDI->tmDescent; /* Units below baseline */
5059
5060 if (bVerticalWriting)
5061 {
5062 Size->cx = ascender + descender;
5063 Size->cy = (TotalWidth64 + 32) >> 6;
5064 }
5065 else
5066 {
5067 Size->cx = (TotalWidth64 + 32) >> 6;
5068 Size->cy = ascender + descender;
5069 }
5070
5071 FontLink_Chain_Finish(&Chain);
5072
5073 return TRUE;
5074}
5075
5076INT
5079 PDC Dc,
5080 LPFONTSIGNATURE lpSig,
5081 DWORD dwFlags)
5082{
5083 PDC_ATTR pdcattr;
5084 UINT Ret = DEFAULT_CHARSET;
5085 INT i;
5086 HFONT hFont;
5087 PTEXTOBJ TextObj;
5088 PFONTGDI FontGdi;
5090 TT_OS2 *pOS2;
5091 FT_Face Face;
5092 CHARSETINFO csi;
5093 DWORD cp, fs0;
5094 USHORT usACP, usOEM;
5095
5096 pdcattr = Dc->pdcattr;
5097 hFont = pdcattr->hlfntNew;
5098 TextObj = RealizeFontInit(hFont);
5099
5100 if (!TextObj)
5101 {
5103 return Ret;
5104 }
5105 FontGdi = ObjToGDI(TextObj->Font, FONT);
5106 Face = FontGdi->SharedFace->Face;
5107 TEXTOBJ_UnlockText(TextObj);
5108
5109 memset(&fs, 0, sizeof(FONTSIGNATURE));
5111 pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
5112 if (NULL != pOS2)
5113 {
5114 fs.fsCsb[0] = pOS2->ulCodePageRange1;
5115 fs.fsCsb[1] = pOS2->ulCodePageRange2;
5116 fs.fsUsb[0] = pOS2->ulUnicodeRange1;
5117 fs.fsUsb[1] = pOS2->ulUnicodeRange2;
5118 fs.fsUsb[2] = pOS2->ulUnicodeRange3;
5119 fs.fsUsb[3] = pOS2->ulUnicodeRange4;
5120 if (pOS2->version == 0)
5121 {
5122 FT_UInt dummy;
5123
5124 if (FT_Get_First_Char( Face, &dummy ) < 0x100)
5125 fs.fsCsb[0] |= FS_LATIN1;
5126 else
5127 fs.fsCsb[0] |= FS_SYMBOL;
5128 }
5129 }
5130 pOS2 = NULL;
5132 DPRINT("Csb 1=%x 0=%x\n", fs.fsCsb[1],fs.fsCsb[0]);
5133 if (fs.fsCsb[0] == 0)
5134 { /* Let's see if we can find any interesting cmaps */
5135 for (i = 0; i < Face->num_charmaps; i++)
5136 {
5137 switch (Face->charmaps[i]->encoding)
5138 {
5139 case FT_ENCODING_UNICODE:
5140 case FT_ENCODING_APPLE_ROMAN:
5141 fs.fsCsb[0] |= FS_LATIN1;
5142 break;
5143 case FT_ENCODING_MS_SYMBOL:
5144 fs.fsCsb[0] |= FS_SYMBOL;
5145 break;
5146 default:
5147 break;
5148 }
5149 }
5150 }
5151 if (lpSig)
5152 {
5153 RtlCopyMemory(lpSig, &fs, sizeof(FONTSIGNATURE));
5154 }
5155
5156 RtlGetDefaultCodePage(&usACP, &usOEM);
5157 cp = usACP;
5158
5160 if (csi.fs.fsCsb[0] & fs.fsCsb[0])
5161 {
5162 DPRINT("Hit 1\n");
5163 Ret = csi.ciCharset;
5164 goto Exit;
5165 }
5166
5167 for (i = 0; i < MAXTCIINDEX; i++)
5168 {
5169 fs0 = 1L << i;
5170 if (fs.fsCsb[0] & fs0)
5171 {
5172 if (IntTranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG))
5173 {
5174 // *cp = csi.ciACP;
5175 DPRINT("Hit 2\n");
5176 Ret = csi.ciCharset;
5177 goto Exit;
5178 }
5179 else
5180 DPRINT1("TCI failing on %x\n", fs0);
5181 }
5182 }
5183Exit:
5184 DPRINT("CharSet %u CodePage %u\n", csi.ciCharset, csi.ciACP);
5185 return (MAKELONG(csi.ciACP, csi.ciCharset));
5186}
5187
5188
5189DWORD
5192{
5193 DWORD size = 0;
5194 DWORD num_ranges = 0;
5195 FT_Face face = Font->SharedFace->Face;
5196
5197 if (face->charmap == NULL)
5198 {
5199 DPRINT1("FIXME: No charmap selected! This is a BUG!\n");
5200 return 0;
5201 }
5202
5203 if (face->charmap->encoding == FT_ENCODING_UNICODE)
5204 {
5205 FT_UInt glyph_code = 0;
5206 FT_ULong char_code, char_code_prev;
5207
5208 char_code_prev = char_code = FT_Get_First_Char(face, &glyph_code);
5209
5210 DPRINT("Face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
5211 face->num_glyphs, glyph_code, char_code);
5212
5213 if (!glyph_code) return 0;
5214
5215 if (glyphset)
5216 {
5217 glyphset->ranges[0].wcLow = (USHORT)char_code;
5218 glyphset->ranges[0].cGlyphs = 0;
5219 glyphset->cGlyphsSupported = 0;
5220 }
5221
5222 num_ranges = 1;
5223 while (glyph_code)
5224 {
5225 if (char_code < char_code_prev)
5226 {
5227 DPRINT1("Expected increasing char code from FT_Get_Next_Char\n");
5228 return 0;
5229 }
5230 if (char_code - char_code_prev > 1)
5231 {
5232 num_ranges++;
5233 if (glyphset)
5234 {
5235 glyphset->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
5236 glyphset->ranges[num_ranges - 1].cGlyphs = 1;
5237 glyphset->cGlyphsSupported++;
5238 }
5239 }
5240 else if (glyphset)
5241 {
5242 glyphset->ranges[num_ranges - 1].cGlyphs++;
5243 glyphset->cGlyphsSupported++;
5244 }
5245 char_code_prev = char_code;
5246 char_code = FT_Get_Next_Char(face, char_code, &glyph_code);
5247 }
5248 }
5249 else
5250 DPRINT1("Encoding %i not supported\n", face->charmap->encoding);
5251
5252 size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
5253 if (glyphset)
5254 {
5255 glyphset->cbThis = size;
5256 glyphset->cRanges = num_ranges;
5257 glyphset->flAccel = 0;
5258 }
5259 return size;
5260}
5261
5262
5263BOOL
5266 HDC hDC,
5267 PTMW_INTERNAL ptmwi)
5268{
5269 PDC dc;
5270 PDC_ATTR pdcattr;
5271 PTEXTOBJ TextObj;
5272 PFONTGDI FontGDI;
5273 FT_Face Face;
5274 TT_OS2 *pOS2;
5275 TT_HoriHeader *pHori;
5277 ULONG Error;
5279 LOGFONTW *plf;
5280
5281 if (!ptmwi)
5282 {
5284 return FALSE;
5285 }
5286 RtlZeroMemory(ptmwi, sizeof(TMW_INTERNAL));
5287
5288 if (!(dc = DC_LockDc(hDC)))
5289 {
5291 return FALSE;
5292 }
5293 pdcattr = dc->pdcattr;
5294 TextObj = RealizeFontInit(pdcattr->hlfntNew);
5295 if (NULL != TextObj)
5296 {
5297 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
5298 FontGDI = ObjToGDI(TextObj->Font, FONT);
5299
5300 Face = FontGDI->SharedFace->Face;
5301
5302 // NOTE: GetTextMetrics simply ignores lfEscapement and XFORM.
5304 Error = IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
5305 FT_Set_Transform(Face, NULL, NULL);
5306
5308
5309 if (0 != Error)
5310 {
5311 DPRINT1("Error in setting pixel sizes: %u\n", Error);
5313 }
5314 else
5315 {
5317
5319
5320 Error = FT_Get_WinFNT_Header(Face, &Win);
5321 pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
5322 pHori = FT_Get_Sfnt_Table(Face, ft_sfnt_hhea);
5323
5324 if (!pOS2 && Error)
5325 {
5326 DPRINT1("Can't find OS/2 table - not TT font?\n");
5328 }
5329
5330 if (!pHori && Error)
5331 {
5332 DPRINT1("Can't find HHEA table - not TT font?\n");
5334 }
5335
5336 if (NT_SUCCESS(Status))
5337 {
5338 FillTM(&ptmwi->TextMetric, FontGDI, pOS2, pHori, (Error ? NULL : &Win));
5339
5340 /* FIXME: Fill Diff member */
5341 }
5342
5344 }
5345 TEXTOBJ_UnlockText(TextObj);
5346 }
5347 else
5348 {
5350 }
5351 DC_UnlockDc(dc);
5352
5353 if (!NT_SUCCESS(Status))
5354 {
5356 return FALSE;
5357 }
5358 return TRUE;
5359}
5360
5361DWORD
5364 PFONTGDI FontGdi,
5365 DWORD Table,
5366 DWORD Offset,
5367 PVOID Buffer,
5368 DWORD Size)
5369{
5371 FT_Face Face = FontGdi->SharedFace->Face;
5372
5374
5375 if (FT_IS_SFNT(Face))
5376 {
5377 if (Table)
5378 Table = Table >> 24 | Table << 24 | (Table >> 8 & 0xFF00) |
5379 (Table << 8 & 0xFF0000);
5380
5381 if (!Buffer) Size = 0;
5382
5383 if (Buffer && Size)
5384 {
5386 FT_ULong Needed = 0;
5387
5388 Error = FT_Load_Sfnt_Table(Face, Table, Offset, NULL, &Needed);
5389
5390 if ( !Error && Needed < Size) Size = Needed;
5391 }
5392 if (!FT_Load_Sfnt_Table(Face, Table, Offset, Buffer, &Size))
5393 Result = Size;
5394 }
5395
5397
5398 return Result;
5399}
5400
5401#define GOT_PENALTY(name, value) Penalty += (value)
5402
5403// NOTE: See Table 1. of https://learn.microsoft.com/en-us/previous-versions/ms969909(v=msdn.10)
5404static UINT
5405GetFontPenalty(const LOGFONTW * LogFont,
5406 const OUTLINETEXTMETRICW * Otm,
5407 const char * style_name)
5408{
5409 ULONG Penalty = 0;
5410 BYTE Byte;
5411 LONG Long;
5412 BOOL fNeedScaling = FALSE;
5413 const BYTE UserCharSet = IntCharSetFromLangID(gusLanguageID);
5414 const TEXTMETRICW * TM = &Otm->otmTextMetrics;
5415 WCHAR* ActualNameW;
5416
5417 ASSERT(Otm);
5418 ASSERT(LogFont);
5419
5420 /* FIXME: IntSizeSynth Penalty 20 */
5421 /* FIXME: SmallPenalty Penalty 1 */
5422 /* FIXME: FaceNameSubst Penalty 500 */
5423
5424 Byte = LogFont->lfCharSet;
5425
5426 if (Byte != TM->tmCharSet)
5427 {
5429 {
5430 /* CharSet Penalty 65000 */
5431 /* Requested charset does not match the candidate's. */
5432 GOT_PENALTY("CharSet", 65000);
5433 }
5434 else
5435 {
5436 if (UserCharSet != TM->tmCharSet)
5437 {
5438 /* UNDOCUMENTED: Not user language */
5439 GOT_PENALTY("UNDOCUMENTED:NotUserLanguage", 100);
5440
5441 if (ANSI_CHARSET != TM->tmCharSet)
5442 {
5443 /* UNDOCUMENTED: Not ANSI charset */
5444 GOT_PENALTY("UNDOCUMENTED:NotAnsiCharSet", 100);
5445 }
5446 }
5447 }
5448 }
5449
5450 Byte = LogFont->lfOutPrecision;
5451 switch (Byte)
5452 {
5453 case OUT_DEFAULT_PRECIS:
5454 /* nothing to do */
5455 break;
5456 case OUT_DEVICE_PRECIS:
5457 if (!(TM->tmPitchAndFamily & TMPF_DEVICE) ||
5459 {
5460 /* OutputPrecision Penalty 19000 */
5461 /* Requested OUT_STROKE_PRECIS, but the device can't do it
5462 or the candidate is not a vector font. */
5463 GOT_PENALTY("OutputPrecision", 19000);
5464 }
5465 break;
5466 default:
5468 {
5469 /* OutputPrecision Penalty 19000 */
5470 /* Or OUT_STROKE_PRECIS not requested, and the candidate
5471 is a vector font that requires GDI support. */
5472 GOT_PENALTY("OutputPrecision", 19000);
5473 }
5474 break;
5475 }
5476
5477 Byte = (LogFont->lfPitchAndFamily & 0x0F);
5478 if (Byte == DEFAULT_PITCH)
5480 if (Byte == FIXED_PITCH)
5481 {
5483 {
5484 /* FixedPitch Penalty 15000 */
5485 /* Requested a fixed pitch font, but the candidate is a
5486 variable pitch font. */
5487 GOT_PENALTY("FixedPitch", 15000);
5488 }
5489 }
5490 if (Byte == VARIABLE_PITCH)
5491 {
5493 {
5494 /* PitchVariable Penalty 350 */
5495 /* Requested a variable pitch font, but the candidate is not a
5496 variable pitch font. */
5497 GOT_PENALTY("PitchVariable", 350);
5498 }
5499 }
5500
5501 Byte = (LogFont->lfPitchAndFamily & 0x0F);
5502 if (Byte == DEFAULT_PITCH)
5503 {
5505 {
5506 /* DefaultPitchFixed Penalty 1 */
5507 /* Requested DEFAULT_PITCH, but the candidate is fixed pitch. */
5508 GOT_PENALTY("DefaultPitchFixed", 1);
5509 }
5510 }
5511
5512 ActualNameW = (WCHAR*)((ULONG_PTR)Otm + (ULONG_PTR)Otm->otmpFamilyName);
5513
5514 if (LogFont->lfFaceName[0] != UNICODE_NULL)
5515 {
5516 BOOL Found = FALSE;
5517
5518 /* localized family name */
5519 if (!Found)
5520 {
5521 Found = (_wcsicmp(LogFont->lfFaceName, ActualNameW) == 0);
5522 }
5523 /* localized full name */
5524 if (!Found)
5525 {
5526 ActualNameW = (WCHAR*)((ULONG_PTR)Otm + (ULONG_PTR)Otm->otmpFaceName);
5527 Found = (_wcsicmp(LogFont->lfFaceName, ActualNameW) == 0);
5528 }
5529 if (!Found)
5530 {
5531 /* FaceName Penalty 10000 */
5532 /* Requested a face name, but the candidate's face name
5533 does not match. */
5534 GOT_PENALTY("FaceName", 10000);
5535 }
5536 }
5537
5538 Byte = (LogFont->lfPitchAndFamily & 0xF0);
5539 if (Byte != FF_DONTCARE)
5540 {
5541 if (Byte != (TM->tmPitchAndFamily & 0xF0))
5542 {
5543 /* Family Penalty 9000 */
5544 /* Requested a family, but the candidate's family is different. */
5545 GOT_PENALTY("Family", 9000);
5546 }
5547 }
5548
5549 if ((TM->tmPitchAndFamily & 0xF0) == FF_DONTCARE)
5550 {
5551 /* FamilyUnknown Penalty 8000 */
5552 /* Requested a family, but the candidate has no family. */
5553 GOT_PENALTY("FamilyUnknown", 8000);
5554 }
5555
5556 /* Is the candidate a non-vector font? */
5558 {
5559 /* Is lfHeight specified? */
5560 if (LogFont->lfHeight != 0)
5561 {
5562 if (labs(LogFont->lfHeight) < TM->tmHeight)
5563 {
5564 /* HeightBigger Penalty 600 */
5565 /* The candidate is a nonvector font and is bigger than the
5566 requested height. */
5567 GOT_PENALTY("HeightBigger", 600);
5568 /* HeightBiggerDifference Penalty 150 */
5569 /* The candidate is a raster font and is larger than the
5570 requested height. Penalty * height difference */
5571 GOT_PENALTY("HeightBiggerDifference", 150 * labs(TM->tmHeight - labs(LogFont->lfHeight)));
5572
5573 fNeedScaling = TRUE;
5574 }
5575 if (TM->tmHeight < labs(LogFont->lfHeight))
5576 {
5577 /* HeightSmaller Penalty 150 */
5578 /* The candidate is a raster font and is smaller than the
5579 requested height. Penalty * height difference */
5580 GOT_PENALTY("HeightSmaller", 150 * labs(TM->tmHeight - labs(LogFont->lfHeight)));
5581
5582 fNeedScaling = TRUE;
5583 }
5584 }
5585 }
5586
5587 switch (LogFont->lfPitchAndFamily & 0xF0)
5588 {
5589 case FF_ROMAN: case FF_MODERN: case FF_SWISS:
5590 switch (TM->tmPitchAndFamily & 0xF0)
5591 {
5592 case FF_DECORATIVE: case FF_SCRIPT:
5593 /* FamilyUnlikely Penalty 50 */
5594 /* Requested a roman/modern/swiss family, but the
5595 candidate is decorative/script. */
5596 GOT_PENALTY("FamilyUnlikely", 50);
5597 break;
5598 default:
5599 break;
5600 }
5601 break;
5602 case FF_DECORATIVE: case FF_SCRIPT:
5603 switch (TM->tmPitchAndFamily & 0xF0)
5604 {
5605 case FF_ROMAN: case FF_MODERN: case FF_SWISS:
5606 /* FamilyUnlikely Penalty 50 */
5607 /* Or requested decorative/script, and the candidate is
5608 roman/modern/swiss. */
5609 GOT_PENALTY("FamilyUnlikely", 50);
5610 break;
5611 default:
5612 break;
5613 }
5614 default:
5615 break;
5616 }
5617
5618 if (LogFont->lfWidth != 0)
5619 {
5620 if (LogFont->lfWidth != TM->tmAveCharWidth)
5621 {
5622 /* Width Penalty 50 */
5623 /* Requested a nonzero width, but the candidate's width
5624 doesn't match. Penalty * width difference */
5625 GOT_PENALTY("Width", 50 * labs(LogFont->lfWidth - TM->tmAveCharWidth));
5626
5628 fNeedScaling = TRUE;
5629 }
5630 }
5631
5632 if (fNeedScaling)
5633 {
5634 /* SizeSynth Penalty 50 */
5635 /* The candidate is a raster font that needs scaling by GDI. */
5636 GOT_PENALTY("SizeSynth", 50);
5637 }
5638
5639 if (!LogFont->lfItalic && TM->tmItalic)
5640 {
5641 /* Italic Penalty 4 */
5642 /* Requested font and candidate font do not agree on italic status,
5643 and the desired result cannot be simulated. */
5644 /* Adjusted to 40 to satisfy (Oblique Penalty > Book Penalty). */
5645 GOT_PENALTY("Italic", 40);
5646 }
5647 else if (LogFont->lfItalic && !TM->tmItalic)
5648 {
5649 /* ItalicSim Penalty 1 */
5650 /* Requested italic font but the candidate is not italic,
5651 although italics can be simulated. */
5652 GOT_PENALTY("ItalicSim", 1);
5653 }
5654
5655 if (LogFont->lfOutPrecision == OUT_TT_PRECIS)
5656 {
5657 if (!(TM->tmPitchAndFamily & TMPF_TRUETYPE))
5658 {
5659 /* NotTrueType Penalty 4 */
5660 /* Requested OUT_TT_PRECIS, but the candidate is not a
5661 TrueType font. */
5662 GOT_PENALTY("NotTrueType", 4);
5663 }
5664 }
5665
5666 Long = LogFont->lfWeight;
5667 if (LogFont->lfWeight == FW_DONTCARE)
5668 Long = FW_NORMAL;
5669 if (Long != TM->tmWeight)
5670 {
5671 /* Weight Penalty 3 */
5672 /* The candidate's weight does not match the requested weight.
5673 Penalty * (weight difference/10) */
5674 GOT_PENALTY("Weight", 3 * (labs(Long - TM->tmWeight) / 10));
5675 }
5676
5677 if (!LogFont->lfUnderline && TM->tmUnderlined)
5678 {
5679 /* Underline Penalty 3 */
5680 /* Requested font has no underline, but the candidate is
5681 underlined. */
5682 GOT_PENALTY("Underline", 3);
5683 }
5684
5685 if (!LogFont->lfStrikeOut && TM->tmStruckOut)
5686 {
5687 /* StrikeOut Penalty 3 */
5688 /* Requested font has no strike-out, but the candidate is
5689 struck out. */
5690 GOT_PENALTY("StrikeOut", 3);
5691 }
5692
5693 /* Is the candidate a non-vector font? */
5695 {
5696 if (LogFont->lfHeight != 0 && TM->tmHeight < LogFont->lfHeight)
5697 {
5698 /* VectorHeightSmaller Penalty 2 */
5699 /* Candidate is a vector font that is smaller than the
5700 requested height. Penalty * height difference */
5701 GOT_PENALTY("VectorHeightSmaller", 2 * labs(TM->tmHeight - LogFont->lfHeight));
5702 }
5703 if (LogFont->lfHeight != 0 && TM->tmHeight > LogFont->lfHeight)
5704 {
5705 /* VectorHeightBigger Penalty 1 */
5706 /* Candidate is a vector font that is bigger than the
5707 requested height. Penalty * height difference */
5708 GOT_PENALTY("VectorHeightBigger", 1 * labs(TM->tmHeight - LogFont->lfHeight));
5709 }
5710 }
5711
5712 if (!(TM->tmPitchAndFamily & TMPF_DEVICE))
5713 {
5714 /* DeviceFavor Penalty 2 */
5715 /* Extra penalty for all nondevice fonts. */
5716 GOT_PENALTY("DeviceFavor", 2);
5717 }
5718
5719 if (TM->tmAveCharWidth >= 5 && TM->tmHeight >= 5)
5720 {
5721 if (TM->tmAveCharWidth / TM->tmHeight >= 3)
5722 {
5723 /* Aspect Penalty 30 */
5724 /* The aspect rate is >= 3. It seems like a bad font. */
5725 GOT_PENALTY("Aspect", ((TM->tmAveCharWidth / TM->tmHeight) - 2) * 30);
5726 }
5727 else if (TM->tmHeight / TM->tmAveCharWidth >= 3)
5728 {
5729 /* Aspect Penalty 30 */
5730 /* The aspect rate is >= 3. It seems like a bad font. */
5731 GOT_PENALTY("Aspect", ((TM->tmHeight / TM->tmAveCharWidth) - 2) * 30);
5732 }
5733 }
5734
5735 if (Penalty < 200)
5736 {
5737 DPRINT("WARNING: Penalty:%ld < 200: RequestedNameW:%ls, "
5738 "ActualNameW:%ls, lfCharSet:%d, lfWeight:%ld, "
5739 "tmCharSet:%d, tmWeight:%ld\n",
5740 Penalty, LogFont->lfFaceName, ActualNameW,
5741 LogFont->lfCharSet, LogFont->lfWeight,
5742 TM->tmCharSet, TM->tmWeight);
5743 }
5744
5745 return Penalty; /* success */
5746}
5747
5748#undef GOT_PENALTY
5749
5750static __inline VOID
5751FindBestFontFromList(FONTOBJ **FontObj, ULONG *MatchPenalty,
5752 const LOGFONTW *LogFont,
5753 const PLIST_ENTRY Head)
5754{
5755 ULONG Penalty;
5757 PFONT_ENTRY CurrentEntry;
5758 FONTGDI *FontGDI;
5759 OUTLINETEXTMETRICW *Otm = NULL;
5760 UINT OtmSize, OldOtmSize = 0;
5761 FT_Face Face;
5762
5763 ASSERT(FontObj);
5764 ASSERT(MatchPenalty);
5765 ASSERT(LogFont);
5766 ASSERT(Head);
5767
5768 /* Start with a pretty big buffer */
5769 OldOtmSize = 0x200;
5770 Otm = ExAllocatePoolWithTag(PagedPool, OldOtmSize, GDITAG_TEXT);
5771
5772 /* get the FontObj of lowest penalty */
5773 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
5774 {
5775 CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
5776
5777 FontGDI = CurrentEntry->Font;
5778 ASSERT(FontGDI);
5779 Face = FontGDI->SharedFace->Face;
5780
5781 /* get text metrics */
5783 OtmSize = IntGetOutlineTextMetrics(FontGDI, 0, NULL, TRUE);
5784 if (OtmSize > OldOtmSize)
5785 {
5786 if (Otm)
5789 }
5790
5791 /* update FontObj if lowest penalty */
5792 if (Otm)
5793 {
5795 IntRequestFontSize(NULL, FontGDI, LogFont->lfWidth, LogFont->lfHeight);
5796
5798 OtmSize = IntGetOutlineTextMetrics(FontGDI, OtmSize, Otm, TRUE);
5799 if (!OtmSize)
5800 continue;
5801
5802 OldOtmSize = OtmSize;
5803
5804 Penalty = GetFontPenalty(LogFont, Otm, Face->style_name);
5805 if (*MatchPenalty == MAXULONG || Penalty < *MatchPenalty)
5806 {
5807 *FontObj = GDIToObj(FontGDI, FONT);
5808 *MatchPenalty = Penalty;
5809 }
5810 }
5811 }
5812
5813 if (Otm)
5815}
5816
5817static
5818VOID
5821{
5822 PS_FontInfoRec psfInfo;
5823 FT_ULong tmp_size = 0;
5824 FT_Face Face = Font->SharedFace->Face;
5825
5827
5828 if (FT_HAS_MULTIPLE_MASTERS(Face))
5829 Font->FontObj.flFontType |= FO_MULTIPLEMASTER;
5830 if (FT_HAS_VERTICAL(Face))
5831 Font->FontObj.flFontType |= FO_VERT_FACE;
5832 if (!FT_IS_SCALABLE(Face))
5833 Font->FontObj.flFontType |= FO_TYPE_RASTER;
5834 if (FT_IS_SFNT(Face))
5835 {
5836 Font->FontObj.flFontType |= FO_TYPE_TRUETYPE;
5838 Font->FontObj.flFontType |= FO_POSTSCRIPT;
5839 }
5840 if (!FT_Get_PS_Font_Info(Face, &psfInfo ))
5841 {
5842 Font->FontObj.flFontType |= FO_POSTSCRIPT;
5843 }
5844 /* Check for the presence of the 'CFF ' table to check if the font is Type1 */
5845 if (!FT_Load_Sfnt_Table(Face, TTAG_CFF, 0, NULL, &tmp_size))
5846 {
5847 Font->FontObj.flFontType |= (FO_CFF|FO_POSTSCRIPT);
5848 }
5849}
5850
5851static BOOL
5853{
5856
5858 Status = IntGetFontLocalizedName(&Name2, SharedFace, NameID, LangID);
5859
5860 if (NT_SUCCESS(Status))
5861 {
5862 if (RtlCompareUnicodeString(Name1, &Name2, TRUE) == 0)
5863 {
5865 return TRUE;
5866 }
5867
5869 }
5870
5871 return FALSE;
5872}
5873
5874static BOOL
5875MatchFontNames(PSHARED_FACE SharedFace, LPCWSTR lfFaceName)
5876{
5877 UNICODE_STRING Name1;
5878
5879 if (lfFaceName[0] == UNICODE_NULL)
5880 return FALSE;
5881
5882 RtlInitUnicodeString(&Name1, lfFaceName);
5883
5884 if (MatchFontName(SharedFace, &Name1, TT_NAME_ID_FONT_FAMILY, LANG_ENGLISH) ||
5885 MatchFontName(SharedFace, &Name1, TT_NAME_ID_FULL_NAME, LANG_ENGLISH))
5886 {
5887 return TRUE;
5888 }
5890 {
5891 if (MatchFontName(SharedFace, &Name1, TT_NAME_ID_FONT_FAMILY, gusLanguageID) ||
5892 MatchFontName(SharedFace, &Name1, TT_NAME_ID_FULL_NAME, gusLanguageID))
5893 {
5894 return TRUE;
5895 }
5896 }
5897 return FALSE;
5898}
5899
5900static void
5902 PTEXTOBJ TextObj,
5903 PFONTGDI FontGdi,
5904 FONTOBJ *pFontObj,
5905 const LOGFONTW *pLogFont,
5906 PLOGFONTW SubstitutedLogFont)
5907{
5909
5910 TextObj->Font = pFontObj;
5911 TextObj->TextFace[0] = UNICODE_NULL;
5912
5913 PSHARED_FACE SharedFace = FontGdi->SharedFace;
5914 if (MatchFontNames(SharedFace, SubstitutedLogFont->lfFaceName))
5915 {
5916 RtlStringCchCopyW(TextObj->TextFace, _countof(TextObj->TextFace), pLogFont->lfFaceName);
5917 }
5918 else
5919 {
5923 if (NT_SUCCESS(Status))
5924 {
5925 /* truncated copy */
5926 IntUnicodeStringToBuffer(TextObj->TextFace, sizeof(TextObj->TextFace), &Name);
5928 }
5929 }
5930
5931 // Need hdev, when freetype is loaded need to create DEVOBJ for
5932 // Consumer and Producer.
5933 TextObj->Font->iUniq = 1; // Now it can be cached.
5934 TextObj->fl |= TEXTOBJECT_INIT;
5935}
5936
5937static void
5938IntPopulateFontGdi(PFONTGDI FontGdi, const FONTOBJ *pFontObj, const LOGFONTW *pLogFont)
5939{
5941
5942 IntFontType(FontGdi);
5943 FontGdi->flType = pFontObj->flFontType;
5944 FontGdi->RequestUnderline = pLogFont->lfUnderline ? 0xFF : 0;
5945 FontGdi->RequestStrikeOut = pLogFont->lfStrikeOut ? 0xFF : 0;
5946 FontGdi->RequestItalic = pLogFont->lfItalic ? 0xFF : 0;
5947 if (pLogFont->lfWeight != FW_DONTCARE)
5948 FontGdi->RequestWeight = pLogFont->lfWeight;
5949 else
5950 FontGdi->RequestWeight = FW_NORMAL;
5951}
5952
5953static PFONT_LOOKUP_CACHE
5955{
5957
5958 PLIST_ENTRY Entry, pHead = &s_FontLookupCacheList;
5959 for (Entry = pHead->Flink; Entry != pHead; Entry = Entry->Flink)
5960 {
5962 if (RtlEqualMemory(&pEntry->LogFont, pLogFont, sizeof(*pLogFont)))
5963 {
5964 // Move to head
5965 RemoveEntryList(&pEntry->ListEntry);
5966 InsertHeadList(&s_FontLookupCacheList, &pEntry->ListEntry);
5967 return pEntry;
5968 }
5969 }
5970 return NULL;
5971}
5972
5973static void
5974FontLookUp_Add(const LOGFONTW *LogFont, PSHARED_FACE SharedFace, FONTOBJ *pFontObj)
5975{
5977
5978 if (s_FontLookupCacheCount >= MAX_FONT_LOOKUP_CACHE) // Too many cached entries?
5979 {
5980 // Remove tail one
5981 PLIST_ENTRY OldestEntry = RemoveTailList(&s_FontLookupCacheList);
5982 PFONT_LOOKUP_CACHE pOldCache = CONTAINING_RECORD(OldestEntry, FONT_LOOKUP_CACHE, ListEntry);
5983 FontLookUp_Destroy(pOldCache);
5985 }
5986
5987 // Add new cache entry
5989 if (pEntry)
5990 {
5991 // Populate
5992 RtlCopyMemory(&pEntry->LogFont, LogFont, sizeof(*LogFont));
5993 pEntry->SharedFace = SharedFace;
5994 SharedFace_AddRef(SharedFace);
5995 pEntry->pFontObj = pFontObj;
5996 // Add to head
5997 InsertHeadList(&s_FontLookupCacheList, &pEntry->ListEntry);
5999 }
6000}
6001
6004{
6006
6007 LOGFONTW LogFont = *pLogFont;
6008 RtlZeroMemory(&LogFont.lfFaceName, sizeof(LogFont.lfFaceName));
6009 RtlStringCchCopyW(LogFont.lfFaceName, _countof(LogFont.lfFaceName), pLogFont->lfFaceName);
6010 pLogFont = &LogFont;
6011
6012 /* Substitute */
6013 LOGFONTW SubstitutedLogFont = *pLogFont;
6014 SubstituteFontRecurse(&SubstitutedLogFont);
6015 DPRINT("Font '%S,%u' is substituted by '%S,%u'.\n",
6016 pLogFont->lfFaceName, pLogFont->lfCharSet,
6017 SubstitutedLogFont.lfFaceName, SubstitutedLogFont.lfCharSet);
6018
6019 FONTOBJ *pFontObj;
6020 PFONT_LOOKUP_CACHE pLookUp = FontLookUp_LookUp(pLogFont);
6021 if (pLookUp)
6022 {
6023 pFontObj = pLookUp->pFontObj;
6024 }
6025 else
6026 {
6027 ULONG MatchPenalty = 0xFFFFFFFF;
6029
6030 /* Search private fonts */
6031 IntLockProcessPrivateFonts(Win32Process);
6032 FindBestFontFromList(&pFontObj, &MatchPenalty, &SubstitutedLogFont,
6033 &Win32Process->PrivateFontListHead);
6034 IntUnLockProcessPrivateFonts(Win32Process);
6035
6036 /* Search system fonts */
6037 FindBestFontFromList(&pFontObj, &MatchPenalty, &SubstitutedLogFont, &g_FontListHead);
6038 }
6039
6040 if (!pFontObj)
6041 {
6042 DPRINT1("Request font %S not found, no fonts loaded at all\n", pLogFont->lfFaceName);
6043 return NULL;
6044 }
6045
6046 PFONTGDI pFontGDI = ObjToGDI(pFontObj, FONT);
6047
6048 if (TextObj)
6049 IntPopulateTextObj(TextObj, pFontGDI, pFontObj, pLogFont, &SubstitutedLogFont);
6050
6051 IntPopulateFontGdi(pFontGDI, pFontObj, pLogFont);
6052
6053 if (!pLookUp)
6054 FontLookUp_Add(pLogFont, pFontGDI->SharedFace, pFontObj);
6055
6056 return pFontGDI->SharedFace;
6057}
6058
6061TextIntRealizeFont(HFONT FontHandle, PTEXTOBJ pTextObj)
6062{
6063 PTEXTOBJ TextObj;
6064 PSHARED_FACE SharedFace;
6065
6066 if (!pTextObj)
6067 {
6068 TextObj = TEXTOBJ_LockText(FontHandle);
6069 if (NULL == TextObj)
6070 {
6071 return STATUS_INVALID_HANDLE;
6072 }
6073
6074 if (TextObj->fl & TEXTOBJECT_INIT)
6075 {
6076 TEXTOBJ_UnlockText(TextObj);
6077 return STATUS_SUCCESS;
6078 }
6079 }
6080 else
6081 {
6082 TextObj = pTextObj;
6083 }
6084
6086 SharedFace = IntRealizeFont(&TextObj->logfont.elfEnumLogfontEx.elfLogFont, TextObj);
6088
6089 if (!pTextObj)
6090 TEXTOBJ_UnlockText(TextObj);
6091
6092 ASSERT((!!SharedFace ^ (NULL == TextObj->Font)) != 0);
6093
6094 return SharedFace ? STATUS_SUCCESS : STATUS_NOT_FOUND;
6095}
6096
6097static
6098BOOL
6101 POBJECT_NAME_INFORMATION NameInfo,
6102 ULONG Size,
6104{
6107 HANDLE hFile;
6109 ULONG Desired;
6110
6112 FileName,
6114 NULL,
6115 NULL);
6116
6118 &hFile,
6119 0, // FILE_READ_ATTRIBUTES,
6123 0);
6124
6125 if (!NT_SUCCESS(Status))
6126 {
6127 DPRINT("ZwOpenFile() failed (Status = 0x%lx)\n", Status);
6128 return FALSE;
6129 }
6130
6131 Status = ZwQueryObject(hFile, ObjectNameInformation, NameInfo, Size, &Desired);
6132 ZwClose(hFile);
6133 if (!NT_SUCCESS(Status))
6134 {
6135 DPRINT("ZwQueryObject() failed (Status = %lx)\n", Status);
6136 return FALSE;
6137 }
6138
6139 return TRUE;
6140}
6141
6142static BOOL
6143EqualFamilyInfo(const FONTFAMILYINFO *pInfo1, const FONTFAMILYINFO *pInfo2)
6144{
6145 const ENUMLOGFONTEXW *pLog1 = &pInfo1->EnumLogFontEx;
6146 const ENUMLOGFONTEXW *pLog2 = &pInfo2->EnumLogFontEx;
6147 const LOGFONTW *plf1 = &pLog1->elfLogFont;
6148 const LOGFONTW *plf2 = &pLog2->elfLogFont;
6149
6150 if (_wcsicmp(plf1->lfFaceName, plf2->lfFaceName) != 0)
6151 {
6152 return FALSE;
6153 }
6154
6155 if (_wcsicmp(pLog1->elfStyle, pLog2->elfStyle) != 0)
6156 {
6157 return FALSE;
6158 }
6159
6160 return TRUE;
6161}
6162
6163static VOID
6165{
6167 if (FamInfo->EnumLogFontEx.elfStyle[0] &&
6168 _wcsicmp(FamInfo->EnumLogFontEx.elfStyle, L"Regular") != 0)
6169 {
6170 wcscat(psz, L" ");
6171 wcscat(psz, FamInfo->EnumLogFontEx.elfStyle);
6172 }
6173}
6174
6175BOOL
6179 PVOID pBuffer,
6180 DWORD *pdwBytes,
6181 DWORD dwType)
6182{
6183 UNICODE_STRING EntryFileName;
6184 POBJECT_NAME_INFORMATION NameInfo1 = NULL, NameInfo2 = NULL;
6185 PLIST_ENTRY ListEntry;
6186 PFONT_ENTRY FontEntry;
6187 ULONG Size, i, Count;
6188 LPBYTE pbBuffer;
6189 BOOL IsEqual;
6190 FONTFAMILYINFO *FamInfo;
6191 const ULONG MaxFamInfo = 64;
6192 const ULONG MAX_FAM_INFO_BYTES = sizeof(FONTFAMILYINFO) * MaxFamInfo;
6193 BOOL bSuccess;
6194 const ULONG NAMEINFO_SIZE = sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR);
6195
6196 DPRINT("IntGdiGetFontResourceInfo: dwType == %lu\n", dwType);
6197
6198 do
6199 {
6200 /* Create buffer for full path name */
6201 NameInfo1 = ExAllocatePoolWithTag(PagedPool, NAMEINFO_SIZE, TAG_FINF);
6202 if (!NameInfo1)
6203 break;
6204
6205 /* Get the full path name */
6206 if (!IntGetFullFileName(NameInfo1, NAMEINFO_SIZE, FileName))
6207 break;
6208
6209 /* Create a buffer for the entries' names */
6210 NameInfo2 = ExAllocatePoolWithTag(PagedPool, NAMEINFO_SIZE, TAG_FINF);
6211 if (!NameInfo2)
6212 break;
6213
6214 FamInfo = ExAllocatePoolWithTag(PagedPool, MAX_FAM_INFO_BYTES, TAG_FINF);
6215 } while (0);
6216
6217 if (!NameInfo1 || !NameInfo2 || !FamInfo)
6218 {
6219 if (NameInfo2)
6220 ExFreePoolWithTag(NameInfo2, TAG_FINF);
6221
6222 if (NameInfo1)
6223 ExFreePoolWithTag(NameInfo1, TAG_FINF);
6224
6226 return FALSE;
6227 }
6228
6229 Count = 0;
6230
6231 /* Try to find the pathname in the global font list */
6233 for (ListEntry = g_FontListHead.Flink; ListEntry != &g_FontListHead;
6234 ListEntry = ListEntry->Flink)
6235 {
6236 FontEntry = CONTAINING_RECORD(ListEntry, FONT_ENTRY, ListEntry);
6237 if (FontEntry->Font->Filename == NULL)
6238 continue;
6239
6240 RtlInitUnicodeString(&EntryFileName , FontEntry->Font->Filename);
6241 if (!IntGetFullFileName(NameInfo2, NAMEINFO_SIZE, &EntryFileName))
6242 continue;
6243
6244 if (!RtlEqualUnicodeString(&NameInfo1->Name, &NameInfo2->Name, FALSE))
6245 continue;
6246
6247 IsEqual = FALSE;
6248 FontFamilyFillInfo(&FamInfo[Count], FontEntry->FaceName.Buffer,
6249 NULL, FontEntry->Font);
6250 for (i = 0; i < Count; ++i)
6251 {
6252 if (EqualFamilyInfo(&FamInfo[i], &FamInfo[Count]))
6253 {
6254 IsEqual = TRUE;
6255 break;
6256 }
6257 }
6258 if (!IsEqual)
6259 {
6260 /* Found */
6261 ++Count;
6262 if (Count >= MaxFamInfo)
6263 break;
6264 }
6265 }
6267
6268 /* Free the buffers */
6269 ExFreePoolWithTag(NameInfo1, TAG_FINF);
6270 ExFreePoolWithTag(NameInfo2, TAG_FINF);
6271
6272 if (Count == 0 && dwType != 5)
6273 {
6274 /* Font could not be found in system table
6275 dwType == 5 will still handle this */
6276 ExFreePoolWithTag(FamInfo, TAG_FINF);
6277 return FALSE;
6278 }
6279
6280 bSuccess = FALSE;
6281 switch (dwType)
6282 {
6283 case 0: /* FIXME: Returns 1 or 2, don't know what this is atm */
6284 Size = sizeof(DWORD);
6285 if (*pdwBytes == 0)
6286 {
6287 *pdwBytes = Size;
6288 bSuccess = TRUE;
6289 }
6290 else if (pBuffer)
6291 {
6292 if (*pdwBytes >= Size)
6293 {
6294 *(DWORD*)pBuffer = Count;
6295 }
6296 *pdwBytes = Size;
6297 bSuccess = TRUE;
6298 }
6299 break;
6300
6301 case 1: /* copy the font title */
6302 /* calculate the required size */
6303 Size = 0;
6304 for (i = 0; i < Count; ++i)
6305 {
6306 if (i > 0)
6307 Size += 3; /* " & " */
6308 Size += wcslen(FamInfo[i].EnumLogFontEx.elfLogFont.lfFaceName);
6309 if (FamInfo[i].EnumLogFontEx.elfStyle[0] &&
6310 _wcsicmp(FamInfo[i].EnumLogFontEx.elfStyle, L"Regular") != 0)
6311 {
6312 Size += 1 + wcslen(FamInfo[i].EnumLogFontEx.elfStyle);
6313 }
6314 }
6315 Size += 2; /* "\0\0" */
6316 Size *= sizeof(WCHAR);
6317
6318 if (*pdwBytes == 0)
6319 {
6320 *pdwBytes = Size;
6321 bSuccess = TRUE;
6322 }
6323 else if (pBuffer)
6324 {
6325 if (*pdwBytes >= Size)
6326 {
6327 /* store font title to buffer */
6328 WCHAR *psz = pBuffer;
6329 *psz = 0;
6330 for (i = 0; i < Count; ++i)
6331 {
6332 if (i > 0)
6333 wcscat(psz, L" & ");
6334 IntAddNameFromFamInfo(psz, &FamInfo[i]);
6335 }
6336 psz[wcslen(psz) + 1] = UNICODE_NULL;
6337 *pdwBytes = Size;
6338 bSuccess = TRUE;
6339 }
6340 else
6341 {
6342 *pdwBytes = 1024; /* this is confirmed value */
6343 }
6344 }
6345 break;
6346
6347 case 2: /* Copy an array of LOGFONTW */
6348 Size = Count * sizeof(LOGFONTW);
6349 if (*pdwBytes == 0)
6350 {
6351 *pdwBytes = Size;
6352 bSuccess = TRUE;
6353 }
6354 else if (pBuffer)
6355 {
6356 if (*pdwBytes >= Size)
6357 {
6358 pbBuffer = (LPBYTE)pBuffer;
6359 for (i = 0; i < Count; ++i)
6360 {
6361 FamInfo[i].EnumLogFontEx.elfLogFont.lfWidth = 0;
6362 RtlCopyMemory(pbBuffer, &FamInfo[i].EnumLogFontEx.elfLogFont, sizeof(LOGFONTW));
6363 pbBuffer += sizeof(LOGFONTW);
6364 }
6365 }
6366 *pdwBytes = Size;
6367 bSuccess = TRUE;
6368 }
6369 else
6370 {
6371 *pdwBytes = 1024; /* this is confirmed value */
6372 }
6373 break;
6374
6375 case 3:
6376 Size = sizeof(DWORD);
6377 if (*pdwBytes == 0)
6378 {
6379 *pdwBytes = Size;
6380 bSuccess = TRUE;
6381 }
6382 else if (pBuffer)
6383 {
6384 if (*pdwBytes >= Size)
6385 {
6386 /* FIXME: What exactly is copied here? */
6387 *(DWORD*)pBuffer = 1;
6388 }
6389 *pdwBytes = Size;
6390 bSuccess = TRUE;
6391 }
6392 break;
6393
6394 case 4: /* full file path */
6395 if (FileName->Length >= 4 * sizeof(WCHAR))
6396 {
6397 /* The beginning of FileName is \??\ */
6398 LPWSTR pch = FileName->Buffer + 4;
6399 DWORD Length = FileName->Length - 4 * sizeof(WCHAR);
6400
6401 Size = Length + sizeof(WCHAR);
6402 if (*pdwBytes == 0)
6403 {
6404 *pdwBytes = Size;
6405 bSuccess = TRUE;
6406 }
6407 else if (pBuffer)
6408 {
6409 if (*pdwBytes >= Size)
6410 {
6412 }
6413 *pdwBytes = Size;
6414 bSuccess = TRUE;
6415 }
6416 }
6417 break;
6418
6419 case 5: /* Looks like a BOOL that is copied, TRUE, if the font was not found */
6420 Size = sizeof(BOOL);
6421 if (*pdwBytes == 0)
6422 {
6423 *pdwBytes = Size;
6424 bSuccess = TRUE;
6425 }
6426 else if (pBuffer)
6427 {
6428 if (*pdwBytes >= Size)
6429 {
6430 *(BOOL*)pBuffer = Count == 0;
6431 }
6432 *pdwBytes = Size;
6433 bSuccess = TRUE;
6434 }
6435 break;
6436 }
6437 ExFreePoolWithTag(FamInfo, TAG_FINF);
6438
6439 return bSuccess;
6440}
6441
6442
6443BOOL
6446{
6447 if (FT_HAS_FIXED_SIZES(Font->SharedFace->Face))
6448 Info->iTechnology = RI_TECH_BITMAP;
6449 else
6450 {
6451 if (FT_IS_SCALABLE(Font->SharedFace->Face))
6452 Info->iTechnology = RI_TECH_SCALABLE;
6453 else
6454 Info->iTechnology = RI_TECH_FIXED;
6455 }
6456 Info->iUniq = Font->FontObj.iUniq;
6457 Info->dwUnknown = -1;
6458 return TRUE;
6459}
6460
6461
6462DWORD
6465 DWORD cPairs,
6466 LPKERNINGPAIR pKerningPair)
6467{
6468 DWORD Count = 0;
6469 INT i = 0;
6470 FT_Face face = Font->SharedFace->Face;
6471
6472 if (FT_HAS_KERNING(face) && face->charmap->encoding == FT_ENCODING_UNICODE)
6473 {
6474 FT_UInt previous_index = 0, glyph_index = 0;
6475 FT_ULong char_code, char_previous;
6476 FT_Vector delta;
6477
6478 char_previous = char_code = FT_Get_First_Char(face, &glyph_index);
6479
6481
6482 while (glyph_index)
6483 {
6484 if (previous_index && glyph_index)
6485 {
6486 FT_Get_Kerning(face, previous_index, glyph_index, FT_KERNING_DEFAULT, &delta);
6487
6488 if (pKerningPair && cPairs)
6489 {
6490 pKerningPair[i].wFirst = char_previous;
6491 pKerningPair[i].wSecond = char_code;
6492 pKerningPair[i].iKernAmount = delta.x;
6493 i++;
6494 if (i == cPairs) break;
6495 }
6496 Count++;
6497 }
6498 previous_index = glyph_index;
6499 char_previous = char_code;
6500 char_code = FT_Get_Next_Char(face, char_code, &glyph_index);
6501 }
6503 }
6504 return Count;
6505}
6506
6507
6509//
6510// Functions needing sorting.
6511//
6513
6516 const LOGFONTW *SafeLogFont,
6517 PFONTFAMILYINFO SafeInfo,
6518 LONG InfoCount)
6519{
6520 LONG AvailCount = 0;
6521 PPROCESSINFO Win32Process;
6522
6523 /* Enumerate font families in the global list */
6525 if (!GetFontFamilyInfoForList(SafeLogFont, SafeInfo, NULL, &AvailCount,
6526 InfoCount, &g_FontListHead))
6527 {
6529 return -1;
6530 }
6531
6532 /* Enumerate font families in the process local list */
6533 Win32Process = PsGetCurrentProcessWin32Process();
6534 IntLockProcessPrivateFonts(Win32Process);
6535 if (!GetFontFamilyInfoForList(SafeLogFont, SafeInfo, NULL, &AvailCount, InfoCount,
6536 &Win32Process->PrivateFontListHead))
6537 {
6538 IntUnLockProcessPrivateFonts(Win32Process);
6540 return -1;
6541 }
6542 IntUnLockProcessPrivateFonts(Win32Process);
6544
6545 /* Enumerate font families in the registry */
6546 if (!GetFontFamilyInfoForSubstitutes(SafeLogFont, SafeInfo, &AvailCount, InfoCount))
6547 {
6548 return -1;
6549 }
6550
6551 return AvailCount;
6552}
6553
6554LONG NTAPI
6556 _In_ HDC Dc,
6557 _In_ const LOGFONTW *UnsafeLogFont,
6558 _Out_ PFONTFAMILYINFO UnsafeInfo,
6559 _Inout_ PLONG UnsafeInfoCount)
6560{
6562 LOGFONTW LogFont;
6564 LONG GotCount, AvailCount, SafeInfoCount;
6566
6567 if (UnsafeLogFont == NULL || UnsafeInfo == NULL || UnsafeInfoCount == NULL)
6568 {
6570 return -1;
6571 }
6572
6573 Status = MmCopyFromCaller(&SafeInfoCount, UnsafeInfoCount, sizeof(SafeInfoCount));
6574 if (!NT_SUCCESS(Status))
6575 {
6577 return -1;
6578 }
6579 GotCount = 0;
6580 Status = MmCopyToCaller(UnsafeInfoCount, &GotCount, sizeof(*UnsafeInfoCount));
6581 if (!NT_SUCCESS(Status))
6582 {
6584 return -1;
6585 }
6586 Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW));
6587 if (!NT_SUCCESS(Status))
6588 {
6590 return -1;
6591 }
6592 if (SafeInfoCount <= 0)
6593 {
6595 return -1;
6596 }
6597
6598 /* Allocate space for a safe copy */
6599 Status = RtlULongMult(SafeInfoCount, sizeof(FONTFAMILYINFO), &DataSize);
6601 {
6602 DPRINT1("Overflowed.\n");
6604 return -1;
6605 }
6607 if (Info == NULL)
6608 {
6610 return -1;
6611 }
6612
6613 /* Retrieve the information */
6614 AvailCount = IntGetFontFamilyInfo(Dc, &LogFont, Info, SafeInfoCount);
6615 GotCount = min(AvailCount, SafeInfoCount);
6616 SafeInfoCount = AvailCount;
6617
6618 /* Return data to caller */
6619 if (GotCount > 0)
6620 {
6621 Status = RtlULongMult(GotCount, sizeof(FONTFAMILYINFO), &DataSize);
6623 {
6624 DPRINT1("Overflowed.\n");
6627 return -1;
6628 }
6629 Status = MmCopyToCaller(UnsafeInfo, Info, DataSize);
6630 if (!NT_SUCCESS(Status))
6631 {
6634 return -1;
6635 }
6636 Status = MmCopyToCaller(UnsafeInfoCount, &SafeInfoCount, sizeof(*UnsafeInfoCount));
6637 if (!NT_SUCCESS(Status))
6638 {
6641 return -1;
6642 }
6643 }
6644
6646
6647 return GotCount;
6648}
6649
6650
6651/*
6652 * Calculate X and Y disposition of the text.
6653 * NOTE: The disposition can be negative.
6654 */
6655static BOOL
6657 _Out_ LONGLONG *pX64,
6658 _Out_ LONGLONG *pY64,
6660 _In_ INT Count,
6661 _In_opt_ const INT *Dx,
6663 _In_ UINT fuOptions,
6664 _In_ BOOL bNoTransform,
6665 _Inout_ PFONTLINK_CHAIN pChain)
6666{
6667 LONGLONG X64 = 0, Y64 = 0;
6668 INT i, glyph_index;
6669 FT_BitmapGlyph realglyph;
6670 FT_Face face = Cache->Hashed.Face;
6671 BOOL use_kerning = FT_HAS_KERNING(face);
6672 ULONG previous = 0;
6673 FT_Vector delta, vec;
6674 DWORD ch0, ch1;
6675
6677
6678 for (i = 0; i < Count; ++i)
6679 {
6680 ch0 = *String++;
6681 if (IS_HIGH_SURROGATE(ch0))
6682 {
6683 ++i;
6684 if (i >= Count)
6685 return TRUE;
6686
6687 ch1 = *String++;
6688 if (IS_LOW_SURROGATE(ch1))
6689 ch0 = Utf32FromSurrogatePair(ch0, ch1);
6690 }
6691
6692 glyph_index = FontLink_Chain_FindGlyph(pChain, Cache, &face, ch0,
6693 (fuOptions & ETO_GLYPH_INDEX));
6694 Cache->Hashed.GlyphIndex = glyph_index;
6695
6696 realglyph = IntGetRealGlyph(Cache);
6697 if (!realglyph)
6698 return FALSE;
6699
6700 /* Retrieve kerning distance */
6701 if (use_kerning && previous && glyph_index)
6702 {
6703 FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
6704 X64 += delta.x;
6705 Y64 -= delta.y;
6706 }
6707
6708 if (NULL == Dx)
6709 {
6710 X64 += realglyph->root.advance.x >> 10;
6711 Y64 -= realglyph->root.advance.y >> 10;
6712 }
6713 else if (fuOptions & ETO_PDY)
6714 {
6715 vec.x = (Dx[2 * i + 0] << 6);
6716 vec.y = (Dx[2 * i + 1] << 6);
6717 if (!bNoTransform)
6718 FT_Vector_Transform(&vec, &Cache->Hashed.matTransform);
6719 X64 += vec.x;
6720 Y64 -= vec.y;
6721 }
6722 else
6723 {
6724 vec.x = (Dx[i] << 6);
6725 vec.y = 0;
6726 if (!bNoTransform)
6727 FT_Vector_Transform(&vec, &Cache->Hashed.matTransform);
6728 X64 += vec.x;
6729 Y64 -= vec.y;
6730 }
6731
6732 previous = glyph_index;
6733 }
6734
6735 *pX64 = X64;
6736 *pY64 = Y64;
6737 return TRUE;
6738}
6739
6740BOOL
6743 _In_ PDC dc,
6744 _In_ INT XStart,
6745 _In_ INT YStart,
6746 _In_ UINT fuOptions,
6749 _In_ INT Count,
6750 _In_opt_ const INT *Dx,
6751 _In_ DWORD dwCodePage)
6752{
6753 /*
6754 * FIXME:
6755 * Call EngTextOut, which does the real work (calling DrvTextOut where
6756 * appropriate)
6757 */
6758
6759 PDC_ATTR pdcattr;
6760 SURFOBJ *psoDest, *psoGlyph;
6761 SURFACE *psurf;
6762 INT glyph_index, i;
6763 FT_Face face;
6764 FT_BitmapGlyph realglyph;
6765 LONGLONG X64, Y64, RealXStart64, RealYStart64, DeltaX64, DeltaY64;
6766 ULONG previous;
6767 RECTL DestRect, MaskRect;
6768 HBITMAP hbmGlyph;
6769 SIZEL glyphSize;
6770 FONTOBJ *FontObj;
6771 PFONTGDI FontGDI;
6772 PTEXTOBJ TextObj = NULL;
6773 EXLATEOBJ exloRGB2Dst, exloDst2RGB;
6774 POINT Start;
6775 PMATRIX pmxWorldToDevice;
6776 FT_Vector delta, vecAscent64, vecDescent64, vec;
6777 LOGFONTW *plf;
6778 BOOL use_kerning, bResult, DoBreak;
6780 FT_Matrix mat;
6781 BOOL bNoTransform;
6782 DWORD ch0, ch1;
6783 const DWORD del = 0x7f, nbsp = 0xa0; // DEL is ASCII DELETE and nbsp is a non-breaking space
6784 FONTLINK_CHAIN Chain;
6785 SIZE spaceWidth;
6786
6787 /* Check if String is valid */
6788 if (Count > 0xFFFF || (Count > 0 && String == NULL))
6789 {
6791 return FALSE;
6792 }
6793
6794 if (PATH_IsPathOpen(dc->dclevel))
6795 {
6796 return PATH_ExtTextOut(dc,
6797 XStart, YStart,
6798 fuOptions,
6799 lprc,
6800 String, Count,
6801 Dx);
6802 }
6803
6805
6806 if (!dc->dclevel.pSurface)
6807 {
6808 /* Memory DC with no surface selected */
6809 bResult = TRUE;
6810 goto Cleanup;
6811 }
6812
6813 pdcattr = dc->pdcattr;
6814 if (pdcattr->flTextAlign & TA_UPDATECP)
6815 {
6816 Start.x = pdcattr->ptlCurrent.x;
6817 Start.y = pdcattr->ptlCurrent.y;
6818 }
6819 else
6820 {
6821 Start.x = XStart;
6822 Start.y = YStart;
6823 }
6824
6825 IntLPtoDP(dc, &Start, 1);
6826 RealXStart64 = ((LONGLONG)Start.x + dc->ptlDCOrig.x) << 6;
6827 RealYStart64 = ((LONGLONG)Start.y + dc->ptlDCOrig.y) << 6;
6828
6829 MaskRect.left = 0;
6830 MaskRect.top = 0;
6831
6832 psurf = dc->dclevel.pSurface;
6833 psoDest = &psurf->SurfObj;
6834
6835 if (pdcattr->iGraphicsMode == GM_ADVANCED)
6836 pmxWorldToDevice = DC_pmxWorldToDevice(dc);
6837 else
6838 pmxWorldToDevice = (PMATRIX)&gmxWorldToDeviceDefault;
6839
6840 if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
6842
6843 if (lprc && (fuOptions & (ETO_CLIPPED | ETO_OPAQUE)))
6844 {
6845 IntLPtoDP(dc, (POINT*)lprc, 2);
6846 lprc->left += dc->ptlDCOrig.x;
6847 lprc->top += dc->ptlDCOrig.y;
6848 lprc->right += dc->ptlDCOrig.x;
6849 lprc->bottom += dc->ptlDCOrig.y;
6850 }
6851
6852 if (lprc && (fuOptions & ETO_OPAQUE))
6853 {
6855 lprc->left, lprc->top,
6856 lprc->right - lprc->left, lprc->bottom - lprc->top,
6857 &dc->eboBackground.BrushObject);
6858 fuOptions &= ~ETO_OPAQUE;
6859 }
6860 else
6861 {
6862 if (pdcattr->jBkMode == OPAQUE)
6863 {
6864 fuOptions |= ETO_OPAQUE;
6865 }
6866 }
6867
6868 TextObj = RealizeFontInit(pdcattr->hlfntNew);
6869 if (TextObj == NULL)
6870 {
6871 bResult = FALSE;
6872 goto Cleanup;
6873 }
6874
6875 FontObj = TextObj->Font;
6876 ASSERT(FontObj);
6877 FontGDI = ObjToGDI(FontObj, FONT);
6878 ASSERT(FontGDI);
6879
6881 Cache.Hashed.Face = face = FontGDI->SharedFace->Face;
6882
6883 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
6884 Cache.Hashed.lfHeight = plf->lfHeight;
6885 Cache.Hashed.lfWidth = plf->lfWidth;
6886 Cache.Hashed.Aspect.Emu.Bold = EMUBOLD_NEEDED(FontGDI->OriginalWeight, plf->lfWeight);
6887 Cache.Hashed.Aspect.Emu.Italic = (plf->lfItalic && !FontGDI->OriginalItalic);
6888
6890 Cache.Hashed.Aspect.RenderMode = (BYTE)IntGetFontRenderMode(plf);
6891 else
6892 Cache.Hashed.Aspect.RenderMode = (BYTE)FT_RENDER_MODE_MONO;
6893
6894 if (!TextIntUpdateSize(dc, TextObj, FontGDI, FALSE))
6895 {
6897 bResult = FALSE;
6898 goto Cleanup;
6899 }
6900
6901 FontLink_Chain_Init(&Chain, TextObj, face);
6902
6903 /* Apply lfEscapement */
6904 if (FT_IS_SCALABLE(face) && plf->lfEscapement != 0)
6905 IntEscapeMatrix(&Cache.Hashed.matTransform, plf->lfEscapement);
6906 else
6907 Cache.Hashed.matTransform = identityMat;
6908
6909 /* Apply the world transformation */
6910 IntMatrixFromMx(&mat, pmxWorldToDevice);
6911 FT_Matrix_Multiply(&mat, &Cache.Hashed.matTransform);
6912 FT_Set_Transform(face, &Cache.Hashed.matTransform, NULL);
6913
6914 /* Is there no transformation? */
6915 bNoTransform = ((mat.xy == 0) && (mat.yx == 0) &&
6916 (mat.xx == (1 << 16)) && (mat.yy == (1 << 16)));
6917
6918 /* Calculate the ascent point and the descent point */
6919 vecAscent64.x = 0;
6920 vecAscent64.y = (FontGDI->tmAscent << 6);
6921 FT_Vector_Transform(&vecAscent64, &Cache.Hashed.matTransform);
6922 vecDescent64.x = 0;
6923 vecDescent64.y = -(FontGDI->tmDescent << 6);
6924 FT_Vector_Transform(&vecDescent64, &Cache.Hashed.matTransform);
6925
6926 /* Process the vertical alignment and fix the real starting point. */
6927#define VALIGN_MASK (TA_TOP | TA_BASELINE | TA_BOTTOM)
6928 if ((pdcattr->flTextAlign & VALIGN_MASK) == TA_BASELINE)
6929 {
6930 NOTHING;
6931 }
6932 else if ((pdcattr->flTextAlign & VALIGN_MASK) == TA_BOTTOM)
6933 {
6934 RealXStart64 -= vecDescent64.x;
6935 RealYStart64 += vecDescent64.y;
6936 }
6937 else /* TA_TOP */
6938 {
6939 RealXStart64 -= vecAscent64.x;
6940 RealYStart64 += vecAscent64.y;
6941 }
6942#undef VALIGN_MASK
6943
6944 use_kerning = FT_HAS_KERNING(face);
6945
6946 /* Calculate the text width if necessary */
6947 if ((fuOptions & ETO_OPAQUE) || (pdcattr->flTextAlign & (TA_CENTER | TA_RIGHT)))
6948 {
6949 if (!IntGetTextDisposition(&DeltaX64, &DeltaY64, String, Count, Dx, &Cache,
6950 fuOptions, bNoTransform, &Chain))
6951 {
6952 FontLink_Chain_Finish(&Chain);
6954 bResult = FALSE;
6955 goto Cleanup;
6956 }
6957
6958 /* Adjust the horizontal position by horizontal alignment */
6959 if ((pdcattr->flTextAlign & TA_CENTER) == TA_CENTER)
6960 {
6961 RealXStart64 -= DeltaX64 / 2;
6962 RealYStart64 -= DeltaY64 / 2;
6963 }
6964 else if ((pdcattr->flTextAlign & TA_RIGHT) == TA_RIGHT)
6965 {
6966 RealXStart64 -= DeltaX64;
6967 RealYStart64 -= DeltaY64;
6968 }
6969
6970 /* Fill background */
6971 if (fuOptions & ETO_OPAQUE)
6972 {
6973 INT X0 = (RealXStart64 + vecAscent64.x + 32) >> 6;
6974 INT Y0 = (RealYStart64 - vecAscent64.y + 32) >> 6;
6975 INT DX = (DeltaX64 >> 6);
6976 if (Cache.Hashed.matTransform.xy == 0 && Cache.Hashed.matTransform.yx == 0)
6977 {
6978 INT CY = (vecAscent64.y - vecDescent64.y + 32) >> 6;
6979 IntEngFillBox(dc, X0, Y0, DX, CY, &dc->eboBackground.BrushObject);
6980 }
6981 else
6982 {
6983 INT DY = (DeltaY64 >> 6);
6984 INT X1 = ((RealXStart64 + vecDescent64.x + 32) >> 6);
6985 INT Y1 = ((RealYStart64 - vecDescent64.y + 32) >> 6);
6986 POINT Points[4] =
6987 {
6988 { X0, Y0 },
6989 { X0 + DX, Y0 + DY },
6990 { X1 + DX, Y1 + DY },
6991 { X1, Y1 },
6992 };
6993 IntEngFillPolygon(dc, Points, 4, &dc->eboBackground.BrushObject);
6994 }
6995 }
6996 }
6997
6998 EXLATEOBJ_vInitialize(&exloRGB2Dst, &gpalRGB, psurf->ppal, 0, 0, 0);
6999 EXLATEOBJ_vInitialize(&exloDst2RGB, psurf->ppal, &gpalRGB, 0, 0, 0);
7000
7001 if (pdcattr->ulDirty_ & DIRTY_TEXT)
7003
7004 /*
7005 * The main rendering loop.
7006 */
7007 X64 = RealXStart64;
7008 Y64 = RealYStart64;
7009 previous = 0;
7010 DoBreak = FALSE;
7011 bResult = TRUE; /* Assume success */
7012 for (i = 0; i < Count; ++i)
7013 {
7014 ch0 = *String++;
7015 if (IS_HIGH_SURROGATE(ch0))
7016 {
7017 ++i;
7018 if (i >= Count)
7019 break;
7020
7021 ch1 = *String++;
7022 if (IS_LOW_SURROGATE(ch1))
7023 ch0 = Utf32FromSurrogatePair(ch0, ch1);
7024 }
7025
7026 glyph_index = FontLink_Chain_FindGlyph(&Chain, &Cache, &face, ch0,
7027 (fuOptions & ETO_GLYPH_INDEX));
7028 Cache.Hashed.GlyphIndex = glyph_index;
7029
7030 realglyph = IntGetRealGlyph(&Cache);
7031 if (!realglyph)
7032 {
7033 bResult = FALSE;
7034 break;
7035 }
7036
7037 /* retrieve kerning distance and move pen position */
7038 if (use_kerning && previous && glyph_index && NULL == Dx)
7039 {
7040 FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
7041 X64 += delta.x;
7042 Y64 -= delta.y;
7043 }
7044
7045 DPRINT("X64, Y64: %I64d, %I64d\n", X64, Y64);
7046 DPRINT("Advance: %d, %d\n", realglyph->root.advance.x, realglyph->root.advance.y);
7047
7048 glyphSize.cx = realglyph->bitmap.width;
7049 glyphSize.cy = realglyph->bitmap.rows;
7050
7051 /* Do chars > space & not DEL & not nbsp have a glyphSize.cx of zero? */
7052 if (ch0 > L' ' && ch0 != del && ch0 != nbsp && glyphSize.cx == 0)
7053 {
7054 DPRINT1("WARNING: family_name '%s' WChar 0x%04x has a glyphSize.cx of zero\n",
7055 face->family_name, ch0);
7056 }
7057
7058 /* Don't ignore spaces or non-breaking spaces when computing offset.
7059 * This completes the fix of CORE-11787. */
7060 if ((pdcattr->flTextAlign & TA_UPDATECP) && glyphSize.cx == 0 &&
7061 (ch0 == L' ' || ch0 == nbsp)) // Space chars needing x-dim widths
7062 {
7064 /* Get the width of the space character */
7065 TextIntGetTextExtentPoint(dc, TextObj, L" ", 1, 0, NULL, NULL, &spaceWidth, 0);
7067 glyphSize.cx = spaceWidth.cx;
7068 realglyph->left = 0;
7069 }
7070
7071 MaskRect.right = realglyph->bitmap.width;
7072 MaskRect.bottom = realglyph->bitmap.rows;
7073
7074 DestRect.left = ((X64 + 32) >> 6) + realglyph->left;
7075 DestRect.right = DestRect.left + glyphSize.cx;
7076 DestRect.top = ((Y64 + 32) >> 6) - realglyph->top;
7077 DestRect.bottom = DestRect.top + glyphSize.cy;
7078
7079 /* Check if the bitmap has any pixels */
7080 if ((glyphSize.cx != 0) && (glyphSize.cy != 0))
7081 {
7082 /*
7083 * We should create the bitmap out of the loop at the biggest possible
7084 * glyph size. Then use memset with 0 to clear it and sourcerect to
7085 * limit the work of the transbitblt.
7086 */
7087 hbmGlyph = EngCreateBitmap(glyphSize, realglyph->bitmap.pitch,
7089 realglyph->bitmap.buffer);
7090 if (!hbmGlyph)
7091 {
7092 DPRINT1("WARNING: EngCreateBitmap() failed!\n");
7093 bResult = FALSE;
7094 break;
7095 }
7096
7097 psoGlyph = EngLockSurface((HSURF)hbmGlyph);
7098 if (!psoGlyph)
7099 {
7100 EngDeleteSurface((HSURF)hbmGlyph);
7101 DPRINT1("WARNING: EngLockSurface() failed!\n");
7102 bResult = FALSE;
7103 break;
7104 }
7105
7106 /*
7107 * Use the font data as a mask to paint onto the DCs surface using a
7108 * brush.
7109 */
7110 if (lprc && (fuOptions & ETO_CLIPPED))
7111 {
7112 // We do the check '>=' instead of '>' to possibly save an iteration
7113 // through this loop, since it's breaking after the drawing is done,
7114 // and x is always incremented.
7115 if (DestRect.right >= lprc->right)
7116 {
7117 DestRect.right = lprc->right;
7118 DoBreak = TRUE;
7119 }
7120
7121 if (DestRect.bottom >= lprc->bottom)
7122 {
7123 DestRect.bottom = lprc->bottom;
7124 }
7125 }
7126
7127 if (!IntEngMaskBlt(psoDest,
7128 psoGlyph,
7129 (CLIPOBJ *)&dc->co,
7130 &exloRGB2Dst.xlo,
7131 &exloDst2RGB.xlo,
7132 &DestRect,
7133 (PPOINTL)&MaskRect,
7134 &dc->eboText.BrushObject,
7135 &g_PointZero))
7136 {
7137 DPRINT1("Failed to MaskBlt a glyph!\n");
7138 }
7139
7140 EngUnlockSurface(psoGlyph);
7141 EngDeleteSurface((HSURF)hbmGlyph);
7142 }
7143
7144 if (DoBreak)
7145 break;
7146
7147 if (NULL == Dx)
7148 {
7149 X64 += realglyph->root.advance.x >> 10;
7150 Y64 -= realglyph->root.advance.y >> 10;
7151 }
7152 else if (fuOptions & ETO_PDY)
7153 {
7154 vec.x = (Dx[2 * i + 0] << 6);
7155 vec.y = (Dx[2 * i + 1] << 6);
7156 if (!bNoTransform)
7157 FT_Vector_Transform(&vec, &Cache.Hashed.matTransform);
7158 X64 += vec.x;
7159 Y64 -= vec.y;
7160 }
7161 else
7162 {
7163 vec.x = (Dx[i] << 6);
7164 vec.y = 0;
7165 if (!bNoTransform)
7166 FT_Vector_Transform(&vec, &Cache.Hashed.matTransform);
7167 X64 += vec.x;
7168 Y64 -= vec.y;
7169 }
7170
7171 DPRINT("New X64, New Y64: %I64d, %I64d\n", X64, Y64);
7172
7173 previous = glyph_index;
7174 }
7175 /* Don't update position if String == NULL. Fixes CORE-19721. */
7176 if ((pdcattr->flTextAlign & TA_UPDATECP) && String)
7177 pdcattr->ptlCurrent.x = DestRect.right - dc->ptlDCOrig.x;
7178
7179 if (plf->lfUnderline || plf->lfStrikeOut) /* Underline or strike-out? */
7180 {
7181 /* Calculate the position and the thickness */
7182 INT underline_position, thickness;
7183 FT_Vector vecA64, vecB64;
7184
7185 DeltaX64 = X64 - RealXStart64;
7186 DeltaY64 = Y64 - RealYStart64;
7187
7188 if (!face->units_per_EM)
7189 {
7191 thickness = 1;
7192 }
7193 else
7194 {
7196 face->underline_position * face->size->metrics.y_ppem / face->units_per_EM;
7197 thickness =
7198 face->underline_thickness * face->size->metrics.y_ppem / face->units_per_EM;
7199 if (thickness <= 0)
7200 thickness = 1;
7201 }
7202
7203 if (plf->lfUnderline) /* Draw underline */
7204 {
7205 vecA64.x = 0;
7206 vecA64.y = (-underline_position - thickness / 2) << 6;
7207 vecB64.x = 0;
7208 vecB64.y = vecA64.y + (thickness << 6);
7209 FT_Vector_Transform(&vecA64, &Cache.Hashed.matTransform);
7210 FT_Vector_Transform(&vecB64, &Cache.Hashed.matTransform);
7211 {
7212 INT X0 = (RealXStart64 - vecA64.x + 32) >> 6;
7213 INT Y0 = (RealYStart64 + vecA64.y + 32) >> 6;
7214 INT DX = (DeltaX64 >> 6);
7215 if (Cache.Hashed.matTransform.xy == 0 && Cache.Hashed.matTransform.yx == 0)
7216 {
7217 INT CY = (vecB64.y - vecA64.y + 32) >> 6;
7218 IntEngFillBox(dc, X0, Y0, DX, CY, &dc->eboText.BrushObject);
7219 }
7220 else
7221 {
7222 INT DY = (DeltaY64 >> 6);
7223 INT X1 = X0 + ((vecA64.x - vecB64.x + 32) >> 6);
7224 INT Y1 = Y0 + ((vecB64.y - vecA64.y + 32) >> 6);
7225 POINT Points[4] =
7226 {
7227 { X0, Y0 },
7228 { X0 + DX, Y0 + DY },
7229 { X1 + DX, Y1 + DY },
7230 { X1, Y1 },
7231 };
7232 IntEngFillPolygon(dc, Points, 4, &dc->eboText.BrushObject);
7233 }
7234 }
7235 }
7236
7237 if (plf->lfStrikeOut) /* Draw strike-out */
7238 {
7239 vecA64.x = 0;
7240 vecA64.y = -(FontGDI->tmAscent << 6) / 3;
7241 vecB64.x = 0;
7242 vecB64.y = vecA64.y + (thickness << 6);
7243 FT_Vector_Transform(&vecA64, &Cache.Hashed.matTransform);
7244 FT_Vector_Transform(&vecB64, &Cache.Hashed.matTransform);
7245 {
7246 INT X0 = (RealXStart64 - vecA64.x + 32) >> 6;
7247 INT Y0 = (RealYStart64 + vecA64.y + 32) >> 6;
7248 INT DX = (DeltaX64 >> 6);
7249 if (Cache.Hashed.matTransform.xy == 0 && Cache.Hashed.matTransform.yx == 0)
7250 {
7251 INT CY = (vecB64.y - vecA64.y + 32) >> 6;
7252 IntEngFillBox(dc, X0, Y0, DX, CY, &dc->eboText.BrushObject);
7253 }
7254 else
7255 {
7256 INT DY = (DeltaY64 >> 6);
7257 INT X1 = X0 + ((vecA64.x - vecB64.x + 32) >> 6);
7258 INT Y1 = Y0 + ((vecB64.y - vecA64.y + 32) >> 6);
7259 POINT Points[4] =
7260 {
7261 { X0, Y0 },
7262 { X0 + DX, Y0 + DY },
7263 { X1 + DX, Y1 + DY },
7264 { X1, Y1 },
7265 };
7266 IntEngFillPolygon(dc, Points, 4, &dc->eboText.BrushObject);
7267 }
7268 }
7269 }
7270 }
7271
7272 FontLink_Chain_Finish(&Chain);
7273
7275
7276 EXLATEOBJ_vCleanup(&exloRGB2Dst);
7277 EXLATEOBJ_vCleanup(&exloDst2RGB);
7278
7279Cleanup:
7281
7282 if (TextObj != NULL)
7283 TEXTOBJ_UnlockText(TextObj);
7284
7285 return bResult;
7286}
7287
7288
7289BOOL
7292 _In_ HDC hDC,
7293 _In_ INT XStart,
7294 _In_ INT YStart,
7295 _In_ UINT fuOptions,
7298 _In_ INT Count,
7299 _In_opt_ const INT *Dx,
7300 _In_ DWORD dwCodePage)
7301{
7302 BOOL bResult;
7303 DC *dc;
7304
7305 // TODO: Write test-cases to exactly match real Windows in different
7306 // bad parameters (e.g. does Windows check the DC or the RECT first?).
7307 dc = DC_LockDc(hDC);
7308 if (!dc)
7309 {
7311 return FALSE;
7312 }
7313
7314 bResult = IntExtTextOutW( dc,
7315 XStart,
7316 YStart,
7317 fuOptions,
7318 lprc,
7319 String,
7320 Count,
7321 Dx,
7322 dwCodePage );
7323
7324 DC_UnlockDc(dc);
7325
7326 return bResult;
7327}
7328
7329#define STACK_TEXT_BUFFER_SIZE 512
7330
7331BOOL
7334 _In_ HDC hDC,
7335 _In_ INT XStart,
7336 _In_ INT YStart,
7337 _In_ UINT fuOptions,
7338 _In_opt_ LPCRECT UnsafeRect,
7339 _In_reads_opt_(Count) PCWCH UnsafeString,
7340 _In_range_(0, 0xFFFF) UINT Count,
7341 _In_reads_opt_(_Inexpressible_(cwc)) const INT *UnsafeDx,
7342 _In_ DWORD dwCodePage)
7343{
7344 BOOL Result = FALSE;
7346 RECTL SafeRect;
7347 BYTE LocalBuffer[STACK_TEXT_BUFFER_SIZE];
7348 PVOID Buffer = LocalBuffer;
7349 LPCWSTR SafeString = NULL;
7350 PINT SafeDx = NULL;
7351 ULONG BufSize, StringSize, DxSize = 0;
7352
7353 /* Check if String is valid */
7354 if ((Count > 0xFFFF) || (Count > 0 && UnsafeString == NULL))
7355 {
7357 return FALSE;
7358 }
7359
7360 if (Count > 0)
7361 {
7362 /* Calculate buffer size for string and Dx values */
7363 BufSize = StringSize = Count * sizeof(WCHAR);
7364 if (UnsafeDx)
7365 {
7366 /* If ETO_PDY is specified, we have pairs of INTs */
7367 DxSize = (Count * sizeof(INT)) * ((fuOptions & ETO_PDY) ? 2 : 1);
7368 BufSize += DxSize;
7369 }
7370
7371 /* Check if our local buffer is large enough */
7372 if (BufSize > sizeof(LocalBuffer))
7373 {
7374 /* It's not, allocate a temp buffer */
7376 if (!Buffer)
7377 {
7378 return FALSE;
7379 }
7380 }
7381
7382 /* Probe and copy user mode data to the buffer */
7383 _SEH2_TRY
7384 {
7385 /* Put the Dx before the String to assure alignment of 4 */
7386 SafeString = (LPCWSTR)(((ULONG_PTR)Buffer) + DxSize);
7387
7388 /* Probe and copy the string */
7389 ProbeForRead(UnsafeString, StringSize, 1);
7390 RtlCopyMemory((PVOID)SafeString, UnsafeString, StringSize);
7391
7392 /* If we have Dx values... */
7393 if (UnsafeDx)
7394 {
7395 /* ... probe and copy them */
7396 SafeDx = Buffer;
7397 ProbeForRead(UnsafeDx, DxSize, 1);
7398 RtlCopyMemory(SafeDx, UnsafeDx, DxSize);
7399 }
7400 }
7402 {
7404 }
7405 _SEH2_END
7406 if (!NT_SUCCESS(Status))
7407 {
7408 goto cleanup;
7409 }
7410 }
7411
7412 /* If we have a rect, copy it */
7413 if (UnsafeRect)
7414 {
7415 _SEH2_TRY
7416 {
7417 ProbeForRead(UnsafeRect, sizeof(RECT), 1);
7418 SafeRect = *UnsafeRect;
7419 }
7421 {
7423 }
7424 _SEH2_END
7425 if (!NT_SUCCESS(Status))
7426 {
7427 goto cleanup;
7428 }
7429 }
7430
7431 /* Finally call the internal routine */
7433 XStart,
7434 YStart,
7435 fuOptions,
7436 &SafeRect,
7437 SafeString,
7438 Count,
7439 SafeDx,
7440 dwCodePage);
7441
7442cleanup:
7443 /* If we allocated a buffer, free it */
7444 if (Buffer != LocalBuffer)
7445 {
7447 }
7448
7449 return Result;
7450}
7451
7452
7453/*
7454* @implemented
7455*/
7456BOOL
7459 _In_ HDC hDC,
7460 _In_ UINT FirstChar,
7462 _In_reads_opt_(Count) PCWCH UnSafepwch,
7463 _In_ FLONG fl,
7465{
7466 LPABC SafeBuff;
7467 LPABCFLOAT SafeBuffF = NULL;
7468 PDC dc;
7469 PDC_ATTR pdcattr;
7470 PTEXTOBJ TextObj;
7471 PFONTGDI FontGDI;
7472 FT_Face face;
7473 FT_CharMap charmap, found = NULL;
7474 UINT i, glyph_index, BufferSize;
7475 HFONT hFont = 0;
7477 PWCHAR Safepwch = NULL;
7478 LOGFONTW *plf;
7479
7480 if (!Buffer)
7481 {
7483 return FALSE;
7484 }
7485
7486 if (UnSafepwch)
7487 {
7488 UINT pwchSize = Count * sizeof(WCHAR);
7489 Safepwch = ExAllocatePoolWithTag(PagedPool, pwchSize, GDITAG_TEXT);
7490
7491 if(!Safepwch)
7492 {
7494 return FALSE;
7495 }
7496
7497 _SEH2_TRY
7498 {
7499 ProbeForRead(UnSafepwch, pwchSize, 1);
7500 RtlCopyMemory(Safepwch, UnSafepwch, pwchSize);
7501 }
7503 {
7505 }
7506 _SEH2_END;
7507 }
7508
7509 if (!NT_SUCCESS(Status))
7510 {
7511 if(Safepwch)
7512 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
7513
7515 return FALSE;
7516 }
7517
7518 BufferSize = Count * sizeof(ABC); // Same size!
7520 if (!fl) SafeBuffF = (LPABCFLOAT) SafeBuff;
7521 if (SafeBuff == NULL)
7522 {
7523 if(Safepwch)
7524 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
7525
7527 return FALSE;
7528 }
7529
7530 dc = DC_LockDc(hDC);
7531 if (dc == NULL)
7532 {
7533 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7534
7535 if(Safepwch)
7536 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
7537
7539 return FALSE;
7540 }
7541 pdcattr = dc->pdcattr;
7542 hFont = pdcattr->hlfntNew;
7543 TextObj = RealizeFontInit(hFont);
7544
7545 DC_UnlockDc(dc);
7546
7547 if (TextObj == NULL)
7548 {
7549 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7550
7551 if(Safepwch)
7552 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
7553
7555 return FALSE;
7556 }
7557
7558 FontGDI = ObjToGDI(TextObj->Font, FONT);
7559
7560 face = FontGDI->SharedFace->Face;
7561 if (face->charmap == NULL)
7562 {
7563 for (i = 0; i < (UINT)face->num_charmaps; i++)
7564 {
7565 charmap = face->charmaps[i];
7566 if (charmap->encoding != 0)
7567 {
7568 found = charmap;
7569 break;
7570 }
7571 }
7572
7573 if (!found)
7574 {
7575 DPRINT1("WARNING: Could not find desired charmap!\n");
7576 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7577
7578 if(Safepwch)
7579 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
7580
7582 return FALSE;
7583 }
7584
7586 FT_Set_Charmap(face, found);
7588 }
7589
7590 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
7591
7592 // NOTE: GetCharABCWidths simply ignores lfEscapement and XFORM.
7594 IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
7596
7597 for (i = FirstChar; i < FirstChar+Count; i++)
7598 {
7599 int adv, lsb, bbx, left, right;
7600
7601 if (Safepwch)
7602 {
7603 glyph_index = get_glyph_index_flagged(face, Safepwch[i - FirstChar], (fl & GCABCW_INDICES));
7604 }
7605 else
7606 {
7607 glyph_index = get_glyph_index_flagged(face, i, (fl & GCABCW_INDICES));
7608 }
7609 FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
7610
7611 left = (INT)face->glyph->metrics.horiBearingX & -64;
7612 right = (INT)((face->glyph->metrics.horiBearingX + face->glyph->metrics.width) + 63) & -64;
7613 adv = (face->glyph->advance.x + 32) >> 6;
7614
7615// int test = (INT)(face->glyph->metrics.horiAdvance + 63) >> 6;
7616// DPRINT1("Advance Wine %d and Advance Ros %d\n",test, adv ); /* It's the same! */
7617
7618 lsb = left >> 6;
7619 bbx = (right - left) >> 6;
7620 /*
7621 DPRINT1("lsb %d and bbx %d\n", lsb, bbx );
7622 */
7623 if (!fl)
7624 {
7625 SafeBuffF[i - FirstChar].abcfA = (FLOAT) lsb;
7626 SafeBuffF[i - FirstChar].abcfB = (FLOAT) bbx;
7627 SafeBuffF[i - FirstChar].abcfC = (FLOAT) (adv - lsb - bbx);
7628 }
7629 else
7630 {
7631 SafeBuff[i - FirstChar].abcA = lsb;
7632 SafeBuff[i - FirstChar].abcB = bbx;
7633 SafeBuff[i - FirstChar].abcC = adv - lsb - bbx;
7634 }
7635 }
7637 TEXTOBJ_UnlockText(TextObj);
7638 Status = MmCopyToCaller(Buffer, SafeBuff, BufferSize);
7639
7640 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7641
7642 if(Safepwch)
7643 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
7644
7645 if (!NT_SUCCESS(Status))
7646 {
7648 return FALSE;
7649 }
7650
7651 DPRINT("NtGdiGetCharABCWidths Worked!\n");
7652 return TRUE;
7653}
7654
7655/*
7656* @implemented
7657*/
7660 _In_ HDC hDC,
7661 _In_ UINT FirstChar,
7662 _In_ UINT Count,
7663 _In_reads_opt_(Count) PCWCH Safepwc,
7664 _In_ FLONG fl,
7666{
7667 PDC dc;
7668 PDC_ATTR pdcattr;
7669 PTEXTOBJ TextObj;
7670 PFONTGDI FontGDI;
7671 FT_Face face;
7672 FT_CharMap charmap, found = NULL;
7673 UINT i, glyph_index;
7674 HFONT hFont = 0;
7675 LOGFONTW *plf;
7676 PINT SafeBuffI;
7677 PFLOAT SafeBuffF;
7678
7679 dc = DC_LockDc(hDC);
7680 if (dc == NULL)
7681 {
7683 return FALSE;
7684 }
7685
7686 pdcattr = dc->pdcattr;
7687 hFont = pdcattr->hlfntNew;
7688 TextObj = RealizeFontInit(hFont);
7689 DC_UnlockDc(dc);
7690
7691 if (TextObj == NULL)
7692 {
7694 return FALSE;
7695 }
7696
7697 FontGDI = ObjToGDI(TextObj->Font, FONT);
7698
7699 face = FontGDI->SharedFace->Face;
7700 if (face->charmap == NULL)
7701 {
7702 // FIXME: Select better charmap
7703 for (i = 0; i < (UINT)face->num_charmaps; i++)
7704 {
7705 charmap = face->charmaps[i];
7706 if (charmap->encoding != 0)
7707 {
7708 found = charmap;
7709 break;
7710 }
7711 }
7712
7713 if (!found && FT_IS_SFNT(face)) // Not found and (TrueType or OpenType)?
7714 {
7715 DPRINT1("WARNING: Could not find desired charmap!\n");
7717 TEXTOBJ_UnlockText(TextObj);
7718 return FALSE;
7719 }
7720
7721 if (found)
7722 {
7724 FT_Set_Charmap(face, found);
7726 }
7727 }
7728
7729 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
7730
7731 // NOTE: GetCharWidth simply ignores lfEscapement and XFORM.
7733 IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
7735
7736 if (!fl)
7737 SafeBuffF = (PFLOAT)Buffer;
7738 else
7739 SafeBuffI = (PINT)Buffer;
7740
7741 for (i = FirstChar; i < FirstChar+Count; i++)
7742 {
7743 if (Safepwc)
7744 glyph_index = get_glyph_index_flagged(face, Safepwc[i - FirstChar], (fl & GCW_INDICES));
7745 else
7746 glyph_index = get_glyph_index_flagged(face, i, (fl & GCW_INDICES));
7747
7748 FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
7749
7750 if (!fl)
7751 SafeBuffF[i - FirstChar] = (FLOAT) ((face->glyph->advance.x + 32) >> 6);
7752 else
7753 SafeBuffI[i - FirstChar] = (face->glyph->advance.x + 32) >> 6;
7754 }
7755
7757 TEXTOBJ_UnlockText(TextObj);
7758
7759 return TRUE;
7760}
7761
7763{
7764 TT_OS2 *pOS2;
7765 FT_WinFNT_HeaderRec WinFNT;
7767
7769
7770 if (FT_IS_SFNT(Face)) // TrueType / OpenType
7771 {
7773 pOS2 = FT_Get_Sfnt_Table(Face, FT_SFNT_OS2);
7774 if (pOS2)
7775 *pDefChar = pOS2->usDefaultChar;
7777 return !!pOS2;
7778 }
7779
7780 if (!FT_IS_SCALABLE(Face)) // *.fon / *.fnt
7781 {
7783 error = FT_Get_WinFNT_Header(Face, &WinFNT);
7785 if (!error)
7786 *pDefChar = WinFNT.default_char;
7787 return !error;
7788 }
7789
7790 *pDefChar = 0; // .notdef
7791 return TRUE;
7792}
7793
7794/*
7795* @implemented
7796*/
7797// TODO: Move this code into NtGdiGetGlyphIndicesWInternal and wrap
7798// NtGdiGetGlyphIndicesW around NtGdiGetGlyphIndicesWInternal instead.
7799// NOTE: See also GreGetGlyphIndicesW.
7801W32KAPI
7802DWORD
7805 _In_ HDC hdc,
7806 _In_reads_opt_(cwc) PCWCH pwc,
7807 _In_ INT cwc,
7810{
7811 PDC dc;
7812 PDC_ATTR pdcattr;
7813 PTEXTOBJ TextObj;
7814 PFONTGDI FontGDI;
7815 HFONT hFont = NULL;
7817 INT i;
7818 WCHAR DefChar = 0xffff;
7819 PWORD Buffer = NULL;
7820 WORD StackBuffer[40];
7821 size_t pwcSize;
7822 PWSTR Safepwc = NULL;
7823 WCHAR pwcStack[40];
7824 LPCWSTR UnSafepwc = pwc;
7825 LPWORD UnSafepgi = pgi;
7826 FT_Face Face;
7827
7828 if (cwc < 0)
7829 {
7830 DPRINT1("cwc < 0\n");
7831 return GDI_ERROR;
7832 }
7833
7834 if (!UnSafepwc && !UnSafepgi && cwc > 0)
7835 {
7836 DPRINT1("!UnSafepwc && !UnSafepgi && cwc > 0\n");
7837 return GDI_ERROR;
7838 }
7839
7840 if (!UnSafepwc != !UnSafepgi)
7841 {
7842 DPRINT1("UnSafepwc == %p, UnSafepgi = %p\n", UnSafepwc, UnSafepgi);
7843 return GDI_ERROR;
7844 }
7845
7846 /* Get FontGDI */
7847 dc = DC_LockDc(hdc);
7848 if (!dc)
7849 {
7850 DPRINT1("!DC_LockDC\n");
7851 return GDI_ERROR;
7852 }
7853 pdcattr = dc->pdcattr;
7854 hFont = pdcattr->hlfntNew;
7855 TextObj = RealizeFontInit(hFont);
7856 DC_UnlockDc(dc);
7857 if (!TextObj)
7858 {
7859 DPRINT1("!TextObj\n");
7860 return GDI_ERROR;
7861 }
7862 FontGDI = ObjToGDI(TextObj->Font, FONT);
7863 Face = FontGDI->SharedFace->Face;
7864 TEXTOBJ_UnlockText(TextObj);
7865
7866 if (cwc == 0)
7867 {
7868 if (!UnSafepwc && !UnSafepgi)
7869 return Face->num_glyphs;
7870
7872 goto ErrorRet;
7873 }
7874
7875 // Allocate Buffer and Safepwc
7876 pwcSize = cwc * sizeof(WORD);
7877 if (pwcSize <= sizeof(StackBuffer) && pwcSize <= sizeof(pwcStack))
7878 {
7879 // Stack is faster than dynamic allocation
7880 Buffer = StackBuffer;
7881 Safepwc = pwcStack;
7882 }
7883 else // Dynamic allocation
7884 {
7886 Safepwc = ExAllocatePoolWithTag(PagedPool, pwcSize, GDITAG_TEXT);
7887 if (!Buffer || !Safepwc)
7888 {
7890 goto ErrorRet;
7891 }
7892 }
7893
7894 /* Get DefChar */
7895 if (!(iMode & GGI_MARK_NONEXISTING_GLYPHS) && IntGetFontDefaultChar(Face, &DefChar))
7896 {
7898 DefChar = get_glyph_index(Face, DefChar); // Convert to glyph index
7900 }
7901
7902 Status = MmCopyFromCaller(Safepwc, UnSafepwc, pwcSize);
7903 if (!NT_SUCCESS(Status))
7904 {
7905 DPRINT1("Status: %08lX\n", Status);
7906 goto ErrorRet;
7907 }
7908
7909 /* Get glyph indeces */
7910 // NOTE: Windows GetGlyphIndices doesn't support Surrogate Pairs.
7912 for (i = 0; i < cwc; i++)
7913 {
7914 Buffer[i] = get_glyph_index(Face, Safepwc[i]);
7915 if (Buffer[i] == 0)
7916 Buffer[i] = DefChar;
7917 }
7919
7920 Status = MmCopyToCaller(UnSafepgi, Buffer, cwc * sizeof(WORD));
7921
7922ErrorRet:
7923 if (Buffer && Buffer != StackBuffer)
7925 if (Safepwc && Safepwc != pwcStack)
7927
7928 if (NT_SUCCESS(Status))
7929 return cwc;
7930
7931 return GDI_ERROR;
7932}
static HDC hDC
Definition: 3dtext.c:33
@ IgnoreFiles
Definition: ACListISF.cpp:75
NTSTATUS NTAPI MmUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:2765
@ ObjectNameInformation
Definition: DriverTester.h:55
#define BufSize
Definition: FsRtlTunnel.c:28
BOOLEAN bLocked
Definition: Mke2fs.c:19
PWSTR Names[]
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define __inline
Definition: _wctype.cpp:15
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define index(s, c)
Definition: various.h:29
#define DPRINT1
Definition: precomp.h:8
HFONT hFont
Definition: main.c:53
static VOID del(LPHIST_ENTRY item)
Definition: history.c:199
BOOL Error
Definition: chkdsk.c:66
#define ULongToHandle(h)
Definition: basetsd.h:75
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
return Found
Definition: dirsup.c:1270
HGDIOBJ hHmgr(VOID)
Definition: baseobj.hpp:95
Definition: bufpool.h:45
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
FORCEINLINE PMATRIX DC_pmxWorldToDevice(PDC pdc)
Definition: coord.h:135
static BOOLEAN IntLPtoDP(DC *pdc, PPOINTL ppt, UINT count)
Definition: coord.h:182
HDC dc
Definition: cylfrac.c:34
#define STATUS_INVALID_HANDLE
Definition: d3dkmdt.h:40
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
VOID FASTCALL DC_vPrepareDCsForBlit(PDC pdcDest, const RECT *rcDest, PDC pdcSrc, const RECT *rcSrc)
Definition: dclife.c:505
VOID FASTCALL DC_vFinishBlit(PDC pdc1, PDC pdc2)
Definition: dclife.c:614
FORCEINLINE VOID DC_UnlockDc(PDC pdc)
Definition: dc.h:238
VOID FASTCALL DC_vUpdateTextBrush(PDC pdc)
Definition: dcobjs.c:108
VOID FASTCALL DC_vUpdateBackgroundBrush(PDC pdc)
Definition: dcobjs.c:126
FORCEINLINE PDC DC_LockDc(HDC hdc)
Definition: dc.h:220
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define BufferSize
Definition: mmc.h:75
LPWSTR Name
Definition: desk.c:124
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
WORD face[3]
Definition: mesh.c:4747
#define TAG_USTR
Definition: libsupp.c:997
#define APIENTRY
Definition: api.h:79
LONG WINAPI RegDeleteValueW(HKEY hKey, LPCWSTR lpValueName)
Definition: reg.c:2330
LONG WINAPI RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2830
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#define wcschr
Definition: compat.h:17
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define PAGE_READONLY
Definition: compat.h:138
#define SECTION_MAP_READ
Definition: compat.h:139
#define wcsrchr
Definition: compat.h:16
#define MAX_PATH
Definition: compat.h:34
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define FILE_SHARE_READ
Definition: compat.h:136
unsigned char Byte
Definition: zlib.h:37
#define TT_MS_ID_UNICODE_CS
Definition: font.c:1181
#define TT_PLATFORM_MICROSOFT
Definition: font.c:1174
#define TT_MS_ID_SYMBOL_CS
Definition: font.c:1180
#define TT_PLATFORM_APPLE_UNICODE
Definition: font.c:1172
static void cleanup(void)
Definition: main.c:1335
WCHAR *WINAPI PathFindFileNameW(const WCHAR *path)
Definition: path.c:1701
BOOL WINAPI PathIsRelativeW(const WCHAR *path)
Definition: path.c:1030
_ACRTIMP int __cdecl _wtoi(const wchar_t *)
Definition: wcs.c:2773
_ACRTIMP int __cdecl _wcsicmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:159
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2983
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
_ACRTIMP int __cdecl _wcsnicmp(const wchar_t *, const wchar_t *, size_t)
Definition: wcs.c:195
#define LONG_MAX
Definition: limits.h:30
_ACRTIMP __msvcrt_long __cdecl labs(__msvcrt_long)
Definition: math.c:680
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
static void CharSet(RTF_Info *info)
Definition: reader.c:2400
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
static const WCHAR Cleanup[]
Definition: register.c:80
@ AnsiString
Definition: dnslib.h:19
#define pt(x, y)
Definition: drawing.c:79
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
return Iosb
Definition: create.c:4403
#define ULONG_PTR
Definition: config.h:101
POINTL point
Definition: edittest.c:50
#define GDIToObj(ClipGDI, Type)
Definition: engobjects.h:185
#define FONTGDI_MAGIC
Definition: engobjects.h:171
#define ObjToGDI(ClipObj, Type)
Definition: engobjects.h:184
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
#define RemoveTailList(ListHead)
Definition: env_spec_w32.h:975
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define PagedPool
Definition: env_spec_w32.h:308
#define ExInitializePushLock
Definition: ex.h:1016
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
@ IsEqual
Definition: fatprocs.h:1887
#define abs(i)
Definition: fconv.c:206
struct _FileName FileName
Definition: fatprocs.h:897
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define FLOATOBJ_Set1(fo)
Definition: floatobj.h:119
#define FLOATOBJ_Equal1(pf)
Definition: floatobj.h:105
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
BOOL LoadFont(LPWSTR lpCmdLine)
VOID IntDeleteRegFontEntries(_In_ PCWSTR pszFileName, _In_ DWORD dwFlags)
Definition: freetype.c:2235
BOOL FASTCALL TextIntUpdateSize(PDC dc, PTEXTOBJ TextObj, PFONTGDI FontGDI, BOOL bDoLock)
Definition: freetype.c:4219
BOOL FASTCALL TextIntGetTextExtentPoint(_In_ PDC dc, _In_ PTEXTOBJ TextObj, _In_reads_(Count) PCWCH String, _In_ INT Count, _In_ ULONG MaxExtent, _Out_ PINT Fit, _Out_writes_to_opt_(Count, *Fit) PINT Dx, _Out_ PSIZE Size, _In_ FLONG fl)
Definition: freetype.c:4956
static PFONT_LOOKUP_CACHE FontLookUp_LookUp(const LOGFONTW *pLogFont)
Definition: freetype.c:5954
static FT_UInt FASTCALL get_glyph_index_flagged(FT_Face face, FT_ULong code, BOOL fCodeAsIndex)
Definition: freetype.c:4337
#define CP_OEMCP
Definition: freetype.c:424
static BOOLEAN FASTCALL GetFontFamilyInfoForList(const LOGFONTW *LogFont, PFONTFAMILYINFO Info, LPCWSTR NominalName, LONG *pCount, LONG MaxCount, PLIST_ENTRY Head)
Definition: freetype.c:3626
static UINT FontLink_Chain_FindGlyph(_Inout_ PFONTLINK_CHAIN pChain, _Out_ PFONT_CACHE_ENTRY pCache, _Inout_ FT_Face *pFace, _In_ UINT code, _In_ BOOL fCodeAsIndex)
Definition: freetype.c:4368
DWORD FASTCALL ftGdiGetKerningPairs(PFONTGDI Font, DWORD cPairs, LPKERNINGPAIR pKerningPair)
Definition: freetype.c:6464
#define ASSERT_FREETYPE_LOCK_NOT_HELD()
Definition: freetype.c:334
static const CHARSETINFO g_FontTci[MAXTCIINDEX]
Definition: freetype.c:382
__kernel_entry W32KAPI DWORD APIENTRY NtGdiGetGlyphIndicesW(_In_ HDC hdc, _In_reads_opt_(cwc) PCWCH pwc, _In_ INT cwc, _Out_writes_opt_(cwc) PWORD pgi, _In_ DWORD iMode)
Definition: freetype.c:7804
static WCHAR s_szDefFontLinkFileName[MAX_PATH]
Definition: freetype.c:61
static VOID FontLink_Chain_Free(_Inout_ PFONTLINK_CHAIN pChain)
Definition: freetype.c:194
LONG FASTCALL IntGetFontFamilyInfo(HDC Dc, const LOGFONTW *SafeLogFont, PFONTFAMILYINFO SafeInfo, LONG InfoCount)
Definition: freetype.c:6515
static PFAST_MUTEX g_FreeTypeLock
Definition: freetype.c:326
VOID FASTCALL IntGdiCleanupMemEntry(PFONT_ENTRY_MEM Head)
Definition: freetype.c:2578
static UINT GetFontPenalty(const LOGFONTW *LogFont, const OUTLINETEXTMETRICW *Otm, const char *style_name)
Definition: freetype.c:5405
static const UNICODE_STRING DosPathPrefix
Definition: freetype.c:1990
static BOOL face_has_symbol_charmap(FT_Face ft_face)
Definition: freetype.c:2821
static DWORD IntGetHash(IN LPCVOID pv, IN DWORD cdw)
Definition: freetype.c:3765
static BOOL FASTCALL IntGetFullFileName(POBJECT_NAME_INFORMATION NameInfo, ULONG Size, PUNICODE_STRING FileName)
Definition: freetype.c:6100
static FT_Error IntRequestFontSize(PDC dc, PFONTGDI FontGDI, LONG lfWidth, LONG lfHeight)
Definition: freetype.c:4080
static INT FASTCALL IntGdiAddFontResourceSingle(_In_ PCUNICODE_STRING FileName, _In_ DWORD Characteristics, _In_ DWORD dwFlags)
Definition: freetype.c:1994
static BOOL s_fFontLinkUseAnsi
Definition: freetype.c:63
static void SharedMem_AddRef(PSHARED_MEM Ptr)
Definition: freetype.c:485
BOOL FASTCALL ftGdiGetTextMetricsW(HDC hDC, PTMW_INTERNAL ptmwi)
Definition: freetype.c:5265
BOOL FASTCALL IntGdiRemoveFontResource(_In_ PCUNICODE_STRING FileName, _In_ DWORD cFiles, _In_ DWORD dwFlags)
Definition: freetype.c:2340
static INT FASTCALL IntGdiLoadFontByIndexFromMemory(PGDI_LOAD_FONT pLoadFont, FT_Long FontIndex)
Definition: freetype.c:1940
static BOOL FontLink_PrepareFontInfo(_Inout_ PFONTLINK pFontLink)
Definition: freetype.c:460
static PSHARED_FACE SharedFace_Create(FT_Face Face, PSHARED_MEM Memory)
Definition: freetype.c:501
static VOID FASTCALL IntFontType(PFONTGDI Font)
Definition: freetype.c:5820
BOOL APIENTRY GreExtTextOutW(_In_ HDC hDC, _In_ INT XStart, _In_ INT YStart, _In_ UINT fuOptions, _In_opt_ PRECTL lprc, _In_reads_opt_(Count) PCWCH String, _In_ INT Count, _In_opt_ const INT *Dx, _In_ DWORD dwCodePage)
Definition: freetype.c:7291
FT_Library g_FreeTypeLibrary
Definition: freetype.c:318
BOOL FASTCALL IntGdiGetFontResourceInfo(PUNICODE_STRING FileName, PVOID pBuffer, DWORD *pdwBytes, DWORD dwType)
Definition: freetype.c:6177
static PWCHAR g_ElfScripts[32]
Definition: freetype.c:354
static PSHARED_MEM SharedMem_Create(PBYTE Buffer, ULONG BufferSize, BOOL IsMapping)
Definition: freetype.c:520
static BOOL EqualFamilyInfo(const FONTFAMILYINFO *pInfo1, const FONTFAMILYINFO *pInfo2)
Definition: freetype.c:6143
static DWORD s_chFontLinkDefaultChar
Definition: freetype.c:60
#define MAXTCIINDEX
Definition: freetype.c:381
BYTE FASTCALL IntCharSetFromCodePage(UINT uCodePage)
Definition: freetype.c:430
static PFONTLINK FontLink_Create(_Inout_ PFONTLINK_CHAIN pChain, _In_ const LOGFONTW *plfBase, _In_ LPCWSTR pszLink)
Definition: freetype.c:1366
static void FontLookUp_Add(const LOGFONTW *LogFont, PSHARED_FACE SharedFace, FONTOBJ *pFontObj)
Definition: freetype.c:5974
#define CP_SYMBOL
Definition: freetype.c:380
static void IntPopulateFontGdi(PFONTGDI FontGdi, const FONTOBJ *pFontObj, const LOGFONTW *pLogFont)
Definition: freetype.c:5938
const MATRIX gmxWorldToPageDefault
Definition: dclife.c:36
UNICODE_STRING g_FontRegPath
Definition: freetype.c:321
VOID FASTCALL IntGdiCleanupPrivateFontsForProcess(VOID)
Definition: freetype.c:2650
static void SharedFaceCache_Init(PSHARED_FACE_CACHE Cache)
Definition: freetype.c:493
static unsigned int get_bezier_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
Definition: freetype.c:3955
BOOL FASTCALL InitFontSupport(VOID)
Definition: freetype.c:997
static FT_UInt FASTCALL get_glyph_index_symbol(FT_Face ft_face, UINT glyph)
Definition: freetype.c:4308
static __inline VOID FindBestFontFromList(FONTOBJ **FontObj, ULONG *MatchPenalty, const LOGFONTW *LogFont, const PLIST_ENTRY Head)
Definition: freetype.c:5751
PSHARED_FACE IntRealizeFont(const LOGFONTW *pLogFont, _Inout_opt_ PTEXTOBJ TextObj)
Definition: freetype.c:6003
static const WCHAR s_szzDefFixedFontLink[]
Definition: freetype.c:1248
static void FontLookUp_Destroy(PFONT_LOOKUP_CACHE pCache)
Definition: freetype.c:950
BOOL FASTCALL IntLoadFontSubstList(PLIST_ENTRY pHead)
Definition: freetype.c:803
static UINT g_FontCacheNumEntries
Definition: freetype.c:352
static WCHAR s_szDefFontLinkFontName[MAX_PATH]
Definition: freetype.c:62
static BOOL IntGetTextDisposition(_Out_ LONGLONG *pX64, _Out_ LONGLONG *pY64, _In_reads_(Count) PCWCH String, _In_ INT Count, _In_opt_ const INT *Dx, _Inout_ PFONT_CACHE_ENTRY Cache, _In_ UINT fuOptions, _In_ BOOL bNoTransform, _Inout_ PFONTLINK_CHAIN pChain)
Definition: freetype.c:6656
VOID FASTCALL IntLoadSystemFonts(VOID)
Definition: freetype.c:1495
DWORD FASTCALL ftGetFontUnicodeRanges(PFONTGDI Font, PGLYPHSET glyphset)
Definition: freetype.c:5191
#define GOT_PENALTY(name, value)
Definition: freetype.c:5401
static void SharedFace_AddRef(PSHARED_FACE Ptr)
Definition: freetype.c:536
BOOL FASTCALL ftGdiGetRasterizerCaps(LPRASTERIZER_STATUS lprs)
Definition: freetype.c:3751
static VOID FASTCALL UnlinkFontMemCollection(PFONT_ENTRY_COLL_MEM Collection)
Definition: freetype.c:2597
INT FASTCALL IntGdiAddFontResourceEx(_In_ PCUNICODE_STRING FileName, _In_ DWORD cFiles, _In_ DWORD Characteristics, _In_ DWORD dwFlags)
Definition: freetype.c:2193
static NTSTATUS FontLink_LoadDefaultCharset(VOID)
Definition: freetype.c:136
struct _FONTLINK_CHAIN FONTLINK_CHAIN
#define SCALE_Y(value)
static VOID FontLink_Chain_Dump(_In_ PFONTLINK_CHAIN pChain)
Definition: freetype.c:4343
static void FASTCALL FontFamilyFillInfo(PFONTFAMILYINFO Info, LPCWSTR FaceName, LPCWSTR FullName, PFONTGDI FontGDI)
Definition: freetype.c:3443
static __inline void FASTCALL IntInitFontNames(FONT_NAMES *Names, PSHARED_FACE SharedFace)
Definition: freetype.c:3066
static void RemoveCacheEntries(FT_Face Face)
Definition: freetype.c:556
#define FM_SEL_USE_TYPO_METRICS
BOOL FASTCALL ftGdiRealizationInfo(PFONTGDI Font, PREALIZATION_INFO Info)
Definition: freetype.c:6445
#define CP_MACCP
Definition: freetype.c:425
static NTSTATUS FontLink_Chain_LoadReg(_Inout_ PFONTLINK_CHAIN pChain, _Inout_ PLOGFONTW pLF)
Definition: freetype.c:1257
VOID FASTCALL FreeFontSupport(VOID)
Definition: freetype.c:1039
VOID FASTCALL IntEnableFontRendering(BOOL Enable)
Definition: freetype.c:2706
#define IntUnLockFreeType()
Definition: freetype.c:343
static BOOL s_fFontLinkUseOem
Definition: freetype.c:64
BOOL APIENTRY GreGetCharWidthW(_In_ HDC hDC, _In_ UINT FirstChar, _In_ UINT Count, _In_reads_opt_(Count) PCWCH Safepwc, _In_ FLONG fl, _Out_writes_bytes_(Count *sizeof(INT)) PVOID Buffer)
Definition: freetype.c:7659
static INT FASTCALL IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont, PSHARED_FACE SharedFace, FT_Long FontIndex, INT CharSetIndex)
Definition: freetype.c:1649
static NTSTATUS FontLink_Chain_Populate(_Inout_ PFONTLINK_CHAIN pChain)
Definition: freetype.c:1407
static NTSTATUS FontLink_LoadSettings(VOID)
Definition: freetype.c:72
static BOOL FontLink_Chain_IsPopulated(const FONTLINK_CHAIN *pChain)
Definition: freetype.c:188
PBYTE FASTCALL IntStoreFontNames(_In_ const FONT_NAMES *Names, _Out_ OUTLINETEXTMETRICW *Otm)
Definition: freetype.c:3102
static unsigned int get_native_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
Definition: freetype.c:3882
static VOID FASTCALL IntMatrixFromMx(FT_Matrix *pmat, const MATRIX *pmx)
Definition: freetype.c:1102
static VOID FASTCALL IntEscapeMatrix(FT_Matrix *pmat, LONG lfEscapement)
Definition: freetype.c:1089
ULONG FASTCALL ftGdiGetGlyphOutline(PDC dc, WCHAR wch, UINT iFormat, LPGLYPHMETRICS pgm, ULONG cjBuf, PVOID pvBuf, const MAT2 *pmat2, BOOL bIgnoreRotation)
Definition: freetype.c:4428
static BOOL FASTCALL IntGdiRemoveFontResourceSingle(_In_ PCUNICODE_STRING FileName, _In_ DWORD dwFlags)
Definition: freetype.c:2270
static VOID FontLink_CleanupCache(VOID)
Definition: freetype.c:274
struct _FONTLINK_CHAIN * PFONTLINK_CHAIN
static BOOLEAN IntTranslateCharsetInfo(PDWORD Src, LPCHARSETINFO Cs, DWORD Flags)
Definition: freetype.c:2775
static void FontLookUp_Cleanup(_In_ BOOL bDoLock, _Inout_opt_ PSHARED_FACE SharedFace)
Definition: freetype.c:958
static VOID IntAddNameFromFamInfo(LPWSTR psz, FONTFAMILYINFO *FamInfo)
Definition: freetype.c:6164
static void FASTCALL FillTM(TEXTMETRICW *TM, PFONTGDI FontGDI, TT_OS2 *pOS2, TT_HoriHeader *pHori, FT_WinFNT_HeaderRec *pFNT)
Definition: freetype.c:2837
#define IntLockFreeType()
Definition: freetype.c:337
static FT_BitmapGlyph IntFindGlyphCache(IN const FONT_CACHE_ENTRY *pCache)
Definition: freetype.c:3780
static FT_BitmapGlyph IntGetBitmapGlyphWithCache(IN OUT PFONT_CACHE_ENTRY Cache, IN FT_GlyphSlot GlyphSlot)
Definition: freetype.c:3817
static BOOL IntGetFontDefaultChar(_In_ FT_Face Face, _Out_ PWCHAR pDefChar)
Definition: freetype.c:7762
#define STACK_TEXT_BUFFER_SIZE
Definition: freetype.c:7329
static __inline void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
Definition: freetype.c:658
NTSTATUS FASTCALL TextIntCreateFontIndirect(CONST LPLOGFONTW lf, HFONT *NewFont)
Definition: freetype.c:2733
static void SharedFaceCache_Release(PSHARED_FACE_CACHE Cache)
Definition: freetype.c:598
static BOOL g_RenderingEnabled
Definition: freetype.c:329
BOOL FASTCALL IntGdiRemoveFontMemResource(HANDLE hMMFont)
Definition: freetype.c:2614
LONG NTAPI NtGdiGetFontFamilyInfo(_In_ HDC Dc, _In_ const LOGFONTW *UnsafeLogFont, _Out_ PFONTFAMILYINFO UnsafeInfo, _Inout_ PLONG UnsafeInfoCount)
Definition: freetype.c:6555
UINT FASTCALL IntGetCharSet(INT nIndex, FT_ULong CodePageRange1)
Definition: freetype.c:1621
static NTSTATUS FontLink_LoadDefaultFonts(VOID)
Definition: freetype.c:98
#define EMUBOLD_NEEDED(original, request)
Definition: freetype.c:308
static __inline VOID FASTCALL CleanupFontEntry(PFONT_ENTRY FontEntry)
Definition: freetype.c:653
struct _FONTLINK FONTLINK
static VOID FontLink_AddCache(_In_ PFONTLINK_CACHE pCache)
Definition: freetype.c:215
NTSTATUS FASTCALL TextIntRealizeFont(HFONT FontHandle, PTEXTOBJ pTextObj)
Definition: freetype.c:6061
static BOOL SubstituteFontByList(PLIST_ENTRY pHead, PUNICODE_STRING pOutputName, PUNICODE_STRING pInputName, BYTE RequestedCharSet, BYTE CharSetMap[FONTSUBST_FROM_AND_TO])
Definition: freetype.c:1131
static FT_UInt FASTCALL get_glyph_index(FT_Face ft_face, UINT glyph)
Definition: freetype.c:4322
static const FT_Matrix identityMat
Definition: freetype.c:313
HANDLE FASTCALL IntGdiAddFontMemResource(PVOID Buffer, DWORD dwSize, PDWORD pNumAdded)
Definition: freetype.c:2528
static __inline FT_Fixed FT_FixedFromFIXED(FIXED f)
Definition: freetype.c:672
static BOOL MatchFontName(PSHARED_FACE SharedFace, PUNICODE_STRING Name1, FT_UShort NameID, FT_UShort LangID)
Definition: freetype.c:5852
static SIZE_T FASTCALL IntStoreName(_In_ const UNICODE_STRING *pName, _Out_ PBYTE pb)
Definition: freetype.c:3094
static BOOLEAN FASTCALL GetFontFamilyInfoForSubstitutes(const LOGFONTW *LogFont, PFONTFAMILYINFO Info, LONG *pCount, LONG MaxCount)
Definition: freetype.c:3690
struct _FONTLINK_CACHE FONTLINK_CACHE
static void SharedFace_Release(PSHARED_FACE Ptr, BOOL bDoLock)
Definition: freetype.c:605
#define SCALE_X(value)
static BOOL MatchFontNames(PSHARED_FACE SharedFace, LPCWSTR lfFaceName)
Definition: freetype.c:5875
#define ASSERT_FREETYPE_LOCK_HELD()
Definition: freetype.c:331
INT FASTCALL ftGdiGetTextCharsetInfo(PDC Dc, LPFONTSIGNATURE lpSig, DWORD dwFlags)
Definition: freetype.c:5078
static FT_BitmapGlyph IntGetRealGlyph(IN OUT PFONT_CACHE_ENTRY Cache)
Definition: freetype.c:4916
static void SharedMem_Release(PSHARED_MEM Ptr)
Definition: freetype.c:577
BOOL APIENTRY NtGdiExtTextOutW(_In_ HDC hDC, _In_ INT XStart, _In_ INT YStart, _In_ UINT fuOptions, _In_opt_ LPCRECT UnsafeRect, _In_reads_opt_(Count) PCWCH UnsafeString, _In_range_(0, 0xFFFF) UINT Count, _In_reads_opt_(_Inexpressible_(cwc)) const INT *UnsafeDx, _In_ DWORD dwCodePage)
Definition: freetype.c:7333
#define VALIGN_MASK
BOOL FASTCALL IntLoadFontsInRegistry(VOID)
Definition: freetype.c:2376
static ULONG s_FontLookupCacheCount
Definition: freetype.c:300
BOOL FASTCALL IntIsFontRenderingEnabled(VOID)
Definition: freetype.c:2700
DWORD FASTCALL ftGdiGetFontData(PFONTGDI FontGdi, DWORD Table, DWORD Offset, PVOID Buffer, DWORD Size)
Definition: freetype.c:5363
#define gmxWorldToDeviceDefault
Definition: freetype.c:316
struct FONT_NAMES * LPFONT_NAMES
#define MAX_FONT_LOOKUP_CACHE
Definition: freetype.c:299
static VOID FontLink_Chain_Finish(_Inout_ PFONTLINK_CHAIN pChain)
Definition: freetype.c:239
static NTSTATUS IntGetFontLocalizedName(PUNICODE_STRING pNameW, PSHARED_FACE SharedFace, FT_UShort NameID, FT_UShort LangID)
Definition: freetype.c:3299
static VOID FontLink_Destroy(_Inout_ PFONTLINK pLink)
Definition: freetype.c:182
#define MAX_FONT_CACHE
Definition: freetype.c:349
struct _FONTLINK * PFONTLINK
static VOID FontLink_Chain_Init(_Out_ PFONTLINK_CHAIN pChain, _Inout_ PTEXTOBJ pTextObj, _In_ FT_Face face)
Definition: freetype.c:1228
FT_Render_Mode FASTCALL IntGetFontRenderMode(LOGFONTW *logfont)
Definition: freetype.c:2712
static BOOL s_fFontLinkUseSymbol
Definition: freetype.c:65
static PFONTLINK FontLink_Chain_FindLink(PFONTLINK_CHAIN pChain, PLOGFONTW plf)
Definition: freetype.c:1348
struct _FONT_LOOKUP_CACHE * PFONT_LOOKUP_CACHE
struct _FONT_LOOKUP_CACHE FONT_LOOKUP_CACHE
INT FASTCALL IntGetOutlineTextMetrics(PFONTGDI FontGDI, UINT Size, OUTLINETEXTMETRICW *Otm, BOOL bLocked)
Definition: freetype.c:3139
static __inline void FASTCALL IntFreeFontNames(FONT_NAMES *Names)
Definition: freetype.c:3126
static void RemoveCachedEntry(PFONT_CACHE_ENTRY Entry)
Definition: freetype.c:544
#define _TMPF_VARIABLE_PITCH
Definition: freetype.c:304
static PFONTLINK_CACHE FontLink_FindCache(_In_ const LOGFONTW *pLogFont)
Definition: freetype.c:259
#define FONTLINK_DEFAULT_CHAR
Definition: freetype.c:58
static void IntPopulateTextObj(PTEXTOBJ TextObj, PFONTGDI FontGdi, FONTOBJ *pFontObj, const LOGFONTW *pLogFont, PLOGFONTW SubstitutedLogFont)
Definition: freetype.c:5901
static BOOL SubstituteFontRecurse(PLOGFONTW pLogFont)
Definition: freetype.c:1192
static LONG g_nFontLinkCacheCount
Definition: freetype.c:69
static const WCHAR s_szzDefFontLink[]
Definition: freetype.c:1240
#define MAX_FONTLINK_CACHE
Definition: freetype.c:67
struct _FONTLINK_CACHE * PFONTLINK_CACHE
static VOID FASTCALL CleanupFontEntryEx(PFONT_ENTRY FontEntry, PFONTGDI FontGDI)
Definition: freetype.c:633
BOOL APIENTRY IntExtTextOutW(_In_ PDC dc, _In_ INT XStart, _In_ INT YStart, _In_ UINT fuOptions, _In_opt_ PRECTL lprc, _In_reads_opt_(Count) PCWCH String, _In_ INT Count, _In_opt_ const INT *Dx, _In_ DWORD dwCodePage)
Definition: freetype.c:6742
BOOL APIENTRY NtGdiGetCharABCWidthsW(_In_ HDC hDC, _In_ UINT FirstChar, _In_ ULONG Count, _In_reads_opt_(Count) PCWCH UnSafepwch, _In_ FLONG fl, _Out_writes_bytes_(Count *sizeof(ABC)) PVOID Buffer)
Definition: freetype.c:7458
FT_Load_Glyph(FT_Face face, FT_UInt glyph_index, FT_Int32 load_flags)
Definition: ftobjs.c:796
#define FT_LOAD_NO_BITMAP
Definition: freetype.h:3025
FT_Set_Transform(FT_Face face, FT_Matrix *matrix, FT_Vector *delta)
Definition: ftobjs.c:689
#define FT_IS_SFNT(face)
Definition: freetype.h:1290
@ FT_SIZE_REQUEST_TYPE_NOMINAL
Definition: freetype.h:2552
FT_Done_Face(FT_Face face)
Definition: ftobjs.c:2783
FT_Get_First_Char(FT_Face face, FT_UInt *agindex)
Definition: ftobjs.c:3760
#define FT_HAS_MULTIPLE_MASTERS(face)
Definition: freetype.h:1361
enum FT_Render_Mode_ FT_Render_Mode
#define FT_LOAD_NO_HINTING
Definition: freetype.h:3023
FT_Get_Char_Index(FT_Face face, FT_ULong charcode)
Definition: ftobjs.c:3731
#define FT_HAS_FIXED_SIZES(face)
Definition: freetype.h:1320
#define FT_IS_SCALABLE(face)
Definition: freetype.h:1271
#define FT_HAS_VERTICAL(face)
Definition: freetype.h:1242
#define FT_LOAD_DEFAULT
Definition: freetype.h:3021
#define FT_IS_FIXED_WIDTH(face)
Definition: freetype.h:1305
FT_Request_Size(FT_Face face, FT_Size_Request req)
Definition: ftobjs.c:3256
FT_Get_Next_Char(FT_Face face, FT_ULong char_code, FT_UInt *agindex)
Definition: ftobjs.c:3785
FT_Set_Charmap(FT_Face face, FT_CharMap charmap)
Definition: ftobjs.c:3564
#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
Definition: freetype.h:3030
FT_Vector_Transform(FT_Vector *vector, const FT_Matrix *matrix)
Definition: ftoutln.c:683
@ FT_RENDER_MODE_MONO
Definition: freetype.h:3251
@ FT_RENDER_MODE_NORMAL
Definition: freetype.h:3249
@ FT_RENDER_MODE_LIGHT
Definition: freetype.h:3250
@ FT_RENDER_MODE_LCD
Definition: freetype.h:3252
FT_Get_Kerning(FT_Face face, FT_UInt left_glyph, FT_UInt right_glyph, FT_UInt kern_mode, FT_Vector *akerning)
Definition: ftobjs.c:3411
@ FT_KERNING_DEFAULT
Definition: freetype.h:3406
FT_MulDiv(FT_Long a, FT_Long b, FT_Long c)
Definition: ftcalc.c:415
FT_New_Memory_Face(FT_Library library, const FT_Byte *file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface)
Definition: ftobjs.c:1493
FT_MulFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:508
#define FT_HAS_KERNING(face)
Definition: freetype.h:1256
FT_Init_FreeType(FT_Library *alibrary)
Definition: ftinit.c:199
@ FileDirectoryInformation
Definition: from_kernel.h:62
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
_Must_inspect_result_ _In_ PCUNICODE_STRING Name2
Definition: fsrtlfuncs.h:796
_Must_inspect_result_ _Outptr_ PVOID * SectionObject
Definition: fsrtlfuncs.h:860
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
FT_Vector * vec
Definition: ftbbox.c:469
FT_Bitmap_New(FT_Bitmap *abitmap)
Definition: ftbitmap.c:53
FT_Bitmap_Done(FT_Library library, FT_Bitmap *bitmap)
Definition: ftbitmap.c:1197
#define INT_TO_FIXED(x)
Definition: ftcalc.h:448
FT_Done_Glyph(FT_Glyph glyph)
Definition: ftglyph.c:641
FT_Glyph_To_Bitmap(FT_Glyph *the_glyph, FT_Render_Mode render_mode, FT_Vector *origin, FT_Bool destroy)
Definition: ftglyph.c:536
FT_Get_Glyph(FT_GlyphSlot slot, FT_Glyph *aglyph)
Definition: ftglyph.c:401
struct FT_BitmapGlyphRec_ * FT_BitmapGlyph
Definition: ftglyph.h:131
FT_Matrix_Multiply(const FT_Matrix *a, FT_Matrix *b)
Definition: ftcalc.c:660
#define ft_glyph_format_bitmap
Definition: ftimage.h:759
@ FT_PIXEL_MODE_MONO
Definition: ftimage.h:183
@ FT_PIXEL_MODE_GRAY
Definition: ftimage.h:184
#define FT_Curve_Tag_On
Definition: ftimage.h:478
#define ft_glyph_format_outline
Definition: ftimage.h:760
FT_Done_Library(FT_Library library)
Definition: ftobjs.c:5353
FT_Outline_Translate(const FT_Outline *outline, FT_Pos xOffset, FT_Pos yOffset)
Definition: ftoutln.c:507
FT_Outline_Get_Bitmap(FT_Library library, FT_Outline *outline, const FT_Bitmap *abitmap)
Definition: ftoutln.c:656
FT_Outline_Transform(const FT_Outline *outline, const FT_Matrix *matrix)
Definition: ftoutln.c:706
long Long
Definition: ftraster.c:311
FT_Get_Sfnt_Name_Count(FT_Face face)
Definition: ftsnames.c:148
FT_BEGIN_HEADER struct FT_SfntName_ FT_SfntName
FT_Get_Sfnt_Name(FT_Face face, FT_UInt idx, FT_SfntName *aname)
Definition: ftsnames.c:157
FT_BEGIN_HEADER FT_GlyphSlot_Embolden(FT_GlyphSlot slot)
Definition: ftsynth.c:89
FT_GlyphSlot_Oblique(FT_GlyphSlot slot)
Definition: ftsynth.c:47
FT_BEGIN_HEADER typedef FT_Fixed FT_Angle
Definition: fttrigon.h:52
FT_Vector_Unit(FT_Vector *vec, FT_Angle angle)
Definition: fttrigon.c:360
unsigned long FT_ULong
Definition: fttypes.h:253
signed long FT_Fixed
Definition: fttypes.h:287
int FT_Error
Definition: fttypes.h:299
signed long FT_Long
Definition: fttypes.h:242
unsigned short FT_UShort
Definition: fttypes.h:209
signed short FT_Short
Definition: fttypes.h:198
unsigned int FT_UInt
Definition: fttypes.h:231
signed int FT_Int
Definition: fttypes.h:220
FT_Get_WinFNT_Header(FT_Face face, FT_WinFNT_HeaderRec *aheader)
Definition: ftwinfnt.c:28
FxAutoRegKey hKey
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
return pTarget Start()
#define FONTSUBST_FROM_AND_TO
Definition: font.h:71
#define FONTSUBST_FROM
Definition: font.h:69
#define FONTSUBST_TO
Definition: font.h:70
Status
Definition: gdiplustypes.h:25
ASMGENDATA Table[]
Definition: genincdata.c:61
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLint GLint GLsizei width
Definition: gl.h:1546
GLdouble n
Definition: glext.h:7729
GLenum src
Definition: glext.h:6340
GLsizeiptr size
Definition: glext.h:5919
GLuint index
Definition: glext.h:6031
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLdouble GLdouble right
Definition: glext.h:10859
GLenum GLuint GLint GLenum face
Definition: glext.h:7025
GLfloat f
Definition: glext.h:7540
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLint left
Definition: glext.h:7726
GLenum GLenum dst
Definition: glext.h:6340
GLint GLint bottom
Definition: glext.h:7726
GLfloat angle
Definition: glext.h:10853
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define fs
Definition: i386-dis.c:444
#define DX
Definition: i386-dis.c:425
#define FLOAT
Definition: i386-dis.c:525
PSERVERINFO gpsi
Definition: imm.c:18
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define NOTHING
Definition: input_list.c:10
#define USHORT_MAX
Definition: intsafe.h:147
#define RtlEqualMemory(dst, src, len)
Definition: kdvm.h:18
#define REG_SZ
Definition: layer.c:22
static PWSTR PDWORD pdwBytes
Definition: layerapi.c:35
if(dx< 0)
Definition: linetemp.h:194
POINT cp
Definition: magnifier.c:59
FLOAT * PFLOAT
Definition: minwindef.h:147
int * PINT
Definition: minwindef.h:150
CONST void * LPCVOID
Definition: minwindef.h:164
#define error(str)
Definition: mkdosfs.c:1605
#define pch(ap)
Definition: match.c:418
#define MmCopyToCaller(x, y, z)
Definition: mmcopy.h:19
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
LPCWSTR szPath
Definition: env.c:37
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static PVOID ptr
Definition: dispmode.c:27
HDC hdc
Definition: main.c:9
FORCEINLINE PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
static LPSTR pName
Definition: security.c:116
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:88
#define TT_NAME_ID_FULL_NAME
Definition: font.c:3539
static const MAT2 mat
Definition: font.c:66
#define TT_NAME_ID_UNIQUE_ID
Definition: font.c:3538
static LPCSTR INT LPWORD pgi
Definition: font.c:51
#define TT_NAME_ID_FONT_FAMILY
Definition: font.c:3536
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
#define TT_NAME_ID_FONT_SUBFAMILY
Definition: font.c:3537
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define min(a, b)
Definition: monoChain.cc:55
_In_ HANDLE hFile
Definition: mswsock.h:90
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
unsigned int UINT
Definition: ndis.h:50
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
#define KernelMode
Definition: asm.h:38
NTSYSAPI NTSTATUS NTAPI ZwOpenFile(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions)
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:408
#define SEC_COMMIT
Definition: mmtypes.h:100
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
NTSYSAPI VOID NTAPI RtlGetDefaultCodePage(_Out_ PUSHORT AnsiCodePage, _Out_ PUSHORT OemCodePage)
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
#define _Out_writes_to_opt_(s, c)
Definition: no_sal2.h:238
#define _In_reads_(s)
Definition: no_sal2.h:168
#define _Inout_
Definition: no_sal2.h:162
#define _Out_writes_opt_(s)
Definition: no_sal2.h:226
#define _Inout_opt_
Definition: no_sal2.h:216
#define _Out_
Definition: no_sal2.h:160
#define _In_reads_opt_(s)
Definition: no_sal2.h:222
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define _In_range_(l, h)
Definition: no_sal2.h:368
#define _Out_writes_bytes_(s)
Definition: no_sal2.h:178
int Count
Definition: noreturn.cpp:7
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
@ KeyFullInformation
Definition: nt_native.h:1136
#define FILE_READ_DATA
Definition: nt_native.h:628
@ KeyValueFullInformation
Definition: nt_native.h:1184
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define KEY_READ
Definition: nt_native.h:1026
#define FILE_LIST_DIRECTORY
Definition: nt_native.h:629
#define SECTION_QUERY
Definition: nt_native.h:1290
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define FASTCALL
Definition: nt_native.h:50
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define REG_MULTI_SZ
Definition: nt_native.h:1504
#define BOOL
Definition: nt_native.h:43
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define KEY_WRITE
Definition: nt_native.h:1034
#define DWORD
Definition: nt_native.h:44
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
#define FILE_GENERIC_READ
Definition: nt_native.h:653
struct _KEY_VALUE_FULL_INFORMATION * PKEY_VALUE_FULL_INFORMATION
#define STANDARD_RIGHTS_REQUIRED
Definition: nt_native.h:63
WCHAR * PWCH
Definition: ntbasedef.h:422
unsigned long FLONG
Definition: ntbasedef.h:378
CONST WCHAR * PCWCH
Definition: ntbasedef.h:423
#define UNICODE_NULL
_NullNull_terminated_ WCHAR * PZZWSTR
Definition: ntbasedef.h:432
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define W32KAPI
Definition: ntgdi.h:9
struct tagFONTFAMILYINFO FONTFAMILYINFO
#define DIRTY_TEXT
Definition: ntgdihdl.h:125
#define DIRTY_BACKGROUND
Definition: ntgdihdl.h:126
#define GTEF_INDICES
Definition: ntgdityp.h:213
#define RI_TECH_SCALABLE
Definition: ntgdityp.h:273
#define GCW_INDICES
Definition: ntgdityp.h:206
#define RI_TECH_FIXED
Definition: ntgdityp.h:272
#define GCABCW_INDICES
Definition: ntgdityp.h:210
#define RI_TECH_BITMAP
Definition: ntgdityp.h:271
struct _MATRIX * PMATRIX
PVOID NTAPI PsGetCurrentProcessWin32Process(VOID)
Definition: process.c:1183
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:559
NTSTRSAFEAPI RtlStringCbCopyW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:174
NTSTRSAFEAPI RtlStringCchCopyNW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_reads_or_z_(cchToCopy) STRSAFE_LPCWSTR pszSrc, _In_ size_t cchToCopy)
Definition: ntstrsafe.h:363
NTSTRSAFEAPI RtlStringCchCopyW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:127
NTSTRSAFEAPI RtlStringCchCatW(_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:601
NTSTRSAFEVAPI RtlStringCbPrintfW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1173
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define PATH_IsPathOpen(dclevel)
Definition: path.h:72
#define CONST
Definition: pedump.c:81
WORD * PWORD
Definition: pedump.c:67
BYTE * PBYTE
Definition: pedump.c:66
DWORD * PDWORD
Definition: pedump.c:68
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define INT
Definition: polytest.cpp:20
#define MmCopyFromCaller
Definition: polytest.cpp:29
#define EngFreeMem
Definition: polytest.cpp:56
#define FL_ZERO_MEMORY
Definition: polytest.cpp:58
void * EngAllocMem(int zero, unsigned long size, int tag=0)
Definition: polytest.cpp:70
static const WCHAR szName[]
Definition: powrprof.c:45
_In_opt_ _In_opt_ _In_ _In_ DWORD cbData
Definition: shlwapi.h:761
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:181
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:184
#define long
Definition: qsort.c:33
PVOID pBuffer
#define REG_DWORD
Definition: sdbapi.c:615
#define LANG_ENGLISH
Definition: nls.h:52
#define PRIMARYLANGID(l)
Definition: nls.h:16
wcscat
wcscpy
#define memset(x, y, z)
Definition: compat.h:39
NTSTATUS NTAPI MmMapViewInSystemSpace(IN PVOID SectionObject, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:4498
NTSTATUS NTAPI MmCreateSection(OUT PVOID *Section, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL, IN PFILE_OBJECT FileObject OPTIONAL)
Definition: section.c:4671
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define DPRINT
Definition: sndvol32.h:73
#define _countof(array)
Definition: sndvol32.h:70
static void Exit(void)
Definition: sock.c:1330
#define __kernel_entry
Definition: specstrings.h:355
Definition: fatfs.h:173
Definition: polytest.cpp:41
base for all directory entries
Definition: entries.h:138
base of all file and directory entries
Definition: entries.h:83
Definition: font.h:77
UNICODE_STRING FontNames[FONTSUBST_FROM_AND_TO]
Definition: font.h:79
BYTE CharSets[FONTSUBST_FROM_AND_TO]
Definition: font.h:80
UNICODE_STRING FullNameW
Definition: freetype.c:3061
UNICODE_STRING FamilyNameW
Definition: freetype.c:3058
UNICODE_STRING FaceNameW
Definition: freetype.c:3059
ULONG OtmSize
Definition: freetype.c:3062
UNICODE_STRING StyleNameW
Definition: freetype.c:3060
FT_Pos xMin
Definition: ftimage.h:120
FT_Pos yMax
Definition: ftimage.h:121
FT_Pos yMin
Definition: ftimage.h:120
FT_Pos xMax
Definition: ftimage.h:121
FT_Bitmap bitmap
Definition: ftglyph.h:172
FT_GlyphRec root
Definition: ftglyph.h:169
unsigned int width
Definition: ftimage.h:263
unsigned char * buffer
Definition: ftimage.h:265
unsigned char pixel_mode
Definition: ftimage.h:267
unsigned int rows
Definition: ftimage.h:262
int pitch
Definition: ftimage.h:264
FT_Encoding encoding
Definition: freetype.h:820
FT_UShort platform_id
Definition: freetype.h:821
FT_Size size
Definition: freetype.h:1066
FT_Long num_glyphs
Definition: freetype.h:1036
FT_Int num_charmaps
Definition: freetype.h:1044
FT_BBox bbox
Definition: freetype.h:1052
FT_UShort units_per_EM
Definition: freetype.h:1054
FT_CharMap * charmaps
Definition: freetype.h:1045
FT_String * style_name
Definition: freetype.h:1039
FT_Short max_advance_width
Definition: freetype.h:1059
FT_String * family_name
Definition: freetype.h:1038
FT_GlyphSlot glyph
Definition: freetype.h:1065
FT_Long num_faces
Definition: freetype.h:1030
FT_Vector advance
Definition: ftglyph.h:117
FT_Bitmap bitmap
Definition: freetype.h:1886
FT_Outline outline
Definition: freetype.h:1890
FT_Glyph_Metrics metrics
Definition: freetype.h:1879
FT_Glyph_Format format
Definition: freetype.h:1884
FT_Fixed xx
Definition: fttypes.h:392
FT_Fixed yx
Definition: fttypes.h:393
FT_Fixed yy
Definition: fttypes.h:393
FT_Fixed xy
Definition: fttypes.h:392
FT_Size_Metrics metrics
Definition: freetype.h:1636
FT_Fixed y_scale
Definition: freetype.h:1601
FT_Fixed x_scale
Definition: freetype.h:1600
FT_UInt horiResolution
Definition: freetype.h:2607
FT_Size_Request_Type type
Definition: freetype.h:2604
FT_UInt vertResolution
Definition: freetype.h:2608
FT_Pos x
Definition: ftimage.h:77
FT_Pos y
Definition: ftimage.h:78
FT_UShort horizontal_resolution
Definition: ftwinfnt.h:191
FT_Byte pitch_and_family
Definition: ftwinfnt.h:202
FT_Byte default_char
Definition: ftwinfnt.h:207
FT_UShort internal_leading
Definition: ftwinfnt.h:193
FT_UShort avg_width
Definition: ftwinfnt.h:203
FT_UShort external_leading
Definition: ftwinfnt.h:194
FT_UShort ascent
Definition: ftwinfnt.h:192
FT_UShort weight
Definition: ftwinfnt.h:198
FT_UShort max_width
Definition: ftwinfnt.h:204
FT_UShort pixel_height
Definition: ftwinfnt.h:201
FT_UShort vertical_resolution
Definition: ftwinfnt.h:190
PUNICODE_STRING pFileName
Definition: font.h:86
PFONT_ENTRY_MEM PrivateEntry
Definition: font.h:92
PSHARED_MEM Memory
Definition: font.h:87
UNICODE_STRING RegValueName
Definition: font.h:89
BOOL IsTrueType
Definition: font.h:90
DWORD Characteristics
Definition: font.h:88
BYTE lfOutPrecision
Definition: dimm.idl:68
BYTE lfStrikeOut
Definition: dimm.idl:66
BYTE lfItalic
Definition: dimm.idl:64
LONG lfHeight
Definition: dimm.idl:59
LONG lfWeight
Definition: dimm.idl:63
WCHAR lfFaceName[LF_FACESIZE]
Definition: dimm.idl:72
LONG lfOrientation
Definition: dimm.idl:62
LONG lfWidth
Definition: dimm.idl:60
BYTE lfUnderline
Definition: dimm.idl:65
BYTE lfClipPrecision
Definition: dimm.idl:69
LONG lfEscapement
Definition: dimm.idl:61
BYTE lfCharSet
Definition: dimm.idl:67
BYTE lfQuality
Definition: dimm.idl:70
BYTE lfPitchAndFamily
Definition: dimm.idl:71
Definition: matrix.h:44
long bottom
Definition: polytest.cpp:53
long right
Definition: polytest.cpp:53
long top
Definition: polytest.cpp:53
long left
Definition: polytest.cpp:53
FT_Short Line_Gap
Definition: tttables.h:205
FT_Short Ascender
Definition: tttables.h:203
FT_Short caret_Slope_Run
Definition: tttables.h:213
FT_Short Descender
Definition: tttables.h:204
FT_Short caret_Slope_Rise
Definition: tttables.h:212
FT_Short sTypoDescender
Definition: tttables.h:407
FT_UShort version
Definition: tttables.h:377
FT_ULong ulUnicodeRange1
Definition: tttables.h:396
FT_ULong ulCodePageRange1
Definition: tttables.h:414
FT_UShort fsSelection
Definition: tttables.h:403
FT_UShort usLastCharIndex
Definition: tttables.h:405
FT_Short ySuperscriptYSize
Definition: tttables.h:387
FT_Short sxHeight
Definition: tttables.h:419
FT_Short yStrikeoutSize
Definition: tttables.h:390
FT_Byte panose[10]
Definition: tttables.h:394
FT_Short ySubscriptXSize
Definition: tttables.h:382
FT_ULong ulUnicodeRange3
Definition: tttables.h:398
FT_Short sTypoLineGap
Definition: tttables.h:408
FT_UShort usWinDescent
Definition: tttables.h:410
FT_Short sTypoAscender
Definition: tttables.h:406
FT_Short ySuperscriptXSize
Definition: tttables.h:386
FT_Short ySubscriptYOffset
Definition: tttables.h:385
FT_ULong ulUnicodeRange2
Definition: tttables.h:397
FT_Short ySuperscriptYOffset
Definition: tttables.h:389
FT_Short ySubscriptXOffset
Definition: tttables.h:384
FT_Short yStrikeoutPosition
Definition: tttables.h:391
FT_Short sCapHeight
Definition: tttables.h:420
FT_ULong ulCodePageRange2
Definition: tttables.h:415
FT_UShort fsType
Definition: tttables.h:381
FT_UShort usWinAscent
Definition: tttables.h:409
FT_ULong ulUnicodeRange4
Definition: tttables.h:399
FT_Short ySuperscriptXOffset
Definition: tttables.h:388
FT_UShort usWeightClass
Definition: tttables.h:379
FT_UShort usDefaultChar
Definition: tttables.h:421
FT_Short xAvgCharWidth
Definition: tttables.h:378
FT_Short ySubscriptYSize
Definition: tttables.h:383
FT_UShort usFirstCharIndex
Definition: tttables.h:404
FT_Short underlineThickness
Definition: tttables.h:455
FT_Short underlinePosition
Definition: tttables.h:454
FLOAT abcfA
Definition: wingdi.h:1862
FLOAT abcfC
Definition: wingdi.h:1864
FLOAT abcfB
Definition: wingdi.h:1863
Definition: wingdi.h:1856
int abcA
Definition: wingdi.h:1857
UINT abcB
Definition: wingdi.h:1858
int abcC
Definition: wingdi.h:1859
POINTL ptlCurrent
Definition: ntgdihdl.h:311
BYTE jBkMode
Definition: ntgdihdl.h:308
INT iGraphicsMode
Definition: ntgdihdl.h:306
HANDLE hlfntNew
Definition: ntgdihdl.h:330
ULONG ulDirty_
Definition: ntgdihdl.h:294
FLONG flTextAlign
Definition: ntgdihdl.h:324
XLATEOBJ xlo
Definition: xlateobj.h:21
WCHAR FileName[ANYSIZE_ARRAY]
Definition: winternl.h:1466
LONG tmInternalLeading
Definition: engobjects.h:164
LPWSTR Filename
Definition: engobjects.h:151
BYTE RequestItalic
Definition: engobjects.h:154
LONG RequestWeight
Definition: engobjects.h:155
LONG lfWidth
Definition: engobjects.h:167
LONG tmAscent
Definition: engobjects.h:162
BYTE RequestStrikeOut
Definition: engobjects.h:153
FLONG flType
Definition: engobjects.h:142
LONG tmDescent
Definition: engobjects.h:163
BYTE OriginalItalic
Definition: engobjects.h:156
BYTE CharSet
Definition: engobjects.h:158
ULONG iUnique
Definition: engobjects.h:141
FONTOBJ FontObj
Definition: engobjects.h:140
PSHARED_FACE SharedFace
Definition: engobjects.h:145
LONG tmHeight
Definition: engobjects.h:161
LONG lfHeight
Definition: engobjects.h:166
LONG OriginalWeight
Definition: engobjects.h:157
BYTE RequestUnderline
Definition: engobjects.h:152
LONG Magic
Definition: engobjects.h:165
ULONG iUniq
Definition: winddi.h:762
FLONG flFontType
Definition: winddi.h:765
Definition: font.h:56
FT_BitmapGlyph BitmapGlyph
Definition: font.h:58
LIST_ENTRY ListEntry
Definition: font.h:57
FONT_CACHE_HASHED Hashed
Definition: font.h:60
DWORD dwHash
Definition: font.h:59
LONG lfHeight
Definition: font.h:44
LONG lfWidth
Definition: font.h:45
INT GlyphIndex
Definition: font.h:42
FT_Face Face
Definition: font.h:43
FT_Matrix matTransform
Definition: font.h:50
DWORD AspectValue
Definition: font.h:47
Definition: font.h:20
FONT_ENTRY_MEM * Entry
Definition: font.h:23
LIST_ENTRY ListEntry
Definition: font.h:21
HANDLE Handle
Definition: font.h:22
Definition: font.h:14
LIST_ENTRY ListEntry
Definition: font.h:15
FONT_ENTRY * Entry
Definition: font.h:16
Definition: font.h:5
FONTGDI * Font
Definition: font.h:7
UNICODE_STRING StyleName
Definition: font.h:9
UNICODE_STRING FaceName
Definition: font.h:8
LIST_ENTRY ListEntry
Definition: font.h:6
PSHARED_FACE SharedFace
Definition: freetype.c:294
LIST_ENTRY ListEntry
Definition: freetype.c:292
FONTOBJ * pFontObj
Definition: freetype.c:295
LOGFONTW LogFont
Definition: freetype.c:293
short gmCellIncX
Definition: wingdi.h:2891
UINT gmBlackBoxY
Definition: wingdi.h:2889
UINT gmBlackBoxX
Definition: wingdi.h:2888
short gmCellIncY
Definition: wingdi.h:2892
POINT gmptGlyphOrigin
Definition: wingdi.h:2890
Definition: text.h:60
BASEOBJECT BaseObject
Definition: text.h:63
FLONG fl
Definition: text.h:65
WCHAR TextFace[LF_FACESIZE]
Definition: text.h:67
ENUMLOGFONTEXDVW logfont
Definition: text.h:70
FONTOBJ * Font
Definition: text.h:66
EX_PUSH_LOCK lock
Definition: text.h:71
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: wingdi.h:2918
FIXED eM22
Definition: wingdi.h:2922
FIXED eM21
Definition: wingdi.h:2921
FIXED eM11
Definition: wingdi.h:2919
FIXED eM12
Definition: wingdi.h:2920
UNICODE_STRING Name
Definition: nt_native.h:1273
PANOSE otmPanoseNumber
Definition: wingdi.h:2962
POINT otmptSuperscriptOffset
Definition: wingdi.h:2982
POINT otmptSuperscriptSize
Definition: wingdi.h:2981
POINT otmptSubscriptSize
Definition: wingdi.h:2979
int otmsStrikeoutPosition
Definition: wingdi.h:2984
int otmsUnderscorePosition
Definition: wingdi.h:2986
TEXTMETRICW otmTextMetrics
Definition: wingdi.h:2960
POINT otmptSubscriptOffset
Definition: wingdi.h:2980
UINT otmsStrikeoutSize
Definition: wingdi.h:2983
LONG y
Definition: windef.h:130
LONG x
Definition: windef.h:129
LIST_ENTRY PrivateMemFontListHead
Definition: win32.h:286
UINT PrivateMemFontHandleCount
Definition: win32.h:287
LIST_ENTRY PrivateFontListHead
Definition: win32.h:285
FT_Face Face
Definition: engobjects.h:132
SHARED_FACE_CACHE UserLanguage
Definition: engobjects.h:136
SHARED_FACE_CACHE EnglishUS
Definition: engobjects.h:135
ULONG BufferSize
Definition: engobjects.h:120
PVOID Buffer
Definition: engobjects.h:119
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
BOOL bFontSmoothing
Definition: sysparams.h:125
UINT uiFontSmoothingType
Definition: sysparams.h:126
SURFOBJ SurfObj
Definition: surface.h:8
struct _PALETTE *const ppal
Definition: surface.h:11
TEXTMETRICW TextMetric
Definition: ntgdityp.h:370
USHORT MaximumLength
Definition: env_spec_w32.h:370
FLOATL eM11
Definition: winddi.h:1234
Definition: inflate.c:139
char * value
Definition: compiler.c:67
Definition: ffs.h:70
Definition: mesh.c:5330
Definition: ps.c:97
FONTSIGNATURE fs
Definition: wingdi.h:1994
UINT ciCharset
Definition: wingdi.h:1992
ENUMLOGFONTEXW elfEnumLogfontEx
Definition: wingdi.h:3225
WCHAR elfStyle[LF_FACESIZE]
Definition: wingdi.h:3150
LOGFONTW elfLogFont
Definition: wingdi.h:3148
WCHAR elfFullName[LF_FULLFACESIZE]
Definition: wingdi.h:3149
ENUMLOGFONTEXW EnumLogFontEx
Definition: ntgdibad.h:47
DWORD fsCsb[2]
Definition: wingdi.h:1989
WORD wSecond
Definition: wingdi.h:2911
int iKernAmount
Definition: wingdi.h:2912
LONG lfWidth
Definition: wingdi.h:2344
BYTE lfCharSet
Definition: wingdi.h:2351
WCHAR lfFaceName[LF_FACESIZE]
Definition: wingdi.h:2356
UINT ntmCellHeight
Definition: wingdi.h:3112
WCHAR tmFirstChar
Definition: wingdi.h:3101
LONG tmDigitizedAspectX
Definition: wingdi.h:3099
LONG tmInternalLeading
Definition: wingdi.h:3093
WCHAR tmDefaultChar
Definition: wingdi.h:3103
LONG tmMaxCharWidth
Definition: wingdi.h:3096
LONG tmAveCharWidth
Definition: wingdi.h:3095
WCHAR tmBreakChar
Definition: wingdi.h:3104
LONG tmExternalLeading
Definition: wingdi.h:3094
LONG tmDigitizedAspectY
Definition: wingdi.h:3100
BYTE tmPitchAndFamily
Definition: wingdi.h:3108
WCHAR tmLastChar
Definition: wingdi.h:3102
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG right
Definition: windef.h:108
LONG bottom
Definition: windef.h:109
LONG top
Definition: windef.h:107
LONG left
Definition: windef.h:106
WCHAR tmFirstChar
Definition: wingdi.h:2840
LONG tmDigitizedAspectX
Definition: wingdi.h:2838
LONG tmDigitizedAspectY
Definition: wingdi.h:2839
LONG tmOverhang
Definition: wingdi.h:2837
LONG tmAveCharWidth
Definition: wingdi.h:2834
LONG tmAscent
Definition: wingdi.h:2830
LONG tmMaxCharWidth
Definition: wingdi.h:2835
BYTE tmItalic
Definition: wingdi.h:2844
BYTE tmStruckOut
Definition: wingdi.h:2846
LONG tmInternalLeading
Definition: wingdi.h:2832
BYTE tmUnderlined
Definition: wingdi.h:2845
LONG tmExternalLeading
Definition: wingdi.h:2833
BYTE tmPitchAndFamily
Definition: wingdi.h:2847
LONG tmWeight
Definition: wingdi.h:2836
WCHAR tmBreakChar
Definition: wingdi.h:2843
WCHAR tmDefaultChar
Definition: wingdi.h:2842
BYTE tmCharSet
Definition: wingdi.h:2848
WCHAR tmLastChar
Definition: wingdi.h:2841
LONG tmHeight
Definition: wingdi.h:2829
LONG tmDescent
Definition: wingdi.h:2831
POINTFX apfx[1]
Definition: wingdi.h:3160
POINTFX pfxStart
Definition: wingdi.h:3165
#define max(a, b)
Definition: svc.c:63
FT_Get_PS_Font_Info(FT_Face face, PS_FontInfo afont_info)
FT_BEGIN_HEADER struct PS_FontInfoRec_ PS_FontInfoRec
T1_FIELD_DICT_FONTDICT family_name
Definition: t1tokens.h:30
T1_FIELD_DICT_FONTDICT T1_FIELD_DICT_FONTDICT T1_FIELD_DICT_FONTDICT underline_position
Definition: t1tokens.h:40
FT_Get_Sfnt_Table(FT_Face face, FT_Sfnt_Tag tag)
Definition: ftobjs.c:4176
#define ft_sfnt_post
Definition: tttables.h:641
FT_Load_Sfnt_Table(FT_Face face, FT_ULong tag, FT_Long offset, FT_Byte *buffer, FT_ULong *length)
Definition: ftobjs.c:4197
#define ft_sfnt_hhea
Definition: tttables.h:639
@ FT_SFNT_HHEA
Definition: tttables.h:625
@ FT_SFNT_POST
Definition: tttables.h:627
@ FT_SFNT_OS2
Definition: tttables.h:624
#define ft_sfnt_os2
Definition: tttables.h:638
#define TTAG_CFF
Definition: tttags.h:44
#define LL
Definition: tui.h:166
uint16_t * PWSTR
Definition: typedefs.h:56
#define MAXULONG
Definition: typedefs.h:251
const uint16_t * PCWSTR
Definition: typedefs.h:57
unsigned char * LPBYTE
Definition: typedefs.h:53
int64_t LONGLONG
Definition: typedefs.h:68
uint16_t * LPWORD
Definition: typedefs.h:56
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
#define MAKELONG(a, b)
Definition: typedefs.h:249
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define OUT
Definition: typedefs.h:40
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_NO_MORE_FILES
Definition: udferr_usr.h:128
LONGLONG QuadPart
Definition: typedefs.h:114
Definition: compat.h:2255
WORD WORD PSZ PSZ pszFileName
Definition: vdmdbg.h:44
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2439
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _In_ _Strict_type_match_ POOL_TYPE _In_opt_ ULONG _In_ _Out_ WDFMEMORY * Memory
Definition: wdfmemory.h:169
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_opt_ PWDF_OBJECT_ATTRIBUTES _In_ WDFCOLLECTION Collection
Definition: wdfregistry.h:374
_Must_inspect_result_ _In_ WDFUSBDEVICE _In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_writes_opt_ NumCharacters PUSHORT _Inout_ PUSHORT _In_ UCHAR _In_opt_ USHORT LangID
Definition: wdfusb.h:1083
NTSTATUS IntDuplicateUnicodeString(IN ULONG Flags, IN PCUNICODE_STRING SourceString, OUT PUNICODE_STRING DestinationString)
Definition: registry.c:361
BOOL APIENTRY IntEngMaskBlt(_Inout_ SURFOBJ *psoDest, _In_ SURFOBJ *psoMask, _In_ CLIPOBJ *pco, _In_ XLATEOBJ *pxloDest, _In_ XLATEOBJ *pxloSource, _In_ RECTL *prclDest, _In_ POINTL *pptlMask, _In_ BRUSHOBJ *pbo, _In_ POINTL *pptlBrushOrg)
Definition: bitblt.c:1103
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:31
PTEXTOBJ FASTCALL RealizeFontInit(_In_ HFONT hFont)
Definition: font.c:433
USHORT gusLanguageID
Definition: init.c:12
PALETTE gpalRGB
Definition: palette.c:20
BOOL FASTCALL PATH_ExtTextOut(PDC dc, INT x, INT y, UINT flags, const RECTL *lprc, LPCWSTR str, UINT count, const INT *dx)
Definition: path.c:2357
#define TAG_FINF
Definition: text.h:3
#define AFRX_WRITE_REGISTRY
Definition: text.h:104
#define LFONT_UnlockFont(plfnt)
Definition: text.h:79
FORCEINLINE PTEXTOBJ TEXTOBJ_LockText(HFONT hfont)
Definition: text.h:83
#define AFRX_DOS_DEVICE_PATH
Definition: text.h:106
#define TEXTOBJECT_INIT
Definition: text.h:56
#define AFRX_ALTERNATIVE_PATH
Definition: text.h:105
#define IntLockProcessPrivateFonts(W32Process)
Definition: text.h:164
FORCEINLINE VOID TEXTOBJ_UnlockText(PLFONT plfnt)
Definition: text.h:96
#define IntUnLockProcessPrivateFonts(W32Process)
Definition: text.h:167
#define LFONT_AllocFontWithHandle()
Definition: text.h:76
VOID APIENTRY IntEngFillPolygon(IN OUT PDC dc, IN POINTL *pPoints, IN UINT cPoints, IN BRUSHOBJ *BrushObj)
Definition: utils.c:254
VOID IntSwapEndian(_Inout_ LPVOID pvData, _In_ DWORD Size)
Definition: utils.c:125
VOID IntRebaseList(_Inout_ PLIST_ENTRY pNewHead, _Inout_ PLIST_ENTRY pOldHead)
Definition: utils.c:30
VOID IntUnicodeStringToBuffer(_Out_ LPWSTR pszBuffer, _In_ SIZE_T cbBuffer, _In_ const UNICODE_STRING *pString)
Definition: utils.c:165
SIZE_T SZZ_GetSize(_In_ PCZZWSTR pszz)
Definition: utils.c:15
LPCWSTR FASTCALL IntNameFromCharSet(_In_ BYTE CharSet)
Definition: utils.c:54
BYTE IntCharSetFromLangID(_In_ LANGID LangID)
Definition: utils.c:82
LONG IntNormalizeAngle(_In_ LONG nTenthsOfDegrees)
Definition: utils.c:46
VOID FASTCALL IntEngFillBox(IN OUT PDC dc, IN INT X, IN INT Y, IN INT Width, IN INT Height, IN BRUSHOBJ *BrushObj)
Definition: utils.c:209
POINTL g_PointZero
Definition: utils.c:12
static DWORD Utf32FromSurrogatePair(_In_ DWORD ch0, _In_ DWORD ch1)
Definition: utils.h:47
SPIVALUES gspv
Definition: sysparams.c:17
#define TAG_INTERNAL_SYNC
Definition: tags.h:18
#define TAG_FONT
Definition: tags.h:12
#define GDITAG_RFONT
Definition: tags.h:92
#define GDITAG_PFF
Definition: tags.h:149
#define GDITAG_TEXT
Definition: tags.h:172
#define FLOATOBJ_DivLong(pf, l)
Definition: winddi.h:2829
#define BMF_8BPP
Definition: winddi.h:357
ENGAPI BOOL APIENTRY EngDeleteSurface(_In_ _Post_ptr_invalid_ HSURF hsurf)
Definition: surface.c:567
_In_ FLONG fl
Definition: winddi.h:1279
_In_ DWORD cjBuf
Definition: winddi.h:3827
#define FO_TYPE_TRUETYPE
Definition: winddi.h:737
ENGAPI SURFOBJ *APIENTRY EngLockSurface(_In_ HSURF hsurf)
Definition: surface.c:607
_In_ ULONG_PTR _In_ ULONG iFace
Definition: winddi.h:3836
FLOAT FLOATOBJ
Definition: winddi.h:677
ENGAPI HBITMAP APIENTRY EngCreateBitmap(_In_ SIZEL sizl, _In_ LONG lWidth, _In_ ULONG iFormat, _In_ FLONG fl, _In_opt_ PVOID pvBits)
#define FO_CFF
Definition: winddi.h:747
#define FLOATOBJ_Mul(pf, pf1)
Definition: winddi.h:2824
_In_ ULONG iMode
Definition: winddi.h:3520
ENGAPI VOID APIENTRY EngGetCurrentCodePage(_Out_ PUSHORT OemCodePage, _Out_ PUSHORT AnsiCodePage)
Definition: engmisc.c:232
#define FLOATOBJ_MulLong(pf, l)
Definition: winddi.h:2826
#define BMF_TOPDOWN
Definition: winddi.h:1180
#define FLOATOBJ_GetLong(pf)
Definition: winddi.h:2817
#define FLOATOBJ_SetFloat(pf, f)
Definition: winddi.h:2814
typedef HSURF(APIENTRY FN_DrvEnableSurface)(_In_ DHPDEV dhpdev)
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:22
#define FLOATOBJ_SetLong(pf, l)
Definition: winddi.h:2815
#define FO_MULTIPLEMASTER
Definition: winddi.h:749
#define FO_POSTSCRIPT
Definition: winddi.h:748
_In_ SIZEL _In_ ULONG iFormat
Definition: winddi.h:3468
ENGAPI VOID APIENTRY EngUnlockSurface(_In_ _Post_ptr_invalid_ SURFOBJ *pso)
Definition: surface.c:628
#define FLOATOBJ_AddLong(pf, l)
Definition: winddi.h:2820
#define FO_VERT_FACE
Definition: winddi.h:750
#define FO_TYPE_RASTER
Definition: winddi.h:735
struct _FILE_DIRECTORY_INFORMATION * PFILE_DIRECTORY_INFORMATION
#define ERROR_GEN_FAILURE
Definition: winerror.h:256
#define FS_TURKISH
Definition: wingdi.h:564
#define FIXED_PITCH
Definition: wingdi.h:444
#define DEFAULT_PITCH
Definition: wingdi.h:443
#define NTM_ITALIC
Definition: wingdi.h:1315
#define TT_ENABLED
Definition: wingdi.h:889
#define PAN_SERIF_THIN
Definition: wingdi.h:476
struct _OUTLINETEXTMETRICW OUTLINETEXTMETRICW
#define VARIABLE_PITCH
Definition: wingdi.h:445
struct _ABCFLOAT * LPABCFLOAT
#define PAN_FAMILY_TEXT_DISPLAY
Definition: wingdi.h:467
#define PAN_PROP_MONOSPACED
Definition: wingdi.h:502
#define RUSSIAN_CHARSET
Definition: wingdi.h:396
#define FS_JOHAB
Definition: wingdi.h:574
#define FW_DONTCARE
Definition: wingdi.h:368
#define ANTIALIASED_QUALITY
Definition: wingdi.h:440
#define PAN_SERIFSTYLE_INDEX
Definition: wingdi.h:455
#define FF_MODERN
Definition: wingdi.h:449
#define FF_DECORATIVE
Definition: wingdi.h:447
#define PAN_SERIF_NORMAL_SANS
Definition: wingdi.h:480
#define FS_THAI
Definition: wingdi.h:569
#define GGO_GRAY2_BITMAP
Definition: wingdi.h:852
#define FS_ARABIC
Definition: wingdi.h:566
#define FF_SCRIPT
Definition: wingdi.h:451
#define FS_WANSUNG
Definition: wingdi.h:572
#define GM_ADVANCED
Definition: wingdi.h:865
#define PAN_SERIF_BONE
Definition: wingdi.h:477
#define FF_ROMAN
Definition: wingdi.h:450
struct _RASTERIZER_STATUS RASTERIZER_STATUS
#define PAN_SERIF_OBTUSE_SANS
Definition: wingdi.h:481
#define PAN_FAMILY_PICTORIAL
Definition: wingdi.h:470
#define TA_UPDATECP
Definition: wingdi.h:936
#define FF_DONTCARE
Definition: wingdi.h:448
#define TRUETYPE_FONTTYPE
Definition: wingdi.h:1109
#define FS_LATIN2
Definition: wingdi.h:561
#define PAN_SERIF_TRIANGLE
Definition: wingdi.h:479
#define FS_VIETNAMESE
Definition: wingdi.h:568
#define ARABIC_CHARSET
Definition: wingdi.h:394
#define HANGEUL_CHARSET
Definition: wingdi.h:387
#define TA_RIGHT
Definition: wingdi.h:933
#define TT_PRIM_CSPLINE
Definition: wingdi.h:1321
#define FS_GREEK
Definition: wingdi.h:563
#define PANOSE_COUNT
Definition: wingdi.h:453
#define TT_POLYGON_TYPE
Definition: wingdi.h:1318
#define OUT_DEVICE_PRECIS
Definition: wingdi.h:420
#define DEFAULT_CHARSET
Definition: wingdi.h:384
#define THAI_CHARSET
Definition: wingdi.h:397
#define TMPF_TRUETYPE
Definition: wingdi.h:1313
#define DRAFT_QUALITY
Definition: wingdi.h:437
#define PAN_PROPORTION_INDEX
Definition: wingdi.h:457
#define RASTER_FONTTYPE
Definition: wingdi.h:1107
#define PAN_NO_FIT
Definition: wingdi.h:466
#define GREEK_CHARSET
Definition: wingdi.h:391
#define TT_PRIM_QSPLINE
Definition: wingdi.h:1320
#define PAN_SERIF_SQUARE_COVE
Definition: wingdi.h:473
#define PAN_SERIF_SQUARE
Definition: wingdi.h:475
#define JOHAB_CHARSET
Definition: wingdi.h:401
#define TCI_SRCLOCALE
Definition: wingdi.h:964
#define ETO_CLIPPED
Definition: wingdi.h:648
#define FS_HEBREW
Definition: wingdi.h:565
#define FS_SYMBOL
Definition: wingdi.h:575
#define TMPF_DEVICE
Definition: wingdi.h:1314
#define PAN_SERIF_OBTUSE_SQUARE_COVE
Definition: wingdi.h:474
#define PAN_SERIF_COVE
Definition: wingdi.h:471
#define CHINESEBIG5_CHARSET
Definition: wingdi.h:390
#define TMPF_VECTOR
Definition: wingdi.h:1312
#define PAN_SERIF_EXAGGERATED
Definition: wingdi.h:478
#define OUT_DEFAULT_PRECIS
Definition: wingdi.h:415
#define GGO_GLYPH_INDEX
Definition: wingdi.h:855
#define ETO_OPAQUE
Definition: wingdi.h:647
#define OPAQUE
Definition: wingdi.h:949
#define NTM_REGULAR
Definition: wingdi.h:1317
#define PAN_SERIF_ROUNDED
Definition: wingdi.h:484
#define ANSI_CHARSET
Definition: wingdi.h:383
#define PROOF_QUALITY
Definition: wingdi.h:438
#define OUT_TT_PRECIS
Definition: wingdi.h:419
#define FS_LATIN1
Definition: wingdi.h:560
#define GDI_ERROR
Definition: wingdi.h:1309
#define TCI_SRCCHARSET
Definition: wingdi.h:961
#define GGO_UNHINTED
Definition: wingdi.h:856
#define PAN_FAMILYTYPE_INDEX
Definition: wingdi.h:454
#define FS_JISJAPAN
Definition: wingdi.h:570
#define FS_CHINESETRAD
Definition: wingdi.h:573
#define FS_CHINESESIMP
Definition: wingdi.h:571
#define GGO_GRAY8_BITMAP
Definition: wingdi.h:854
#define ETO_PDY
Definition: wingdi.h:657
#define CLIP_DEFAULT_PRECIS
Definition: wingdi.h:426
#define OEM_CHARSET
Definition: wingdi.h:400
#define TT_AVAILABLE
Definition: wingdi.h:888
#define PAN_FAMILY_DECORATIVE
Definition: wingdi.h:469
#define TA_BOTTOM
Definition: wingdi.h:929
#define PAN_SERIF_PERP_SANS
Definition: wingdi.h:482
#define FW_NORMAL
Definition: wingdi.h:373
#define VIETNAMESE_CHARSET
Definition: wingdi.h:402
#define TA_BASELINE
Definition: wingdi.h:928
#define GGO_BITMAP
Definition: wingdi.h:849
struct _ABC ABC
#define GGO_GRAY4_BITMAP
Definition: wingdi.h:853
#define NTM_BOLD
Definition: wingdi.h:1316
#define PAN_SERIF_FLARED
Definition: wingdi.h:483
#define TA_CENTER
Definition: wingdi.h:931
#define PAN_FAMILY_SCRIPT
Definition: wingdi.h:468
#define GGO_NATIVE
Definition: wingdi.h:850
#define MAC_CHARSET
Definition: wingdi.h:403
#define CLEARTYPE_QUALITY
Definition: wingdi.h:441
#define PAN_SERIF_OBTUSE_COVE
Definition: wingdi.h:472
#define TT_PRIM_LINE
Definition: wingdi.h:1319
#define HEBREW_CHARSET
Definition: wingdi.h:393
#define SHIFTJIS_CHARSET
Definition: wingdi.h:386
#define PAN_ANY
Definition: wingdi.h:465
#define FS_BALTIC
Definition: wingdi.h:567
#define GGO_METRICS
Definition: wingdi.h:848
#define FF_SWISS
Definition: wingdi.h:452
#define SYMBOL_CHARSET
Definition: wingdi.h:385
#define GGI_MARK_NONEXISTING_GLYPHS
Definition: wingdi.h:1085
#define EASTEUROPE_CHARSET
Definition: wingdi.h:399
#define GGO_BEZIER
Definition: wingdi.h:851
#define GB2312_CHARSET
Definition: wingdi.h:389
#define TCI_SRCFONTSIG
Definition: wingdi.h:963
#define NONANTIALIASED_QUALITY
Definition: wingdi.h:439
#define FS_CYRILLIC
Definition: wingdi.h:562
#define BALTIC_CHARSET
Definition: wingdi.h:395
#define TCI_SRCCODEPAGE
Definition: wingdi.h:962
#define TURKISH_CHARSET
Definition: wingdi.h:392
#define OUT_OUTLINE_PRECIS
Definition: wingdi.h:423
#define IS_HIGH_SURROGATE(ch)
Definition: winnls.h:752
#define IS_LOW_SURROGATE(ch)
Definition: winnls.h:753
#define RegOpenKey
Definition: winreg.h:551
#define RegQueryValue
Definition: winreg.h:555
_In_ int _Inout_ LPRECT lprc
Definition: winuser.h:4568
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
* PFAST_MUTEX
Definition: extypes.h:17
FAST_MUTEX
Definition: extypes.h:17
* PFILE_OBJECT
Definition: iotypes.h:1998
#define ObDereferenceObject
Definition: obfuncs.h:203
_In_ PSTRING FullName
Definition: rtlfuncs.h:1665
#define RTL_STATIC_LIST_HEAD(x)
Definition: rtlfuncs.h:47
#define XFORMOBJ_vInit
Definition: xformobj.h:12
#define XFORMOBJ_iGetXform
Definition: xformobj.h:9
VOID NTAPI EXLATEOBJ_vInitialize(_Out_ PEXLATEOBJ pexlo, _In_opt_ PALETTE *ppalSrc, _In_opt_ PALETTE *ppalDst, _In_ COLORREF crSrcBackColor, _In_ COLORREF crDstBackColor, _In_ COLORREF crDstForeColor)
Definition: xlateobj.c:491
VOID NTAPI EXLATEOBJ_vCleanup(_Inout_ PEXLATEOBJ pexlo)
Definition: xlateobj.c:894
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
char * LPSTR
Definition: xmlstorage.h:182
unsigned char BYTE
Definition: xxhash.c:193