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