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