ReactOS 0.4.16-dev-981-g80eb313
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 = FALSE;
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
2089/* Adds the font resource from the specified file to the system */
2090static INT FASTCALL
2093 _In_ DWORD Characteristics,
2095{
2098 PVOID Buffer = NULL;
2101 SIZE_T ViewSize = 0, Length;
2102 LARGE_INTEGER SectionSize;
2105 INT FontCount;
2107 UNICODE_STRING PathName;
2108 LPWSTR pszBuffer;
2110 static const UNICODE_STRING TrueTypePostfix = RTL_CONSTANT_STRING(L" (TrueType)");
2111 static const UNICODE_STRING DosPathPrefix = RTL_CONSTANT_STRING(L"\\??\\");
2112
2113 /* Build PathName */
2115 {
2116 Length = DosPathPrefix.Length + FileName->Length + sizeof(UNICODE_NULL);
2118 if (!pszBuffer)
2119 return 0; /* failure */
2120
2121 RtlInitEmptyUnicodeString(&PathName, pszBuffer, Length);
2122 RtlAppendUnicodeStringToString(&PathName, &DosPathPrefix);
2124 }
2125 else
2126 {
2128 if (!NT_SUCCESS(Status))
2129 return 0; /* failure */
2130 }
2131
2132 /* Open the font file */
2136 &FileHandle,
2139 &Iosb,
2142 if (!NT_SUCCESS(Status))
2143 {
2144 DPRINT1("Could not load font file: %wZ\n", &PathName);
2145 RtlFreeUnicodeString(&PathName);
2146 return 0;
2147 }
2148
2151 if (!NT_SUCCESS(Status))
2152 {
2153 DPRINT1("ObReferenceObjectByHandle failed.\n");
2155 RtlFreeUnicodeString(&PathName);
2156 return 0;
2157 }
2158
2159 SectionSize.QuadPart = 0LL;
2162 NULL, &SectionSize, PAGE_READONLY,
2164 if (!NT_SUCCESS(Status))
2165 {
2166 DPRINT1("Could not map file: %wZ\n", &PathName);
2169 RtlFreeUnicodeString(&PathName);
2170 return 0;
2171 }
2173
2175 if (!NT_SUCCESS(Status))
2176 {
2177 DPRINT1("Could not map file: %wZ\n", &PathName);
2180 RtlFreeUnicodeString(&PathName);
2181 return 0;
2182 }
2183
2184 RtlZeroMemory(&LoadFont, sizeof(LoadFont));
2185 LoadFont.pFileName = &PathName;
2187 LoadFont.Characteristics = Characteristics;
2188 RtlInitUnicodeString(&LoadFont.RegValueName, NULL);
2189 LoadFont.CharSet = DEFAULT_CHARSET;
2190 FontCount = IntGdiLoadFontByIndexFromMemory(&LoadFont, -1);
2191
2192 /* Release our copy */
2196
2198
2200
2201 /* Save the loaded font name into the registry */
2202 if (FontCount > 0 && (dwFlags & AFRX_WRITE_REGISTRY))
2203 {
2204 UNICODE_STRING NewString;
2205 SIZE_T Length;
2206 PWCHAR pszBuffer;
2207 LPCWSTR CharSetName;
2208 if (LoadFont.IsTrueType)
2209 {
2210 /* Append " (TrueType)" */
2211 Length = LoadFont.RegValueName.Length + TrueTypePostfix.Length + sizeof(UNICODE_NULL);
2213 if (pszBuffer)
2214 {
2215 RtlInitEmptyUnicodeString(&NewString, pszBuffer, Length);
2216 NewString.Buffer[0] = UNICODE_NULL;
2217 RtlAppendUnicodeStringToString(&NewString, &LoadFont.RegValueName);
2218 RtlAppendUnicodeStringToString(&NewString, &TrueTypePostfix);
2219 RtlFreeUnicodeString(&LoadFont.RegValueName);
2220 LoadFont.RegValueName = NewString;
2221 }
2222 else
2223 {
2224 // FIXME!
2225 }
2226 }
2227 else if (LoadFont.CharSet != DEFAULT_CHARSET)
2228 {
2229 /* Append " (CharSetName)" */
2230 CharSetName = NameFromCharSet(LoadFont.CharSet);
2231 Length = LoadFont.RegValueName.Length +
2232 (wcslen(CharSetName) + 3) * sizeof(WCHAR) +
2233 sizeof(UNICODE_NULL);
2234
2236 if (pszBuffer)
2237 {
2238 RtlInitEmptyUnicodeString(&NewString, pszBuffer, Length);
2239 NewString.Buffer[0] = UNICODE_NULL;
2240 RtlAppendUnicodeStringToString(&NewString, &LoadFont.RegValueName);
2241 RtlAppendUnicodeToString(&NewString, L" (");
2242 RtlAppendUnicodeToString(&NewString, CharSetName);
2243 RtlAppendUnicodeToString(&NewString, L")");
2244 RtlFreeUnicodeString(&LoadFont.RegValueName);
2245 LoadFont.RegValueName = NewString;
2246 }
2247 else
2248 {
2249 // FIXME!
2250 }
2251 }
2252
2255 NULL, NULL);
2256 Status = ZwOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes);
2257 if (NT_SUCCESS(Status))
2258 {
2260 LPWSTR pFileName;
2261
2263 {
2264 pFileName = PathName.Buffer;
2265 }
2266 else
2267 {
2268 pFileName = wcsrchr(PathName.Buffer, L'\\');
2269 }
2270
2271 if (pFileName)
2272 {
2274 {
2275 pFileName++;
2276 }
2277 DataSize = (wcslen(pFileName) + 1) * sizeof(WCHAR);
2278 ZwSetValueKey(KeyHandle, &LoadFont.RegValueName, 0, REG_SZ,
2279 pFileName, DataSize);
2280 }
2282 }
2283 }
2284 RtlFreeUnicodeString(&LoadFont.RegValueName);
2285
2286 RtlFreeUnicodeString(&PathName);
2287 return FontCount;
2288}
2289
2293 _In_ DWORD cFiles,
2294 _In_ DWORD Characteristics,
2296{
2297 PWSTR pchFile = FileName->Buffer;
2298 SIZE_T cchFile;
2299 INT ret = 0;
2300
2301 while (cFiles--)
2302 {
2303 _SEH2_TRY
2304 {
2305 cchFile = wcslen(pchFile);
2306 }
2308 {
2309 _SEH2_YIELD(return FALSE);
2310 }
2311 _SEH2_END;
2312
2313 UNICODE_STRING ustrPathName;
2314 ustrPathName.Length = (USHORT)(cchFile * sizeof(WCHAR));
2315 ustrPathName.MaximumLength = ustrPathName.Length + sizeof(WCHAR);
2316 ustrPathName.Buffer = pchFile;
2317
2318 INT count = IntGdiAddFontResourceSingle(&ustrPathName, Characteristics, dwFlags);
2319 if (!count)
2320 return 0;
2321 ret += count;
2322
2323 pchFile += cchFile + 1;
2324 }
2325
2326 return ret;
2327}
2328
2329static BOOL FASTCALL
2333{
2334 return FALSE; // FIXME
2335}
2336
2340 _In_ DWORD cFiles,
2342{
2343 PWSTR pchFile = FileName->Buffer;
2344 SIZE_T cchFile;
2345
2346 while (cFiles--)
2347 {
2348 _SEH2_TRY
2349 {
2350 cchFile = wcslen(pchFile);
2351 }
2353 {
2354 _SEH2_YIELD(return FALSE);
2355 }
2356 _SEH2_END;
2357
2358 UNICODE_STRING ustrPathName;
2359 ustrPathName.Length = (USHORT)(cchFile * sizeof(WCHAR));
2360 ustrPathName.MaximumLength = ustrPathName.Length + sizeof(WCHAR);
2361 ustrPathName.Buffer = pchFile;
2362
2364 if (!ret)
2365 return FALSE;
2366
2367 pchFile += cchFile + 1;
2368 }
2369
2370 return TRUE;
2371}
2372
2373/* Borrowed from shlwapi!PathIsRelativeW */
2375{
2376 if (!lpszPath || !*lpszPath)
2377 return TRUE;
2378 if (*lpszPath == L'\\' || (*lpszPath && lpszPath[1] == L':'))
2379 return FALSE;
2380 return TRUE;
2381}
2382
2385{
2389 KEY_FULL_INFORMATION KeyFullInfo;
2390 ULONG i, Length;
2391 UNICODE_STRING FontTitleW, FileNameW;
2392 SIZE_T InfoSize;
2393 LPBYTE InfoBuffer;
2395 LPWSTR pchPath;
2397 INT nFontCount = 0;
2398 DWORD dwFlags;
2399
2400 /* open registry key */
2403 NULL, NULL);
2404 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
2405 if (!NT_SUCCESS(Status))
2406 {
2407 DPRINT1("ZwOpenKey failed: 0x%08X\n", Status);
2408 return FALSE; /* failure */
2409 }
2410
2411 /* query count of values */
2412 Status = ZwQueryKey(KeyHandle, KeyFullInformation,
2413 &KeyFullInfo, sizeof(KeyFullInfo), &Length);
2414 if (!NT_SUCCESS(Status))
2415 {
2416 DPRINT1("ZwQueryKey failed: 0x%08X\n", Status);
2418 return FALSE; /* failure */
2419 }
2420
2421 /* allocate buffer */
2422 InfoSize = (MAX_PATH + 256) * sizeof(WCHAR);
2423 InfoBuffer = ExAllocatePoolWithTag(PagedPool, InfoSize, TAG_FONT);
2424 if (!InfoBuffer)
2425 {
2426 DPRINT1("ExAllocatePoolWithTag failed\n");
2428 return FALSE;
2429 }
2430
2431 /* for each value */
2432 for (i = 0; i < KeyFullInfo.Values; ++i)
2433 {
2434 /* get value name */
2435 Status = ZwEnumerateValueKey(KeyHandle, i, KeyValueFullInformation,
2436 InfoBuffer, InfoSize, &Length);
2438 {
2439 /* too short buffer */
2440 ExFreePoolWithTag(InfoBuffer, TAG_FONT);
2441 InfoSize *= 2;
2442 InfoBuffer = ExAllocatePoolWithTag(PagedPool, InfoSize, TAG_FONT);
2443 if (!InfoBuffer)
2444 {
2445 DPRINT1("ExAllocatePoolWithTag failed\n");
2446 break;
2447 }
2448 /* try again */
2449 Status = ZwEnumerateValueKey(KeyHandle, i, KeyValueFullInformation,
2450 InfoBuffer, InfoSize, &Length);
2451 }
2452 if (!NT_SUCCESS(Status))
2453 {
2454 DPRINT1("ZwEnumerateValueKey failed: 0x%08X\n", Status);
2455 break; /* failure */
2456 }
2457
2458 /* create FontTitleW string */
2459 pInfo = (PKEY_VALUE_FULL_INFORMATION)InfoBuffer;
2460 Length = pInfo->NameLength / sizeof(WCHAR);
2461 pInfo->Name[Length] = UNICODE_NULL; /* truncate */
2462 if (!RtlCreateUnicodeString(&FontTitleW, pInfo->Name))
2463 {
2465 DPRINT1("RtlCreateUnicodeString failed\n");
2466 break; /* failure */
2467 }
2468
2469 /* query value */
2470 Status = ZwQueryValueKey(KeyHandle, &FontTitleW, KeyValueFullInformation,
2471 InfoBuffer, InfoSize, &Length);
2473 {
2474 /* too short buffer */
2475 ExFreePoolWithTag(InfoBuffer, TAG_FONT);
2476 InfoSize *= 2;
2477 InfoBuffer = ExAllocatePoolWithTag(PagedPool, InfoSize, TAG_FONT);
2478 if (!InfoBuffer)
2479 {
2480 DPRINT1("ExAllocatePoolWithTag failed\n");
2481 break;
2482 }
2483 /* try again */
2484 Status = ZwQueryValueKey(KeyHandle, &FontTitleW, KeyValueFullInformation,
2485 InfoBuffer, InfoSize, &Length);
2486 }
2487 pInfo = (PKEY_VALUE_FULL_INFORMATION)InfoBuffer;
2488 if (!NT_SUCCESS(Status) || !pInfo->DataLength)
2489 {
2490 DPRINT1("ZwQueryValueKey failed: 0x%08X\n", Status);
2491 RtlFreeUnicodeString(&FontTitleW);
2492 break; /* failure */
2493 }
2494
2495 /* Build pchPath */
2496 pchPath = (LPWSTR)((PUCHAR)pInfo + pInfo->DataOffset);
2497 Length = pInfo->DataLength / sizeof(WCHAR);
2498 pchPath[Length] = UNICODE_NULL; /* truncate */
2499
2500 /* Load font(s) without writing registry */
2501 if (PathIsRelativeW(pchPath))
2502 {
2503 dwFlags = 0;
2505 L"\\SystemRoot\\Fonts\\%s", pchPath);
2506 }
2507 else
2508 {
2510 Status = RtlStringCbCopyW(szPath, sizeof(szPath), pchPath);
2511 }
2512
2513 if (NT_SUCCESS(Status))
2514 {
2515 RtlCreateUnicodeString(&FileNameW, szPath);
2516 nFontCount += IntGdiAddFontResourceEx(&FileNameW, 1, 0, dwFlags);
2517 RtlFreeUnicodeString(&FileNameW);
2518 }
2519
2520 RtlFreeUnicodeString(&FontTitleW);
2521 }
2522
2523 /* close now */
2525
2526 /* free memory block */
2527 if (InfoBuffer)
2528 {
2529 ExFreePoolWithTag(InfoBuffer, TAG_FONT);
2530 }
2531
2532 return (KeyFullInfo.Values != 0 && nFontCount != 0);
2533}
2534
2537{
2538 HANDLE Ret = NULL;
2540 PFONT_ENTRY_COLL_MEM EntryCollection;
2541 INT FaceCount;
2542
2544 if (!BufferCopy)
2545 {
2546 *pNumAdded = 0;
2547 return NULL;
2548 }
2549 RtlCopyMemory(BufferCopy, Buffer, dwSize);
2550
2551 RtlZeroMemory(&LoadFont, sizeof(LoadFont));
2552 LoadFont.Memory = SharedMem_Create(BufferCopy, dwSize, FALSE);
2553 LoadFont.Characteristics = FR_PRIVATE | FR_NOT_ENUM;
2554 RtlInitUnicodeString(&LoadFont.RegValueName, NULL);
2556
2557 RtlFreeUnicodeString(&LoadFont.RegValueName);
2558
2559 /* Release our copy */
2563
2564 if (FaceCount > 0)
2565 {
2566 EntryCollection = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY_COLL_MEM), TAG_FONT);
2567 if (EntryCollection)
2568 {
2570 EntryCollection->Entry = LoadFont.PrivateEntry;
2572 IntLockProcessPrivateFonts(Win32Process);
2573 EntryCollection->Handle = ULongToHandle(++Win32Process->PrivateMemFontHandleCount);
2574 InsertTailList(&Win32Process->PrivateMemFontListHead, &EntryCollection->ListEntry);
2575 IntUnLockProcessPrivateFonts(Win32Process);
2577 Ret = EntryCollection->Handle;
2578 }
2579 }
2580 *pNumAdded = FaceCount;
2581
2582 return Ret;
2583}
2584
2587{
2589 PFONT_ENTRY_MEM FontEntry;
2590
2591 while (!IsListEmpty(&Head->ListEntry))
2592 {
2593 Entry = RemoveHeadList(&Head->ListEntry);
2594 FontEntry = CONTAINING_RECORD(Entry, FONT_ENTRY_MEM, ListEntry);
2595
2596 CleanupFontEntry(FontEntry->Entry);
2597 ExFreePoolWithTag(FontEntry, TAG_FONT);
2598 }
2599
2600 CleanupFontEntry(Head->Entry);
2602}
2603
2604static VOID FASTCALL
2606{
2607 PFONT_ENTRY_MEM FontMemEntry = Collection->Entry;
2608 PLIST_ENTRY ListEntry;
2609 RemoveEntryList(&Collection->ListEntry);
2610
2611 do {
2612 /* Also unlink the FONT_ENTRY stuff from the PrivateFontListHead */
2613 RemoveEntryList(&FontMemEntry->Entry->ListEntry);
2614
2615 ListEntry = FontMemEntry->ListEntry.Flink;
2616 FontMemEntry = CONTAINING_RECORD(ListEntry, FONT_ENTRY_MEM, ListEntry);
2617
2618 } while (FontMemEntry != Collection->Entry);
2619}
2620
2623{
2625 PFONT_ENTRY_COLL_MEM CurrentEntry;
2626 PFONT_ENTRY_COLL_MEM EntryCollection = NULL;
2628
2630 IntLockProcessPrivateFonts(Win32Process);
2631 for (Entry = Win32Process->PrivateMemFontListHead.Flink;
2632 Entry != &Win32Process->PrivateMemFontListHead;
2633 Entry = Entry->Flink)
2634 {
2635 CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY_COLL_MEM, ListEntry);
2636
2637 if (CurrentEntry->Handle == hMMFont)
2638 {
2639 EntryCollection = CurrentEntry;
2640 UnlinkFontMemCollection(CurrentEntry);
2641 break;
2642 }
2643 }
2644 IntUnLockProcessPrivateFonts(Win32Process);
2646
2647 if (EntryCollection)
2648 {
2649 IntGdiCleanupMemEntry(EntryCollection->Entry);
2650 ExFreePoolWithTag(EntryCollection, TAG_FONT);
2651 return TRUE;
2652 }
2653 return FALSE;
2654}
2655
2656
2659{
2662 PFONT_ENTRY_COLL_MEM EntryCollection;
2663
2664 DPRINT("IntGdiCleanupPrivateFontsForProcess()\n");
2665 do {
2666 Entry = NULL;
2667 EntryCollection = NULL;
2668
2670 IntLockProcessPrivateFonts(Win32Process);
2671 if (!IsListEmpty(&Win32Process->PrivateMemFontListHead))
2672 {
2673 Entry = Win32Process->PrivateMemFontListHead.Flink;
2674 EntryCollection = CONTAINING_RECORD(Entry, FONT_ENTRY_COLL_MEM, ListEntry);
2675 UnlinkFontMemCollection(EntryCollection);
2676 }
2677 IntUnLockProcessPrivateFonts(Win32Process);
2679
2680 if (EntryCollection)
2681 {
2682 IntGdiCleanupMemEntry(EntryCollection->Entry);
2683 ExFreePoolWithTag(EntryCollection, TAG_FONT);
2684 }
2685 else
2686 {
2687 /* No Mem fonts anymore, see if we have any other private fonts left */
2688 Entry = NULL;
2690 IntLockProcessPrivateFonts(Win32Process);
2691 if (!IsListEmpty(&Win32Process->PrivateFontListHead))
2692 {
2693 Entry = RemoveHeadList(&Win32Process->PrivateFontListHead);
2694 }
2695 IntUnLockProcessPrivateFonts(Win32Process);
2697
2698 if (Entry)
2699 {
2701 }
2702 }
2703
2704 } while (Entry);
2705}
2706
2709{
2710 return (gpsi->BitsPixel > 8) && g_RenderingEnabled;
2711}
2712
2715{
2717}
2718
2721{
2722 switch (logfont->lfQuality)
2723 {
2725 break;
2727 return FT_RENDER_MODE_MONO;
2728 case DRAFT_QUALITY:
2729 return FT_RENDER_MODE_LIGHT;
2730 case CLEARTYPE_QUALITY:
2731 if (!gspv.bFontSmoothing)
2732 break;
2734 break;
2735 return FT_RENDER_MODE_LCD;
2736 }
2737 return FT_RENDER_MODE_NORMAL;
2738}
2739
2740
2743{
2744 PLFONT plfont;
2745 LOGFONTW *plf;
2746
2747 ASSERT(lf);
2748 plfont = LFONT_AllocFontWithHandle();
2749 if (!plfont)
2750 {
2751 return STATUS_NO_MEMORY;
2752 }
2753
2754 ExInitializePushLock(&plfont->lock);
2755 *NewFont = plfont->BaseObject.hHmgr;
2756 plf = &plfont->logfont.elfEnumLogfontEx.elfLogFont;
2757 RtlCopyMemory(plf, lf, sizeof(LOGFONTW));
2758 if (lf->lfEscapement != lf->lfOrientation)
2759 {
2760 /* This should really depend on whether GM_ADVANCED is set */
2761 plf->lfOrientation = plf->lfEscapement;
2762 }
2763 LFONT_UnlockFont(plfont);
2764
2765 return STATUS_SUCCESS;
2766}
2767
2768/*************************************************************************
2769 * TranslateCharsetInfo
2770 *
2771 * Fills a CHARSETINFO structure for a character set, code page, or
2772 * font. This allows making the correspondance between different labelings
2773 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2774 * of the same encoding.
2775 *
2776 * Only one codepage will be set in Cs->fs. If TCI_SRCFONTSIG is used,
2777 * only one codepage should be set in *Src.
2778 *
2779 * RETURNS
2780 * TRUE on success, FALSE on failure.
2781 *
2782 */
2783static BOOLEAN
2785 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2786 if flags == TCI_SRCCHARSET: a character set value
2787 if flags == TCI_SRCCODEPAGE: a code page value */
2788 LPCHARSETINFO Cs, /* [out] structure to receive charset information */
2789 DWORD Flags /* [in] determines interpretation of lpSrc */)
2790{
2791 int Index = 0;
2792
2793 switch (Flags)
2794 {
2795 case TCI_SRCFONTSIG:
2796 while (Index < MAXTCIINDEX && 0 == (*Src >> Index & 0x0001))
2797 {
2798 Index++;
2799 }
2800 break;
2801 case TCI_SRCCODEPAGE:
2802 while (Index < MAXTCIINDEX && *Src != g_FontTci[Index].ciACP)
2803 {
2804 Index++;
2805 }
2806 break;
2807 case TCI_SRCCHARSET:
2808 while (Index < MAXTCIINDEX && *Src != g_FontTci[Index].ciCharset)
2809 {
2810 Index++;
2811 }
2812 break;
2813 case TCI_SRCLOCALE:
2815 return FALSE;
2816 default:
2817 return FALSE;
2818 }
2819
2820 if (Index >= MAXTCIINDEX || DEFAULT_CHARSET == g_FontTci[Index].ciCharset)
2821 {
2822 return FALSE;
2823 }
2824
2825 RtlCopyMemory(Cs, &g_FontTci[Index], sizeof(CHARSETINFO));
2826
2827 return TRUE;
2828}
2829
2830
2832{
2833 int i;
2834
2835 for(i = 0; i < ft_face->num_charmaps; i++)
2836 {
2837 if (ft_face->charmaps[i]->platform_id == TT_PLATFORM_MICROSOFT &&
2838 ft_face->charmaps[i]->encoding == FT_ENCODING_MS_SYMBOL)
2839 {
2840 return TRUE;
2841 }
2842 }
2843 return FALSE;
2844}
2845
2846static void FASTCALL
2848 TT_OS2 *pOS2, TT_HoriHeader *pHori,
2849 FT_WinFNT_HeaderRec *pFNT)
2850{
2851 FT_Fixed XScale, YScale;
2852 int Ascent, Descent;
2853 FT_Face Face = FontGDI->SharedFace->Face;
2854
2856
2857 XScale = Face->size->metrics.x_scale;
2858 YScale = Face->size->metrics.y_scale;
2859
2860 if (pFNT)
2861 {
2862 TM->tmHeight = pFNT->pixel_height;
2863 TM->tmAscent = pFNT->ascent;
2864 TM->tmDescent = TM->tmHeight - TM->tmAscent;
2867 TM->tmAveCharWidth = pFNT->avg_width;
2868 TM->tmMaxCharWidth = pFNT->max_width;
2869 TM->tmOverhang = 0;
2872 TM->tmFirstChar = pFNT->first_char;
2873 TM->tmLastChar = pFNT->last_char;
2874 TM->tmDefaultChar = pFNT->default_char + pFNT->first_char;
2875 TM->tmBreakChar = pFNT->break_char + pFNT->first_char;
2877 TM->tmWeight = FontGDI->RequestWeight;
2878 TM->tmItalic = FontGDI->RequestItalic;
2879 TM->tmUnderlined = FontGDI->RequestUnderline;
2880 TM->tmStruckOut = FontGDI->RequestStrikeOut;
2881 TM->tmCharSet = FontGDI->CharSet;
2882 return;
2883 }
2884
2885 ASSERT(pOS2);
2886 if (!pOS2)
2887 return;
2888
2889 if ((FT_Short)pOS2->usWinAscent + (FT_Short)pOS2->usWinDescent == 0)
2890 {
2891 Ascent = pHori->Ascender;
2892 Descent = -pHori->Descender;
2893 }
2894 else
2895 {
2896 Ascent = (FT_Short)pOS2->usWinAscent;
2897 Descent = (FT_Short)pOS2->usWinDescent;
2898 }
2899
2900 TM->tmAscent = FontGDI->tmAscent;
2901 TM->tmDescent = FontGDI->tmDescent;
2902 TM->tmHeight = TM->tmAscent + TM->tmDescent;
2903 TM->tmInternalLeading = FontGDI->tmInternalLeading;
2904
2905 /* MSDN says:
2906 * el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
2907 */
2908 TM->tmExternalLeading = max(0, (FT_MulFix(pHori->Line_Gap
2909 - ((Ascent + Descent)
2910 - (pHori->Ascender - pHori->Descender)),
2911 YScale) + 32) >> 6);
2912 if (FontGDI->lfWidth != 0)
2913 TM->tmAveCharWidth = FontGDI->lfWidth;
2914 else
2915 TM->tmAveCharWidth = (FT_MulFix(pOS2->xAvgCharWidth, XScale) + 32) >> 6;
2916
2917 if (TM->tmAveCharWidth == 0)
2918 TM->tmAveCharWidth = 1;
2919
2920 /* Correct forumla to get the maxcharwidth from unicode and ansi font */
2921 TM->tmMaxCharWidth = (FT_MulFix(Face->max_advance_width, XScale) + 32) >> 6;
2922
2923 if (FontGDI->OriginalWeight != FW_DONTCARE &&
2924 FontGDI->OriginalWeight != FW_NORMAL)
2925 {
2926 TM->tmWeight = FontGDI->OriginalWeight;
2927 }
2928 else
2929 {
2930 TM->tmWeight = FontGDI->RequestWeight;
2931 }
2932
2933 TM->tmOverhang = 0;
2934 TM->tmDigitizedAspectX = 96;
2935 TM->tmDigitizedAspectY = 96;
2936 if (face_has_symbol_charmap(Face) ||
2937 (pOS2->usFirstCharIndex >= 0xf000 && pOS2->usFirstCharIndex < 0xf100))
2938 {
2939 USHORT cpOEM, cpAnsi;
2940
2941 EngGetCurrentCodePage(&cpOEM, &cpAnsi);
2942 TM->tmFirstChar = 0;
2943 switch(cpAnsi)
2944 {
2945 case 1257: /* Baltic */
2946 TM->tmLastChar = 0xf8fd;
2947 break;
2948 default:
2949 TM->tmLastChar = 0xf0ff;
2950 }
2951 TM->tmBreakChar = 0x20;
2952 TM->tmDefaultChar = 0x1f;
2953 }
2954 else
2955 {
2956 TM->tmFirstChar = pOS2->usFirstCharIndex; /* Should be the first char in the cmap */
2957 TM->tmLastChar = pOS2->usLastCharIndex; /* Should be min(cmap_last, os2_last) */
2958
2959 if(pOS2->usFirstCharIndex <= 1)
2960 TM->tmBreakChar = pOS2->usFirstCharIndex + 2;
2961 else if (pOS2->usFirstCharIndex > 0xff)
2962 TM->tmBreakChar = 0x20;
2963 else
2964 TM->tmBreakChar = pOS2->usFirstCharIndex;
2965 TM->tmDefaultChar = TM->tmBreakChar - 1;
2966 }
2967
2968 if (FontGDI->OriginalItalic || FontGDI->RequestItalic)
2969 {
2970 TM->tmItalic = 0xFF;
2971 }
2972 else
2973 {
2974 TM->tmItalic = 0;
2975 }
2976 TM->tmUnderlined = (FontGDI->RequestUnderline ? 0xFF : 0);
2977 TM->tmStruckOut = (FontGDI->RequestStrikeOut ? 0xFF : 0);
2978
2979 if (!FT_IS_FIXED_WIDTH(Face))
2980 {
2981 switch (pOS2->panose[PAN_PROPORTION_INDEX])
2982 {
2984 TM->tmPitchAndFamily = 0;
2985 break;
2986 default:
2988 break;
2989 }
2990 }
2991 else
2992 {
2993 TM->tmPitchAndFamily = 0;
2994 }
2995
2996 switch (pOS2->panose[PAN_FAMILYTYPE_INDEX])
2997 {
2998 case PAN_FAMILY_SCRIPT:
3000 break;
3003 break;
3004
3005 case PAN_ANY:
3006 case PAN_NO_FIT:
3008 case PAN_FAMILY_PICTORIAL: /* Symbol fonts get treated as if they were text */
3009 /* Which is clearly not what the panose spec says. */
3010 if (TM->tmPitchAndFamily == 0) /* Fixed */
3011 {
3013 }
3014 else
3015 {
3016 switch (pOS2->panose[PAN_SERIFSTYLE_INDEX])
3017 {
3018 case PAN_ANY:
3019 case PAN_NO_FIT:
3020 default:
3022 break;
3023
3024 case PAN_SERIF_COVE:
3028 case PAN_SERIF_SQUARE:
3029 case PAN_SERIF_THIN:
3030 case PAN_SERIF_BONE:
3032 case PAN_SERIF_TRIANGLE:
3034 break;
3035
3039 case PAN_SERIF_FLARED:
3040 case PAN_SERIF_ROUNDED:
3042 break;
3043 }
3044 }
3045 break;
3046 default:
3048 }
3049
3050 if (FT_IS_SCALABLE(Face))
3051 {
3053 }
3054 if (FT_IS_SFNT(Face))
3055 {
3057 }
3058
3059 TM->tmCharSet = FontGDI->CharSet;
3060}
3061
3062static NTSTATUS
3064 FT_UShort NameID, FT_UShort LangID);
3065
3066typedef struct FONT_NAMES
3067{
3068 UNICODE_STRING FamilyNameW; /* family name (TT_NAME_ID_FONT_FAMILY) */
3069 UNICODE_STRING FaceNameW; /* face name (TT_NAME_ID_FULL_NAME) */
3070 UNICODE_STRING StyleNameW; /* style name (TT_NAME_ID_FONT_SUBFAMILY) */
3071 UNICODE_STRING FullNameW; /* unique name (TT_NAME_ID_UNIQUE_ID) */
3072 ULONG OtmSize; /* size of OUTLINETEXTMETRICW with extra data */
3074
3075static __inline void FASTCALL
3077{
3078 ULONG OtmSize;
3079
3080 RtlInitUnicodeString(&Names->FamilyNameW, NULL);
3081 RtlInitUnicodeString(&Names->FaceNameW, NULL);
3082 RtlInitUnicodeString(&Names->StyleNameW, NULL);
3083 RtlInitUnicodeString(&Names->FullNameW, NULL);
3084
3085 /* family name */
3087 /* face name */
3089 /* style name */
3091 /* unique name (full name) */
3093
3094 /* Calculate the size of OUTLINETEXTMETRICW with extra data */
3095 OtmSize = sizeof(OUTLINETEXTMETRICW) +
3096 Names->FamilyNameW.Length + sizeof(UNICODE_NULL) +
3097 Names->FaceNameW.Length + sizeof(UNICODE_NULL) +
3098 Names->StyleNameW.Length + sizeof(UNICODE_NULL) +
3099 Names->FullNameW.Length + sizeof(UNICODE_NULL);
3100 Names->OtmSize = OtmSize;
3101}
3102
3105{
3106 RtlCopyMemory(pb, pName->Buffer, pName->Length);
3107 *(WCHAR *)&pb[pName->Length] = UNICODE_NULL;
3108 return pName->Length + sizeof(UNICODE_NULL);
3109}
3110
3111static __inline BYTE *FASTCALL
3113{
3114 BYTE *pb = (BYTE *)Otm + sizeof(OUTLINETEXTMETRICW);
3115
3116 /* family name */
3117 Otm->otmpFamilyName = (LPSTR)(pb - (BYTE*) Otm);
3118 pb += IntStoreName(&Names->FamilyNameW, pb);
3119
3120 /* face name */
3121 Otm->otmpFaceName = (LPSTR)(pb - (BYTE*) Otm);
3122 pb += IntStoreName(&Names->FaceNameW, pb);
3123
3124 /* style name */
3125 Otm->otmpStyleName = (LPSTR)(pb - (BYTE*) Otm);
3126 pb += IntStoreName(&Names->StyleNameW, pb);
3127
3128 /* unique name (full name) */
3129 Otm->otmpFullName = (LPSTR)(pb - (BYTE*) Otm);
3130 pb += IntStoreName(&Names->FullNameW, pb);
3131
3132 return pb;
3133}
3134
3135static __inline void FASTCALL
3137{
3138 RtlFreeUnicodeString(&Names->FamilyNameW);
3139 RtlFreeUnicodeString(&Names->FaceNameW);
3140 RtlFreeUnicodeString(&Names->StyleNameW);
3141 RtlFreeUnicodeString(&Names->FullNameW);
3142}
3143
3144/*************************************************************
3145 * IntGetOutlineTextMetrics
3146 *
3147 */
3150 UINT Size,
3151 OUTLINETEXTMETRICW *Otm,
3152 BOOL bLocked)
3153{
3154 TT_OS2 *pOS2;
3155 TT_HoriHeader *pHori;
3156 TT_Postscript *pPost;
3157 FT_Fixed XScale, YScale;
3158 FT_WinFNT_HeaderRec WinFNT;
3160 BYTE *pb;
3161 FONT_NAMES FontNames;
3162 PSHARED_FACE SharedFace = FontGDI->SharedFace;
3164 FT_Face Face = SharedFace->Face;
3165
3166 if (bLocked)
3168 else
3170
3172 {
3173 Cache = &SharedFace->EnglishUS;
3174 }
3175 else
3176 {
3177 Cache = &SharedFace->UserLanguage;
3178 }
3179
3180 if (Size == 0 && Cache->OutlineRequiredSize > 0)
3181 {
3182 ASSERT(Otm == NULL);
3183 return Cache->OutlineRequiredSize;
3184 }
3185
3186 if (!bLocked)
3188
3189 IntInitFontNames(&FontNames, SharedFace);
3190 Cache->OutlineRequiredSize = FontNames.OtmSize;
3191
3192 if (Size == 0)
3193 {
3194 ASSERT(Otm == NULL);
3195 IntFreeFontNames(&FontNames);
3196 if (!bLocked)
3198 return Cache->OutlineRequiredSize;
3199 }
3200
3201 ASSERT(Otm != NULL);
3202
3203 if (Size < Cache->OutlineRequiredSize)
3204 {
3205 DPRINT1("Size %u < OutlineRequiredSize %u\n", Size,
3206 Cache->OutlineRequiredSize);
3207 IntFreeFontNames(&FontNames);
3208 if (!bLocked)
3210 return 0; /* failure */
3211 }
3212
3213 XScale = Face->size->metrics.x_scale;
3214 YScale = Face->size->metrics.y_scale;
3215
3216 pOS2 = FT_Get_Sfnt_Table(Face, FT_SFNT_OS2);
3217 pHori = FT_Get_Sfnt_Table(Face, FT_SFNT_HHEA);
3218 pPost = FT_Get_Sfnt_Table(Face, FT_SFNT_POST); /* We can live with this failing */
3219 Error = FT_Get_WinFNT_Header(Face, &WinFNT);
3220
3221 if (pOS2 == NULL && Error)
3222 {
3223 if (!bLocked)
3225 DPRINT1("Can't find OS/2 table - not TT font?\n");
3226 IntFreeFontNames(&FontNames);
3227 return 0;
3228 }
3229
3230 if (pHori == NULL && Error)
3231 {
3232 if (!bLocked)
3234 DPRINT1("Can't find HHEA table - not TT font?\n");
3235 IntFreeFontNames(&FontNames);
3236 return 0;
3237 }
3238
3239 Otm->otmSize = Cache->OutlineRequiredSize;
3240
3241 FillTM(&Otm->otmTextMetrics, FontGDI, pOS2, pHori, (Error ? NULL : &WinFNT));
3242
3243 if (!pOS2)
3244 goto skip_os2;
3245
3246 Otm->otmFiller = 0;
3248 Otm->otmfsSelection = pOS2->fsSelection;
3249 Otm->otmfsType = pOS2->fsType;
3250 Otm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
3251 Otm->otmsCharSlopeRun = pHori->caret_Slope_Run;
3252 Otm->otmItalicAngle = 0; /* POST table */
3253 Otm->otmEMSquare = Face->units_per_EM;
3254
3255#define SCALE_X(value) ((FT_MulFix((value), XScale) + 32) >> 6)
3256#define SCALE_Y(value) ((FT_MulFix((value), YScale) + 32) >> 6)
3257
3258 Otm->otmAscent = SCALE_Y(pOS2->sTypoAscender);
3259 Otm->otmDescent = SCALE_Y(pOS2->sTypoDescender);
3260 Otm->otmLineGap = SCALE_Y(pOS2->sTypoLineGap);
3261 Otm->otmsCapEmHeight = SCALE_Y(pOS2->sCapHeight);
3262 Otm->otmsXHeight = SCALE_Y(pOS2->sxHeight);
3263 Otm->otmrcFontBox.left = SCALE_X(Face->bbox.xMin);
3264 Otm->otmrcFontBox.right = SCALE_X(Face->bbox.xMax);
3265 Otm->otmrcFontBox.top = SCALE_Y(Face->bbox.yMax);
3266 Otm->otmrcFontBox.bottom = SCALE_Y(Face->bbox.yMin);
3269 Otm->otmMacLineGap = Otm->otmLineGap;
3270 Otm->otmusMinimumPPEM = 0; /* TT Header */
3281
3282 if (!pPost)
3283 {
3284 Otm->otmsUnderscoreSize = 0;
3285 Otm->otmsUnderscorePosition = 0;
3286 }
3287 else
3288 {
3291 }
3292
3293#undef SCALE_X
3294#undef SCALE_Y
3295
3296skip_os2:
3297 if (!bLocked)
3299
3300 pb = IntStoreFontNames(&FontNames, Otm);
3301 ASSERT(pb - (BYTE*)Otm == Cache->OutlineRequiredSize);
3302
3303 IntFreeFontNames(&FontNames);
3304
3305 return Cache->OutlineRequiredSize;
3306}
3307
3308/* See https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2008/bb165625(v=vs.90) */
3309static BYTE
3311{
3312 /* FIXME: Add more and fix if wrong */
3313 switch (PRIMARYLANGID(LangID))
3314 {
3315 case LANG_CHINESE:
3316 switch (SUBLANGID(LangID))
3317 {
3319 return CHINESEBIG5_CHARSET;
3321 default:
3322 break;
3323 }
3324 return GB2312_CHARSET;
3325
3326 case LANG_CZECH: case LANG_HUNGARIAN: case LANG_POLISH:
3327 case LANG_SLOVAK: case LANG_SLOVENIAN: case LANG_ROMANIAN:
3328 return EASTEUROPE_CHARSET;
3329
3331 case LANG_SERBIAN: case LANG_UKRAINIAN:
3332 return RUSSIAN_CHARSET;
3333
3334 case LANG_ARABIC: return ARABIC_CHARSET;
3335 case LANG_GREEK: return GREEK_CHARSET;
3336 case LANG_HEBREW: return HEBREW_CHARSET;
3337 case LANG_JAPANESE: return SHIFTJIS_CHARSET;
3338 case LANG_KOREAN: return JOHAB_CHARSET;
3339 case LANG_TURKISH: return TURKISH_CHARSET;
3340 case LANG_THAI: return THAI_CHARSET;
3341 case LANG_LATVIAN: return BALTIC_CHARSET;
3343
3344 case LANG_ENGLISH: case LANG_BASQUE: case LANG_CATALAN:
3345 case LANG_DANISH: case LANG_DUTCH: case LANG_FINNISH:
3346 case LANG_FRENCH: case LANG_GERMAN: case LANG_ITALIAN:
3348 case LANG_SWEDISH: default:
3349 return ANSI_CHARSET;
3350 }
3351}
3352
3353static void
3355{
3356 BYTE b, *pb = pvData;
3357 Size /= 2;
3358 while (Size-- > 0)
3359 {
3360 b = pb[0];
3361 pb[0] = pb[1];
3362 pb[1] = b;
3363 ++pb; ++pb;
3364 }
3365}
3366
3367static NTSTATUS
3369 FT_UShort NameID, FT_UShort LangID)
3370{
3372 INT i, Count, BestIndex, Score, BestScore;
3375 ANSI_STRING AnsiName;
3377 FT_Face Face = SharedFace->Face;
3378
3379 RtlFreeUnicodeString(pNameW);
3380
3381 /* select cache */
3383 {
3384 Cache = &SharedFace->EnglishUS;
3385 }
3386 else
3387 {
3388 Cache = &SharedFace->UserLanguage;
3389 }
3390
3391 /* use cache if available */
3392 if (NameID == TT_NAME_ID_FONT_FAMILY && Cache->FontFamily.Buffer)
3393 {
3394 return DuplicateUnicodeString(&Cache->FontFamily, pNameW);
3395 }
3396 if (NameID == TT_NAME_ID_FULL_NAME && Cache->FullName.Buffer)
3397 {
3398 return DuplicateUnicodeString(&Cache->FullName, pNameW);
3399 }
3400
3401 BestIndex = -1;
3402 BestScore = 0;
3403
3405 for (i = 0; i < Count; ++i)
3406 {
3407 Error = FT_Get_Sfnt_Name(Face, i, &Name);
3408 if (Error)
3409 {
3410 continue; /* failure */
3411 }
3412
3413 if (Name.name_id != NameID)
3414 {
3415 continue; /* mismatched */
3416 }
3417
3418 if (Name.platform_id != TT_PLATFORM_MICROSOFT ||
3419 (Name.encoding_id != TT_MS_ID_UNICODE_CS &&
3420 Name.encoding_id != TT_MS_ID_SYMBOL_CS))
3421 {
3422 continue; /* not Microsoft Unicode name */
3423 }
3424
3425 if (Name.string == NULL || Name.string_len == 0 ||
3426 (Name.string[0] == 0 && Name.string[1] == 0))
3427 {
3428 continue; /* invalid string */
3429 }
3430
3431 if (Name.language_id == LangID)
3432 {
3433 Score = 30;
3434 BestIndex = i;
3435 break; /* best match */
3436 }
3437 else if (PRIMARYLANGID(Name.language_id) == PRIMARYLANGID(LangID))
3438 {
3439 Score = 20;
3440 }
3441 else if (PRIMARYLANGID(Name.language_id) == LANG_ENGLISH)
3442 {
3443 Score = 10;
3444 }
3445 else
3446 {
3447 Score = 0;
3448 }
3449
3450 if (Score > BestScore)
3451 {
3452 BestScore = Score;
3453 BestIndex = i;
3454 }
3455 }
3456
3457 if (BestIndex >= 0)
3458 {
3459 /* store the best name */
3460 Error = (Score == 30) ? 0 : FT_Get_Sfnt_Name(Face, BestIndex, &Name);
3461 if (!Error)
3462 {
3463 /* NOTE: Name.string is not null-terminated */
3464 UNICODE_STRING Tmp;
3465 Tmp.Buffer = (PWCH)Name.string;
3466 Tmp.Length = Tmp.MaximumLength = Name.string_len;
3467
3468 pNameW->Length = 0;
3469 pNameW->MaximumLength = Name.string_len + sizeof(WCHAR);
3471
3472 if (pNameW->Buffer)
3473 {
3474 Status = RtlAppendUnicodeStringToString(pNameW, &Tmp);
3475 if (Status == STATUS_SUCCESS)
3476 {
3477 /* Convert UTF-16 big endian to little endian */
3478 SwapEndian(pNameW->Buffer, pNameW->Length);
3479 }
3480 }
3481 else
3482 {
3484 }
3485 }
3486 }
3487
3488 if (!NT_SUCCESS(Status))
3489 {
3490 /* defaulted */
3491 if (NameID == TT_NAME_ID_FONT_SUBFAMILY)
3492 {
3493 RtlInitAnsiString(&AnsiName, Face->style_name);
3494 Status = RtlAnsiStringToUnicodeString(pNameW, &AnsiName, TRUE);
3495 }
3496 else
3497 {
3498 RtlInitAnsiString(&AnsiName, Face->family_name);
3499 Status = RtlAnsiStringToUnicodeString(pNameW, &AnsiName, TRUE);
3500 }
3501 }
3502
3503 if (NT_SUCCESS(Status))
3504 {
3505 /* make cache */
3506 if (NameID == TT_NAME_ID_FONT_FAMILY)
3507 {
3509 if (!Cache->FontFamily.Buffer)
3510 DuplicateUnicodeString(pNameW, &Cache->FontFamily);
3511 }
3512 else if (NameID == TT_NAME_ID_FULL_NAME)
3513 {
3515 if (!Cache->FullName.Buffer)
3516 DuplicateUnicodeString(pNameW, &Cache->FullName);
3517 }
3518 }
3519
3520 return Status;
3521}
3522
3523static void FASTCALL
3525 LPCWSTR FullName, PFONTGDI FontGDI)
3526{
3527 ANSI_STRING StyleA;
3528 UNICODE_STRING StyleW;
3529 TT_OS2 *pOS2;
3531 CHARSETINFO CharSetInfo;
3532 unsigned i, Size;
3533 OUTLINETEXTMETRICW *Otm;
3534 LOGFONTW *Lf;
3535 TEXTMETRICW *TM;
3536 NEWTEXTMETRICW *Ntm;
3537 DWORD fs0;
3539 PSHARED_FACE SharedFace = FontGDI->SharedFace;
3540 FT_Face Face = SharedFace->Face;
3541 UNICODE_STRING NameW;
3542
3543 RtlInitUnicodeString(&NameW, NULL);
3546 Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL, TRUE);
3547 if (!Size)
3548 return;
3550 if (!Otm)
3551 return;
3553 Size = IntGetOutlineTextMetrics(FontGDI, Size, Otm, TRUE);
3554 if (!Size)
3555 {
3557 return;
3558 }
3559
3560 Lf = &Info->EnumLogFontEx.elfLogFont;
3561 TM = &Otm->otmTextMetrics;
3562
3563 Lf->lfHeight = TM->tmHeight;
3564 Lf->lfWidth = TM->tmAveCharWidth;
3565 Lf->lfWeight = TM->tmWeight;
3566 Lf->lfItalic = TM->tmItalic;
3567 Lf->lfPitchAndFamily = (TM->tmPitchAndFamily & 0xf1) + 1;
3568 Lf->lfCharSet = TM->tmCharSet;
3572
3573 Ntm = &Info->NewTextMetricEx.ntmTm;
3574 Ntm->tmHeight = TM->tmHeight;
3575 Ntm->tmAscent = TM->tmAscent;
3576 Ntm->tmDescent = TM->tmDescent;
3579 Ntm->tmAveCharWidth = TM->tmAveCharWidth;
3580 Ntm->tmMaxCharWidth = TM->tmMaxCharWidth;
3581 Ntm->tmWeight = TM->tmWeight;
3582 Ntm->tmOverhang = TM->tmOverhang;
3585 Ntm->tmFirstChar = TM->tmFirstChar;
3586 Ntm->tmLastChar = TM->tmLastChar;
3587 Ntm->tmDefaultChar = TM->tmDefaultChar;
3588 Ntm->tmBreakChar = TM->tmBreakChar;
3589 Ntm->tmItalic = TM->tmItalic;
3590 Ntm->tmUnderlined = TM->tmUnderlined;
3591 Ntm->tmStruckOut = TM->tmStruckOut;
3593 Ntm->tmCharSet = TM->tmCharSet;
3594 Ntm->ntmFlags = TM->tmItalic ? NTM_ITALIC : 0;
3595
3596 if (550 < TM->tmWeight) Ntm->ntmFlags |= NTM_BOLD;
3597
3598 if (0 == Ntm->ntmFlags) Ntm->ntmFlags = NTM_REGULAR;
3599
3600 Info->FontType = (0 != (TM->tmPitchAndFamily & TMPF_TRUETYPE)
3601 ? TRUETYPE_FONTTYPE : 0);
3602
3603 if (0 == (TM->tmPitchAndFamily & TMPF_VECTOR))
3604 Info->FontType |= RASTER_FONTTYPE;
3605
3606
3607 /* face name */
3608 if (!FaceName)
3609 FaceName = (WCHAR*)((ULONG_PTR)Otm + (ULONG_PTR)Otm->otmpFamilyName);
3610
3611 RtlStringCbCopyW(Lf->lfFaceName, sizeof(Lf->lfFaceName), FaceName);
3612
3613 /* full name */
3614 if (!FullName)
3615 FullName = (WCHAR*)((ULONG_PTR) Otm + (ULONG_PTR)Otm->otmpFaceName);
3616
3617 RtlStringCbCopyW(Info->EnumLogFontEx.elfFullName,
3618 sizeof(Info->EnumLogFontEx.elfFullName),
3619 FullName);
3620
3621 RtlInitAnsiString(&StyleA, Face->style_name);
3622 StyleW.Buffer = Info->EnumLogFontEx.elfStyle;
3623 StyleW.MaximumLength = sizeof(Info->EnumLogFontEx.elfStyle);
3624 status = RtlAnsiStringToUnicodeString(&StyleW, &StyleA, FALSE);
3625 if (!NT_SUCCESS(status))
3626 {
3628 return;
3629 }
3630 Info->EnumLogFontEx.elfScript[0] = UNICODE_NULL;
3631
3632 pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
3633
3634 if (!pOS2)
3635 {
3637 return;
3638 }
3639
3640 Ntm->ntmSizeEM = Otm->otmEMSquare;
3642 Ntm->ntmAvgWidth = 0;
3643
3645
3646 fs.fsCsb[0] = pOS2->ulCodePageRange1;
3647 fs.fsCsb[1] = pOS2->ulCodePageRange2;
3648 fs.fsUsb[0] = pOS2->ulUnicodeRange1;
3649 fs.fsUsb[1] = pOS2->ulUnicodeRange2;
3650 fs.fsUsb[2] = pOS2->ulUnicodeRange3;
3651 fs.fsUsb[3] = pOS2->ulUnicodeRange4;
3652
3653 if (0 == pOS2->version)
3654 {
3655 FT_UInt Dummy;
3656
3657 if (FT_Get_First_Char(Face, &Dummy) < 0x100)
3658 fs.fsCsb[0] |= FS_LATIN1;
3659 else
3660 fs.fsCsb[0] |= FS_SYMBOL;
3661 }
3662
3663 if (fs.fsCsb[0] == 0)
3664 {
3665 /* Let's see if we can find any interesting cmaps */
3666 for (i = 0; i < (UINT)Face->num_charmaps; i++)
3667 {
3668 switch (Face->charmaps[i]->encoding)
3669 {
3670 case FT_ENCODING_UNICODE:
3671 case FT_ENCODING_APPLE_ROMAN:
3672 fs.fsCsb[0] |= FS_LATIN1;
3673 break;
3674 case FT_ENCODING_MS_SYMBOL:
3675 fs.fsCsb[0] |= FS_SYMBOL;
3676 break;
3677 default:
3678 break;
3679 }
3680 }
3681 }
3682
3683 for (i = 0; i < MAXTCIINDEX; i++)
3684 {
3685 fs0 = 1L << i;
3686 if (fs.fsCsb[0] & fs0)
3687 {
3688 if (!IntTranslateCharsetInfo(&fs0, &CharSetInfo, TCI_SRCFONTSIG))
3689 {
3690 CharSetInfo.ciCharset = DEFAULT_CHARSET;
3691 }
3692 if (DEFAULT_CHARSET != CharSetInfo.ciCharset)
3693 {
3694 if (g_ElfScripts[i])
3695 wcscpy(Info->EnumLogFontEx.elfScript, g_ElfScripts[i]);
3696 else
3697 {
3698 DPRINT1("Unknown elfscript for bit %u\n", i);
3699 }
3700 }
3701 }
3702 }
3703 Info->NewTextMetricEx.ntmFontSig = fs;
3704}
3705
3706static BOOLEAN FASTCALL
3709 LPCWSTR NominalName,
3710 LONG *pCount,
3711 LONG MaxCount,
3712 PLIST_ENTRY Head)
3713{
3715 PFONT_ENTRY CurrentEntry;
3716 FONTGDI *FontGDI;
3717 FONTFAMILYINFO InfoEntry;
3718 LONG Count = *pCount;
3719
3720 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
3721 {
3722 CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
3723 FontGDI = CurrentEntry->Font;
3724 ASSERT(FontGDI);
3725
3726 if (LogFont->lfCharSet != DEFAULT_CHARSET &&
3727 LogFont->lfCharSet != FontGDI->CharSet)
3728 {
3729 continue; /* charset mismatch */
3730 }
3731
3732 /* get one info entry */
3733 FontFamilyFillInfo(&InfoEntry, NULL, NULL, FontGDI);
3734
3735 if (LogFont->lfFaceName[0] != UNICODE_NULL)
3736 {
3737 /* check name */
3738 if (_wcsnicmp(LogFont->lfFaceName,
3740 RTL_NUMBER_OF(LogFont->lfFaceName) - 1) != 0 &&
3741 _wcsnicmp(LogFont->lfFaceName,
3742 InfoEntry.EnumLogFontEx.elfFullName,
3743 RTL_NUMBER_OF(LogFont->lfFaceName) - 1) != 0)
3744 {
3745 continue;
3746 }
3747 }
3748
3749 if (NominalName)
3750 {
3751 /* store the nominal name */
3753 sizeof(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName),
3754 NominalName);
3755 }
3756
3757 /* store one entry to Info */
3758 if (0 <= Count && Count < MaxCount)
3759 {
3760 RtlCopyMemory(&Info[Count], &InfoEntry, sizeof(InfoEntry));
3761 }
3762 Count++;
3763 }
3764
3765 *pCount = Count;
3766
3767 return TRUE;
3768}
3769
3770static BOOLEAN FASTCALL
3773 LONG *pCount,
3774 LONG MaxCount)
3775{
3776 PLIST_ENTRY pEntry, pHead = &g_FontSubstListHead;
3777 PFONTSUBST_ENTRY pCurrentEntry;
3778 PUNICODE_STRING pFromW, pToW;
3779 LOGFONTW lf = *LogFont;
3781
3782 for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink)
3783 {
3784 pCurrentEntry = CONTAINING_RECORD(pEntry, FONTSUBST_ENTRY, ListEntry);
3785
3786 pFromW = &pCurrentEntry->FontNames[FONTSUBST_FROM];
3787 if (LogFont->lfFaceName[0] != UNICODE_NULL)
3788 {
3789 /* check name */
3790 if (_wcsicmp(LogFont->lfFaceName, pFromW->Buffer) != 0)
3791 continue; /* mismatch */
3792 }
3793
3794 pToW = &pCurrentEntry->FontNames[FONTSUBST_TO];
3795 if (RtlEqualUnicodeString(pFromW, pToW, TRUE) &&
3796 pCurrentEntry->CharSets[FONTSUBST_FROM] ==
3797 pCurrentEntry->CharSets[FONTSUBST_TO])
3798 {
3799 /* identical mapping */
3800 continue;
3801 }
3802
3803 /* substitute and get the real name */
3804 IntUnicodeStringToBuffer(lf.lfFaceName, sizeof(lf.lfFaceName), pFromW);
3806 if (LogFont->lfCharSet != DEFAULT_CHARSET && LogFont->lfCharSet != lf.lfCharSet)
3807 continue;
3808
3809 /* search in global fonts */
3811 GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount, &g_FontListHead);
3812
3813 /* search in private fonts */
3814 IntLockProcessPrivateFonts(Win32Process);
3815 GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount,
3816 &Win32Process->PrivateFontListHead);
3817 IntUnLockProcessPrivateFonts(Win32Process);
3819
3820 if (LogFont->lfFaceName[0] != UNICODE_NULL)
3821 {
3822 /* it's already matched to the exact name and charset if the name
3823 was specified at here, then so don't scan more for another name */
3824 break;
3825 }
3826 }
3827
3828 return TRUE;
3829}
3830
3831BOOL
3834{
3835 if ( lprs )
3836 {
3837 lprs->nSize = sizeof(RASTERIZER_STATUS);
3838 lprs->wFlags = TT_AVAILABLE | TT_ENABLED;
3839 lprs->nLanguageID = gusLanguageID;
3840 return TRUE;
3841 }
3843 return FALSE;
3844}
3845
3846static DWORD
3848{
3849 DWORD dwHash = cdw;
3850 const DWORD *pdw = pv;
3851
3852 while (cdw-- > 0)
3853 {
3854 dwHash *= 3;
3855 dwHash ^= *pdw++;
3856 }
3857
3858 return dwHash;
3859}
3860
3861static FT_BitmapGlyph
3863{
3864 PLIST_ENTRY CurrentEntry;
3865 PFONT_CACHE_ENTRY FontEntry;
3866 DWORD dwHash = pCache->dwHash;
3867
3869
3870 for (CurrentEntry = g_FontCacheListHead.Flink;
3871 CurrentEntry != &g_FontCacheListHead;
3872 CurrentEntry = CurrentEntry->Flink)
3873 {
3874 FontEntry = CONTAINING_RECORD(CurrentEntry, FONT_CACHE_ENTRY, ListEntry);
3875 if (FontEntry->dwHash == dwHash &&
3876 FontEntry->Hashed.GlyphIndex == pCache->Hashed.GlyphIndex &&
3877 FontEntry->Hashed.Face == pCache->Hashed.Face &&
3878 FontEntry->Hashed.lfHeight == pCache->Hashed.lfHeight &&
3879 FontEntry->Hashed.lfWidth == pCache->Hashed.lfWidth &&
3880 FontEntry->Hashed.AspectValue == pCache->Hashed.AspectValue &&
3881 memcmp(&FontEntry->Hashed.matTransform, &pCache->Hashed.matTransform,
3882 sizeof(FT_Matrix)) == 0)
3883 {
3884 break;
3885 }
3886 }
3887
3888 if (CurrentEntry == &g_FontCacheListHead)
3889 {
3890 return NULL;
3891 }
3892
3893 RemoveEntryList(CurrentEntry);
3894 InsertHeadList(&g_FontCacheListHead, CurrentEntry);
3895 return FontEntry->BitmapGlyph;
3896}
3897
3898static FT_BitmapGlyph
3901 IN FT_GlyphSlot GlyphSlot)
3902{
3903 FT_Glyph GlyphCopy;
3904 INT error;
3905 PFONT_CACHE_ENTRY NewEntry;
3906 FT_Bitmap AlignedBitmap;
3907 FT_BitmapGlyph BitmapGlyph;
3908
3910
3911 error = FT_Get_Glyph(GlyphSlot, &GlyphCopy);
3912 if (error)
3913 {
3914 DPRINT1("Failure caching glyph.\n");
3915 return NULL;
3916 };
3917
3918 error = FT_Glyph_To_Bitmap(&GlyphCopy, Cache->Hashed.Aspect.RenderMode, 0, 1);
3919 if (error)
3920 {
3921 FT_Done_Glyph(GlyphCopy);
3922 DPRINT1("Failure rendering glyph.\n");
3923 return NULL;
3924 };
3925
3927 if (!NewEntry)
3928 {
3929 DPRINT1("Alloc failure caching glyph.\n");
3930 FT_Done_Glyph(GlyphCopy);
3931 return NULL;
3932 }
3933
3934 BitmapGlyph = (FT_BitmapGlyph)GlyphCopy;
3935 FT_Bitmap_New(&AlignedBitmap);
3936 if (FT_Bitmap_Convert_ReactOS_Hack(GlyphSlot->library, &BitmapGlyph->bitmap,
3937 &AlignedBitmap, 4, TRUE))
3938 {
3939 DPRINT1("Conversion failed\n");
3940 ExFreePoolWithTag(NewEntry, TAG_FONT);
3941 FT_Bitmap_Done(GlyphSlot->library, &AlignedBitmap);
3942 FT_Done_Glyph((FT_Glyph)BitmapGlyph);
3943 return NULL;
3944 }
3945
3946 FT_Bitmap_Done(GlyphSlot->library, &BitmapGlyph->bitmap);
3947 BitmapGlyph->bitmap = AlignedBitmap;
3948
3949 NewEntry->BitmapGlyph = BitmapGlyph;
3950 NewEntry->dwHash = Cache->dwHash;
3951 NewEntry->Hashed = Cache->Hashed;
3952
3953 InsertHeadList(&g_FontCacheListHead, &NewEntry->ListEntry);
3955 {
3956 NewEntry = CONTAINING_RECORD(g_FontCacheListHead.Blink, FONT_CACHE_ENTRY, ListEntry);
3957 RemoveCachedEntry(NewEntry);
3958 }
3959
3960 return BitmapGlyph;
3961}
3962
3963
3964static unsigned int get_native_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
3965{
3966 TTPOLYGONHEADER *pph;
3967 TTPOLYCURVE *ppc;
3968 int needed = 0, point = 0, contour, first_pt;
3969 unsigned int pph_start, cpfx;
3970 DWORD type;
3971
3972 for (contour = 0; contour < outline->n_contours; contour++)
3973 {
3974 /* Ignore contours containing one point */
3975 if (point == outline->contours[contour])
3976 {
3977 point++;
3978 continue;
3979 }
3980
3981 pph_start = needed;
3982 pph = (TTPOLYGONHEADER *)(buf + needed);
3983 first_pt = point;
3984 if (buf)
3985 {
3986 pph->dwType = TT_POLYGON_TYPE;
3987 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
3988 }
3989 needed += sizeof(*pph);
3990 point++;
3991 while (point <= outline->contours[contour])
3992 {
3993 ppc = (TTPOLYCURVE *)(buf + needed);
3994 type = (outline->tags[point] & FT_Curve_Tag_On) ?
3996 cpfx = 0;
3997 do
3998 {
3999 if (buf)
4000 FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
4001 cpfx++;
4002 point++;
4003 } while (point <= outline->contours[contour] &&
4004 (outline->tags[point] & FT_Curve_Tag_On) ==
4005 (outline->tags[point-1] & FT_Curve_Tag_On));
4006 /* At the end of a contour Windows adds the start point, but
4007 only for Beziers */
4008 if (point > outline->contours[contour] &&
4009 !(outline->tags[point-1] & FT_Curve_Tag_On))
4010 {
4011 if (buf)
4012 FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
4013 cpfx++;
4014 }
4015 else if (point <= outline->contours[contour] &&
4016 outline->tags[point] & FT_Curve_Tag_On)
4017 {
4018 /* add closing pt for bezier */
4019 if (buf)
4020 FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
4021 cpfx++;
4022 point++;
4023 }
4024 if (buf)
4025 {
4026 ppc->wType = type;
4027 ppc->cpfx = cpfx;
4028 }
4029 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
4030 }
4031 if (buf)
4032 pph->cb = needed - pph_start;
4033 }
4034 return needed;
4035}
4036
4037static unsigned int get_bezier_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
4038{
4039 /* Convert the quadratic Beziers to cubic Beziers.
4040 The parametric eqn for a cubic Bezier is, from PLRM:
4041 r(t) = at^3 + bt^2 + ct + r0
4042 with the control points:
4043 r1 = r0 + c/3
4044 r2 = r1 + (c + b)/3
4045 r3 = r0 + c + b + a
4046
4047 A quadratic Bezier has the form:
4048 p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
4049
4050 So equating powers of t leads to:
4051 r1 = 2/3 p1 + 1/3 p0
4052 r2 = 2/3 p1 + 1/3 p2
4053 and of course r0 = p0, r3 = p2
4054 */
4055 int contour, point = 0, first_pt;
4056 TTPOLYGONHEADER *pph;
4057 TTPOLYCURVE *ppc;
4058 DWORD pph_start, cpfx, type;
4059 FT_Vector cubic_control[4];
4060 unsigned int needed = 0;
4061
4062 for (contour = 0; contour < outline->n_contours; contour++)
4063 {
4064 pph_start = needed;
4065 pph = (TTPOLYGONHEADER *)(buf + needed);
4066 first_pt = point;
4067 if (buf)
4068 {
4069 pph->dwType = TT_POLYGON_TYPE;
4070 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
4071 }
4072 needed += sizeof(*pph);
4073 point++;
4074 while (point <= outline->contours[contour])
4075 {
4076 ppc = (TTPOLYCURVE *)(buf + needed);
4077 type = (outline->tags[point] & FT_Curve_Tag_On) ?
4079 cpfx = 0;
4080 do
4081 {
4082 if (type == TT_PRIM_LINE)
4083 {
4084 if (buf)
4085 FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
4086 cpfx++;
4087 point++;
4088 }
4089 else
4090 {
4091 /* Unlike QSPLINEs, CSPLINEs always have their endpoint
4092 so cpfx = 3n */
4093
4094 /* FIXME: Possible optimization in endpoint calculation
4095 if there are two consecutive curves */
4096 cubic_control[0] = outline->points[point-1];
4097 if (!(outline->tags[point-1] & FT_Curve_Tag_On))
4098 {
4099 cubic_control[0].x += outline->points[point].x + 1;
4100 cubic_control[0].y += outline->points[point].y + 1;
4101 cubic_control[0].x >>= 1;
4102 cubic_control[0].y >>= 1;
4103 }
4104 if (point+1 > outline->contours[contour])
4105 cubic_control[3] = outline->points[first_pt];
4106 else
4107 {
4108 cubic_control[3] = outline->points[point+1];
4109 if (!(outline->tags[point+1] & FT_Curve_Tag_On))
4110 {
4111 cubic_control[3].x += outline->points[point].x + 1;
4112 cubic_control[3].y += outline->points[point].y + 1;
4113 cubic_control[3].x >>= 1;
4114 cubic_control[3].y >>= 1;
4115 }
4116 }
4117 /* r1 = 1/3 p0 + 2/3 p1
4118 r2 = 1/3 p2 + 2/3 p1 */
4119 cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
4120 cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
4121 cubic_control[2] = cubic_control[1];
4122 cubic_control[1].x += (cubic_control[0].x + 1) / 3;
4123 cubic_control[1].y += (cubic_control[0].y + 1) / 3;
4124 cubic_control[2].x += (cubic_control[3].x + 1) / 3;
4125 cubic_control[2].y += (cubic_control[3].y + 1) / 3;
4126 if (buf)
4127 {
4128 FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
4129 FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
4130 FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
4131 }
4132 cpfx += 3;
4133 point++;
4134 }
4135 } while (point <= outline->contours[contour] &&
4136 (outline->tags[point] & FT_Curve_Tag_On) ==
4137 (outline->tags[point-1] & FT_Curve_Tag_On));
4138 /* At the end of a contour Windows adds the start point,
4139 but only for Beziers and we've already done that.
4140 */
4141 if (point <= outline->contours[contour] &&
4142 outline->tags[point] & FT_Curve_Tag_On)
4143 {
4144 /* This is the closing pt of a bezier, but we've already
4145 added it, so just inc point and carry on */
4146 point++;
4147 }
4148 if (buf)
4149 {
4150 ppc->wType = type;
4151 ppc->cpfx = cpfx;
4152 }
4153 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
4154 }
4155 if (buf)
4156 pph->cb = needed - pph_start;
4157 }
4158 return needed;
4159}
4160
4161static FT_Error
4162IntRequestFontSize(PDC dc, PFONTGDI FontGDI, LONG lfWidth, LONG lfHeight)
4163{
4166 FT_Face face = FontGDI->SharedFace->Face;
4167 TT_OS2 *pOS2;
4168 TT_HoriHeader *pHori;
4169 FT_WinFNT_HeaderRec WinFNT;
4170 LONG Ascent, Descent, Sum, EmHeight;
4171
4172 lfWidth = abs(lfWidth);
4173 if (lfHeight == 0)
4174 {
4175 if (lfWidth == 0)
4176 {
4177 DPRINT("lfHeight and lfWidth are zero.\n");
4178 lfHeight = -16;
4179 }
4180 else
4181 {
4182 lfHeight = lfWidth;
4183 }
4184 }
4185
4186 if (lfHeight == -1)
4187 lfHeight = -2;
4188
4189 if (FontGDI->Magic == FONTGDI_MAGIC &&
4190 FontGDI->lfHeight == lfHeight &&
4191 FontGDI->lfWidth == lfWidth)
4192 {
4193 return 0; /* Cached */
4194 }
4195
4199
4200 if (!pOS2 || !pHori)
4201 {
4202 error = FT_Get_WinFNT_Header(face, &WinFNT);
4203 if (error)
4204 {
4205 DPRINT1("%s: Failed to request font size.\n", face->family_name);
4206 return error;
4207 }
4208
4209 FontGDI->tmHeight = WinFNT.pixel_height;
4210 FontGDI->tmAscent = WinFNT.ascent;
4211 FontGDI->tmDescent = FontGDI->tmHeight - FontGDI->tmAscent;
4212 FontGDI->tmInternalLeading = WinFNT.internal_leading;
4213 FontGDI->Magic = FONTGDI_MAGIC;
4214 FontGDI->lfHeight = lfHeight;
4215 FontGDI->lfWidth = lfWidth;
4216 return 0;
4217 }
4218
4219 /*
4220 * NOTE: We cast TT_OS2.usWinAscent and TT_OS2.usWinDescent to signed FT_Short.
4221 * Why? See: https://learn.microsoft.com/en-us/typography/opentype/spec/os2#uswindescent
4222 *
4223 * > usWinDescent is "usually" a positive value ...
4224 *
4225 * We can read it as "not always". See CORE-14994.
4226 * See also: https://learn.microsoft.com/en-us/typography/opentype/spec/os2#fsselection
4227 */
4228#define FM_SEL_USE_TYPO_METRICS 0x80
4229 if (lfHeight > 0)
4230 {
4231 /* case (A): lfHeight is positive */
4232 Sum = (FT_Short)pOS2->usWinAscent + (FT_Short)pOS2->usWinDescent;
4233 if (Sum == 0 || (pOS2->fsSelection & FM_SEL_USE_TYPO_METRICS))
4234 {
4235 Ascent = pHori->Ascender;
4236 Descent = -pHori->Descender;
4237 Sum = Ascent + Descent;
4238 }
4239 else
4240 {
4241 Ascent = (FT_Short)pOS2->usWinAscent;
4242 Descent = (FT_Short)pOS2->usWinDescent;
4243 }
4244
4245 FontGDI->tmAscent = FT_MulDiv(lfHeight, Ascent, Sum);
4246 FontGDI->tmDescent = FT_MulDiv(lfHeight, Descent, Sum);
4247 FontGDI->tmHeight = FontGDI->tmAscent + FontGDI->tmDescent;
4248 FontGDI->tmInternalLeading = FontGDI->tmHeight - FT_MulDiv(lfHeight, face->units_per_EM, Sum);
4249 }
4250 else if (lfHeight < 0)
4251 {
4252 /* case (B): lfHeight is negative */
4254 {
4255 FontGDI->tmAscent = FT_MulDiv(-lfHeight, pHori->Ascender, face->units_per_EM);
4256 FontGDI->tmDescent = FT_MulDiv(-lfHeight, -pHori->Descender, face->units_per_EM);
4257 }
4258 else
4259 {
4260 FontGDI->tmAscent = FT_MulDiv(-lfHeight, (FT_Short)pOS2->usWinAscent, face->units_per_EM);
4261 FontGDI->tmDescent = FT_MulDiv(-lfHeight, (FT_Short)pOS2->usWinDescent, face->units_per_EM);
4262 }
4263 FontGDI->tmHeight = FontGDI->tmAscent + FontGDI->tmDescent;
4264 FontGDI->tmInternalLeading = FontGDI->tmHeight + lfHeight;
4265 }
4266#undef FM_SEL_USE_TYPO_METRICS
4267
4268 FontGDI->Magic = FONTGDI_MAGIC;
4269 FontGDI->lfHeight = lfHeight;
4270 FontGDI->lfWidth = lfWidth;
4271
4272 EmHeight = FontGDI->tmHeight - FontGDI->tmInternalLeading;
4273 EmHeight = max(EmHeight, 1);
4274 EmHeight = min(EmHeight, USHORT_MAX);
4275
4276#if 1
4277 /* I think this is wrong implementation but its test result is better. */
4278 if (lfWidth != 0)
4279 req.width = FT_MulDiv(lfWidth, face->units_per_EM, pOS2->xAvgCharWidth) << 6;
4280#else
4281 /* I think this is correct implementation but it is mismatching to the
4282 other metric functions. The test result is bad. */
4283 if (lfWidth != 0)
4284 req.width = (FT_MulDiv(lfWidth, 96 * 5, 72 * 3) << 6); /* ??? FIXME */
4285#endif
4286 else
4287 req.width = 0;
4288
4289 /* HACK: We do not handle small widths well, so just use zero for these. See CORE-19870. */
4290 if (lfWidth < 10)
4291 req.width = 0;
4292
4294 req.height = (EmHeight << 6);
4295 req.horiResolution = 0;
4296 req.vertResolution = 0;
4297 return FT_Request_Size(face, &req);
4298}
4299
4300BOOL
4303 PTEXTOBJ TextObj,
4304 PFONTGDI FontGDI,
4305 BOOL bDoLock)
4306{
4307 FT_Face face;
4308 INT error, n;
4309 FT_CharMap charmap, found;
4310 LOGFONTW *plf;
4311
4312 if (bDoLock)
4314
4315 face = FontGDI->SharedFace->Face;
4316 if (face->charmap == NULL)
4317 {
4318 DPRINT("WARNING: No charmap selected!\n");
4319 DPRINT("This font face has %d charmaps\n", face->num_charmaps);
4320
4321 found = NULL;
4322 for (n = 0; n < face->num_charmaps; n++)
4323 {
4324 charmap = face->charmaps[n];
4325 if (charmap->encoding == FT_ENCODING_UNICODE)
4326 {
4327 found = charmap;
4328 break;
4329 }
4330 }
4331 if (!found)
4332 {
4333 for (n = 0; n < face->num_charmaps; n++)
4334 {
4335 charmap = face->charmaps[n];
4336 if (charmap->platform_id == TT_PLATFORM_APPLE_UNICODE)
4337 {
4338 found = charmap;
4339 break;
4340 }
4341 }
4342 }
4343 if (!found)
4344 {
4345 for (n = 0; n < face->num_charmaps; n++)
4346 {
4347 charmap = face->charmaps[n];
4348 if (charmap->encoding == FT_ENCODING_MS_SYMBOL)
4349 {
4350 found = charmap;
4351 break;
4352 }
4353 }
4354 }
4355 if (!found && face->num_charmaps > 0)
4356 {
4357 found = face->charmaps[0];
4358 }
4359 if (!found)
4360 {
4361 DPRINT1("WARNING: Could not find desired charmap!\n");
4362 }
4363 else
4364 {
4365 DPRINT("Found charmap encoding: %i\n", found->encoding);
4366 error = FT_Set_Charmap(face, found);
4367 if (error)
4368 {
4369 DPRINT1("WARNING: Could not set the charmap!\n");
4370 }
4371 }
4372 }
4373
4374 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
4375
4376 error = IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
4377
4378 if (bDoLock)
4380
4381 if (error)
4382 {
4383 DPRINT1("Error in setting pixel sizes: %d\n", error);
4384 return FALSE;
4385 }
4386
4387 return TRUE;
4388}
4389
4390static inline FT_UInt FASTCALL
4392{
4393 FT_UInt ret;
4394
4395 if (glyph < 0x100) glyph += 0xf000;
4396 /* there are a number of old pre-Unicode "broken" TTFs, which
4397 do have symbols at U+00XX instead of U+f0XX */
4398 if (!(ret = FT_Get_Char_Index(ft_face, glyph)))
4399 ret = FT_Get_Char_Index(ft_face, glyph - 0xf000);
4400
4401 return ret;
4402}
4403
4404static inline FT_UInt FASTCALL
4406{
4407 FT_UInt ret;
4408
4409 if (face_has_symbol_charmap(ft_face))
4410 {
4411 ret = get_glyph_index_symbol(ft_face, glyph);
4412 if (ret != 0)
4413 return ret;
4414 }
4415
4416 return FT_Get_Char_Index(ft_face, glyph);
4417}
4418
4419static inline FT_UInt FASTCALL
4421{
4422 return (fCodeAsIndex ? code : get_glyph_index(face, code));
4423}
4424
4425static inline VOID
4427 _In_ PFONTLINK_CHAIN pChain)
4428{
4429#if 0
4430 PLIST_ENTRY Entry, Head;
4431 PFONTLINK pFontLink;
4432 INT iLink = 0;
4433
4434 DPRINT1("%S, %p, %p\n", pChain->LogFont.lfFaceName, pChain->pBaseTextObj, pChain->pDefFace);
4435
4436 Head = &pChain->FontLinkList;
4437 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
4438 {
4439 pFontLink = CONTAINING_RECORD(Entry, FONTLINK, ListEntry);
4440 DPRINT1("FontLink #%d: %p, %d, %S, %p, %p\n",
4441 iLink, pFontLink, pFontLink->bIgnore, pFontLink->LogFont.lfFaceName,
4442 pFontLink->pFontGDI, pFontLink->SharedFace);
4443 ++iLink;
4444 }
4445#endif
4446}
4447
4450static UINT
4452 _Inout_ PFONTLINK_CHAIN pChain,
4453 _Out_ PFONT_CACHE_ENTRY pCache,
4454 _Inout_ FT_Face *pFace,
4455 _In_ UINT code,
4456 _In_ BOOL fCodeAsIndex)
4457{
4458 PFONTLINK pFontLink;
4459 PLIST_ENTRY Entry, Head;
4460 UINT index;
4461 FT_Face face;
4462
4463 // Try the default font at first
4464 index = get_glyph_index_flagged(pChain->pDefFace, code, fCodeAsIndex);
4465 if (index)
4466 {
4467 DPRINT("code: 0x%08X, index: 0x%08X, fCodeAsIndex:%d\n", code, index, fCodeAsIndex);
4468 pCache->Hashed.Face = *pFace = pChain->pDefFace;
4469 return index; // The glyph is found on the default font
4470 }
4471
4472 if (!FontLink_Chain_IsPopulated(pChain)) // The chain is not populated yet
4473 {
4475 FontLink_Chain_Dump(pChain);
4476 }
4477
4478 // Now the chain is populated. Looking for the target glyph...
4479 Head = &pChain->FontLinkList;
4480 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
4481 {
4482 pFontLink = CONTAINING_RECORD(Entry, FONTLINK, ListEntry);
4483 if (!FontLink_PrepareFontInfo(pFontLink))
4484 continue; // This link is not useful, check the next one
4485
4486 face = pFontLink->SharedFace->Face;
4488 if (!index)
4489 continue; // The glyph does not exist, continue searching
4490
4491 // The target glyph is found in the chain
4492 DPRINT("code: 0x%08X, index: 0x%08X\n", code, index);
4493 pCache->Hashed.Face = *pFace = face;
4494 FT_Set_Transform(face, &pCache->Hashed.matTransform, NULL);
4495 return index;
4496 }
4497
4498 // No target glyph found in the chain: use default glyph
4500 index = get_glyph_index(*pFace, code);
4501 DPRINT("code: 0x%08X, index: 0x%08X\n", code, index);
4502 pCache->Hashed.Face = *pFace = pChain->pDefFace;
4503 return index;
4504}
4505
4506/*
4507 * Based on WineEngGetGlyphOutline
4508 */
4509ULONG
4512 PDC dc,
4513 WCHAR wch,
4514 UINT iFormat,
4515 LPGLYPHMETRICS pgm,
4516 ULONG cjBuf,
4517 PVOID pvBuf,
4518 LPMAT2 pmat2,
4519 BOOL bIgnoreRotation)
4520{
4521 PDC_ATTR pdcattr;
4522 PTEXTOBJ TextObj;
4523 PFONTGDI FontGDI;
4524 HFONT hFont = 0;
4525 GLYPHMETRICS gm;
4526 ULONG Size;
4527 FT_Face ft_face;
4528 FT_UInt glyph_index;
4529 DWORD width, height, pitch, needed = 0;
4530 FT_Bitmap ft_bitmap;
4532 INT left, right, top = 0, bottom = 0;
4534 FLOATOBJ eM11, widthRatio, eTemp;
4535 FT_Matrix mat, transMat = identityMat;
4536 BOOL needsTransform = FALSE;
4537 INT orientation;
4538 LONG aveWidth;
4539 INT adv, lsb, bbx; /* These three hold to widths of the unrotated chars */
4540 OUTLINETEXTMETRICW *potm;
4541 XFORMOBJ xo;
4542 XFORML xform;
4543 LOGFONTW *plf;
4544
4545 DPRINT("%u, %08x, %p, %08lx, %p, %p\n", wch, iFormat, pgm,
4546 cjBuf, pvBuf, pmat2);
4547
4548 pdcattr = dc->pdcattr;
4549
4550 XFORMOBJ_vInit(&xo, &dc->pdcattr->mxWorldToDevice);
4551 XFORMOBJ_iGetXform(&xo, &xform);
4552 FLOATOBJ_SetFloat(&eM11, xform.eM11);
4553
4554 hFont = pdcattr->hlfntNew;
4555 TextObj = RealizeFontInit(hFont);
4556
4557 if (!TextObj)
4558 {
4560 return GDI_ERROR;
4561 }
4562 FontGDI = ObjToGDI(TextObj->Font, FONT);
4563 ft_face = FontGDI->SharedFace->Face;
4564
4565 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
4566 aveWidth = FT_IS_SCALABLE(ft_face) ? abs(plf->lfWidth) : 0;
4567 orientation = FT_IS_SCALABLE(ft_face) ? plf->lfOrientation : 0;
4568
4570 Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL, FALSE);
4571 if (!Size)
4572 {
4573 TEXTOBJ_UnlockText(TextObj);
4575 return GDI_ERROR;
4576 }
4578 if (!potm)
4579 {
4580 TEXTOBJ_UnlockText(TextObj);
4582 return GDI_ERROR;
4583 }
4585 Size = IntGetOutlineTextMetrics(FontGDI, Size, potm, FALSE);
4586 if (!Size)
4587 {
4589 TEXTOBJ_UnlockText(TextObj);
4591 return GDI_ERROR;
4592 }
4593
4595 TextIntUpdateSize(dc, TextObj, FontGDI, FALSE);
4597 FT_Set_Transform(ft_face, &mat, NULL);
4598
4599 TEXTOBJ_UnlockText(TextObj);
4600
4601 glyph_index = get_glyph_index_flagged(ft_face, wch, (iFormat & GGO_GLYPH_INDEX));
4602 iFormat &= ~GGO_GLYPH_INDEX;
4603
4604 if (orientation || (iFormat != GGO_METRICS && iFormat != GGO_BITMAP) || aveWidth || pmat2)
4605 load_flags |= FT_LOAD_NO_BITMAP;
4606
4607 if (iFormat & GGO_UNHINTED)
4608 {
4609 load_flags |= FT_LOAD_NO_HINTING;
4610 iFormat &= ~GGO_UNHINTED;
4611 }
4612
4613 error = FT_Load_Glyph(ft_face, glyph_index, load_flags);
4614 if (error)
4615 {
4616 DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
4618 if (potm) ExFreePoolWithTag(potm, GDITAG_TEXT);
4619 return GDI_ERROR;
4620 }
4622
4623 FLOATOBJ_Set1(&widthRatio);
4624 if (aveWidth && potm)
4625 {
4626 // widthRatio = aveWidth * eM11 / potm->otmTextMetrics.tmAveCharWidth
4627 FLOATOBJ_SetLong(&widthRatio, aveWidth);
4628 FLOATOBJ_Mul(&widthRatio, &eM11);
4630 }
4631
4632 //left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64;
4633 FLOATOBJ_SetLong(&eTemp, ft_face->glyph->metrics.horiBearingX);
4634 FLOATOBJ_Mul(&eTemp, &widthRatio);
4635 left = FLOATOBJ_GetLong(&eTemp) & -64;
4636
4637 //right = (INT)((ft_face->glyph->metrics.horiBearingX +
4638 // ft_face->glyph->metrics.width) * widthRatio + 63) & -64;
4639 FLOATOBJ_SetLong(&eTemp, ft_face->glyph->metrics.horiBearingX * ft_face->glyph->metrics.width);
4640 FLOATOBJ_Mul(&eTemp, &widthRatio);
4641 FLOATOBJ_AddLong(&eTemp, 63);
4642 right = FLOATOBJ_GetLong(&eTemp) & -64;
4643
4644 //adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6;
4645 FLOATOBJ_SetLong(&eTemp, ft_face->glyph->metrics.horiAdvance);
4646 FLOATOBJ_Mul(&eTemp, &widthRatio);
4647 FLOATOBJ_AddLong(&eTemp, 63);
4648 adv = FLOATOBJ_GetLong(&eTemp) >> 6;
4649
4650 lsb = left >> 6;
4651 bbx = (right - left) >> 6;
4652
4653 DPRINT("Advance = %d, lsb = %d, bbx = %d\n",adv, lsb, bbx);
4654
4656
4657 /* Width scaling transform */
4658 if (!FLOATOBJ_Equal1(&widthRatio))
4659 {
4660 FT_Matrix scaleMat;
4661
4662 eTemp = widthRatio;
4663 FLOATOBJ_MulLong(&eTemp, 1 << 16);
4664
4665 scaleMat.xx = FLOATOBJ_GetLong(&eTemp);
4666 scaleMat.xy = 0;
4667 scaleMat.yx = 0;
4668 scaleMat.yy = INT_TO_FIXED(1);
4669 FT_Matrix_Multiply(&scaleMat, &transMat);
4670 needsTransform = TRUE;
4671 }
4672
4673 /* World transform */
4674 {
4675 FT_Matrix ftmatrix;
4677
4678 /* Create a freetype matrix, by converting to 16.16 fixpoint format */
4679 IntMatrixFromMx(&ftmatrix, pmx);
4680
4681 if (memcmp(&ftmatrix, &identityMat, sizeof(identityMat)) != 0)
4682 {
4683 FT_Matrix_Multiply(&ftmatrix, &transMat);
4684 needsTransform = TRUE;
4685 }
4686 }
4687
4688 /* Rotation transform */
4689 if (orientation)
4690 {
4691 FT_Matrix rotationMat;
4692 DPRINT("Rotation Trans!\n");
4693 IntEscapeMatrix(&rotationMat, orientation);
4694 FT_Matrix_Multiply(&rotationMat, &transMat);
4695 needsTransform = TRUE;
4696 }
4697
4698 /* Extra transformation specified by caller */
4699 if (pmat2)
4700 {
4701 FT_Matrix extraMat;
4702 DPRINT("MAT2 Matrix Trans!\n");
4703 extraMat.xx = FT_FixedFromFIXED(pmat2->eM11);
4704 extraMat.xy = FT_FixedFromFIXED(pmat2->eM21);
4705 extraMat.yx = FT_FixedFromFIXED(pmat2->eM12);
4706 extraMat.yy = FT_FixedFromFIXED(pmat2->eM22);
4707 FT_Matrix_Multiply(&extraMat, &transMat);
4708 needsTransform = TRUE;
4709 }
4710
4711 if (potm) ExFreePoolWithTag(potm, GDITAG_TEXT); /* It looks like we are finished with potm ATM. */
4712
4713 if (!needsTransform)
4714 {
4715 DPRINT("No Need to be Transformed!\n");
4716 top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
4717 bottom = (ft_face->glyph->metrics.horiBearingY -
4718 ft_face->glyph->metrics.height) & -64;
4719 gm.gmCellIncX = adv;
4720 gm.gmCellIncY = 0;
4721 }
4722 else
4723 {
4724 INT xc, yc;
4725 FT_Vector vec;
4726 for (xc = 0; xc < 2; xc++)
4727 {
4728 for (yc = 0; yc < 2; yc++)
4729 {
4730 vec.x = (ft_face->glyph->metrics.horiBearingX +
4731 xc * ft_face->glyph->metrics.width);
4732 vec.y = ft_face->glyph->metrics.horiBearingY -
4733 yc * ft_face->glyph->metrics.height;
4734 DPRINT("Vec %ld,%ld\n", vec.x, vec.y);
4735 FT_Vector_Transform(&vec, &transMat);
4736 if (xc == 0 && yc == 0)
4737 {
4738 left = right = vec.x;
4739 top = bottom = vec.y;
4740 }
4741 else
4742 {
4743 if (vec.x < left) left = vec.x;
4744 else if (vec.x > right) right = vec.x;
4745 if (vec.y < bottom) bottom = vec.y;
4746 else if (vec.y > top) top = vec.y;
4747 }
4748 }
4749 }
4750 left = left & -64;
4751 right = (right + 63) & -64;
4752 bottom = bottom & -64;
4753 top = (top + 63) & -64;
4754
4755 DPRINT("Transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
4756 vec.x = ft_face->glyph->metrics.horiAdvance;
4757 vec.y = 0;
4758 FT_Vector_Transform(&vec, &transMat);
4759 gm.gmCellIncX = (vec.x+63) >> 6;
4760 gm.gmCellIncY = -((vec.y+63) >> 6);
4761 }
4762 gm.gmBlackBoxX = (right - left) >> 6;
4763 gm.gmBlackBoxY = (top - bottom) >> 6;
4764 gm.gmptGlyphOrigin.x = left >> 6;
4765 gm.gmptGlyphOrigin.y = top >> 6;
4766
4767 DPRINT("CX %d CY %d BBX %u BBY %u GOX %d GOY %d\n",
4768 gm.gmCellIncX, gm.gmCellIncY,
4769 gm.gmBlackBoxX, gm.gmBlackBoxY,
4771
4773
4774 if (iFormat == GGO_METRICS)
4775 {
4776 DPRINT("GGO_METRICS Exit!\n");
4777 *pgm = gm;
4778 return 1; /* FIXME */
4779 }
4780
4781 if (ft_face->glyph->format != ft_glyph_format_outline && iFormat != GGO_BITMAP)
4782 {
4783 DPRINT1("Loaded a bitmap\n");
4784 return GDI_ERROR;
4785 }
4786
4787 switch (iFormat)
4788 {
4789 case GGO_BITMAP:
4790 {
4791 width = gm.gmBlackBoxX;
4792 height = gm.gmBlackBoxY;
4793 pitch = ((width + 31) >> 5) << 2;
4794 needed = pitch * height;
4795
4796 if (!pvBuf || !cjBuf) break;
4797 if (!needed) return GDI_ERROR; /* empty glyph */
4798 if (needed > cjBuf)
4799 return GDI_ERROR;
4800
4801 switch (ft_face->glyph->format)
4802 {
4804 {
4805 BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
4806 INT w = min( pitch, (ft_face->glyph->bitmap.width + 7) >> 3 );
4807 INT h = min( height, ft_face->glyph->bitmap.rows );
4808 while (h--)
4809 {
4811 src += ft_face->glyph->bitmap.pitch;
4812 dst += pitch;
4813 }
4814 break;
4815 }
4816
4818 {
4819 ft_bitmap.width = width;
4820 ft_bitmap.rows = height;
4821 ft_bitmap.pitch = pitch;
4822 ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
4823 ft_bitmap.buffer = pvBuf;
4824
4826 if (needsTransform)
4827 {
4828 FT_Outline_Transform(&ft_face->glyph->outline, &transMat);
4829 }
4830 FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
4831 /* Note: FreeType will only set 'black' bits for us. */
4832 RtlZeroMemory(pvBuf, needed);
4833 FT_Outline_Get_Bitmap(g_FreeTypeLibrary, &ft_face->glyph->outline, &ft_bitmap);
4835 break;
4836 }
4837
4838 default:
4839 DPRINT1("Loaded glyph format %x\n", ft_face->glyph->format);
4840 return GDI_ERROR;
4841 }
4842
4843 break;
4844 }
4845
4846 case GGO_GRAY2_BITMAP:
4847 case GGO_GRAY4_BITMAP:
4848 case GGO_GRAY8_BITMAP:
4849 {
4850 unsigned int mult, row, col;
4851 BYTE *start, *ptr;
4852
4853 width = gm.gmBlackBoxX;
4854 height = gm.gmBlackBoxY;
4855 pitch = (width + 3) / 4 * 4;
4856 needed = pitch * height;
4857
4858 if (!pvBuf || !cjBuf) break;
4859 if (!needed) return GDI_ERROR; /* empty glyph */
4860 if (needed > cjBuf)
4861 return GDI_ERROR;
4862
4863 switch (ft_face->glyph->format)
4864 {
4866 {
4867 BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
4868 INT h = min( height, ft_face->glyph->bitmap.rows );
4869 INT x;
4870 while (h--)
4871 {
4872 for (x = 0; (UINT)x < pitch; x++)
4873 {
4874 if (x < ft_face->glyph->bitmap.width)
4875 dst[x] = (src[x / 8] & (1 << ( (7 - (x % 8))))) ? 0xff : 0;
4876 else
4877 dst[x] = 0;
4878 }
4879 src += ft_face->glyph->bitmap.pitch;
4880 dst += pitch;
4881 }
4882 break;
4883 }
4885 {
4886 ft_bitmap.width = width;
4887 ft_bitmap.rows = height;
4888 ft_bitmap.pitch = pitch;
4889 ft_bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
4890 ft_bitmap.buffer = pvBuf;
4891
4893 if (needsTransform)
4894 {
4895 FT_Outline_Transform(&ft_face->glyph->outline, &transMat);
4896 }
4897 FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
4898 RtlZeroMemory(ft_bitmap.buffer, cjBuf);
4899 FT_Outline_Get_Bitmap(g_FreeTypeLibrary, &ft_face->glyph->outline, &ft_bitmap);
4901
4903 mult = 4;
4904 else if (iFormat == GGO_GRAY4_BITMAP)
4905 mult = 16;
4906 else if (iFormat == GGO_GRAY8_BITMAP)
4907 mult = 64;
4908 else
4909 {
4910 return GDI_ERROR;
4911 }
4912
4913 start = pvBuf;
4914 for (row = 0; row < height; row++)
4915 {
4916 ptr = start;
4917 for (col = 0; col < width; col++, ptr++)
4918 {
4919 *ptr = (((int)*ptr) * mult + 128) / 256;
4920 }
4921 start += pitch;
4922 }
4923
4924 break;
4925 }
4926 default:
4927 DPRINT1("Loaded glyph format %x\n", ft_face->glyph->format);
4928 return GDI_ERROR;
4929 }
4930
4931 break;
4932 }
4933
4934 case GGO_NATIVE:
4935 {
4936 FT_Outline *outline = &ft_face->glyph->outline;
4937
4938 if (cjBuf == 0) pvBuf = NULL; /* This is okay, need cjBuf to allocate. */
4939
4941 if (needsTransform && pvBuf) FT_Outline_Transform(outline, &transMat);
4942
4944
4945 if (!pvBuf || !cjBuf)
4946 {
4948 break;
4949 }
4950 if (needed > cjBuf)
4951 {
4953 return GDI_ERROR;
4954 }
4957 break;
4958 }
4959
4960 case GGO_BEZIER:
4961 {
4962 FT_Outline *outline = &ft_face->glyph->outline;
4963 if (cjBuf == 0) pvBuf = NULL;
4964
4965 if (needsTransform && pvBuf)
4966 {
4968 FT_Outline_Transform(outline, &transMat);
4970 }
4972
4973 if (!pvBuf || !cjBuf)
4974 break;
4975 if (needed > cjBuf)
4976 return GDI_ERROR;
4977
4979 break;
4980 }
4981
4982 default:
4983 DPRINT1("Unsupported format %u\n", iFormat);
4984 return GDI_ERROR;
4985 }
4986
4987 DPRINT("ftGdiGetGlyphOutline END and needed %lu\n", needed);
4988
4989 if (gm.gmBlackBoxX == 0)
4990 gm.gmBlackBoxX = 1;
4991 if (gm.gmBlackBoxY == 0)
4992 gm.gmBlackBoxY = 1;
4993
4994 *pgm = gm;
4995 return needed;
4996}
4997
4998static FT_BitmapGlyph
5001{
5002 INT error;
5003 FT_GlyphSlot glyph;
5004 FT_BitmapGlyph realglyph;
5005
5007
5008 Cache->dwHash = IntGetHash(&Cache->Hashed, sizeof(Cache->Hashed) / sizeof(DWORD));
5009
5010 realglyph = IntFindGlyphCache(Cache);
5011 if (realglyph)
5012 return realglyph;
5013
5014 error = FT_Load_Glyph(Cache->Hashed.Face, Cache->Hashed.GlyphIndex, FT_LOAD_DEFAULT);
5015 if (error)
5016 {
5017 DPRINT1("WARNING: Failed to load and render glyph! [index: %d]\n", Cache->Hashed.GlyphIndex);
5018 return NULL;
5019 }
5020
5021 glyph = Cache->Hashed.Face->glyph;
5022
5023 if (Cache->Hashed.Aspect.Emu.Bold)
5024 FT_GlyphSlot_Embolden(glyph); /* Emulate Bold */
5025
5026 if (Cache->Hashed.Aspect.Emu.Italic)
5027 FT_GlyphSlot_Oblique(glyph); /* Emulate Italic */
5028
5029 realglyph = IntGetBitmapGlyphWithCache(Cache, glyph);
5030
5031 if (!realglyph)
5032 DPRINT1("Failed to render glyph! [index: %d]\n", Cache->Hashed.GlyphIndex);
5033
5034 return realglyph;
5035}
5036
5037BOOL
5040 PTEXTOBJ TextObj,
5042 INT Count,
5043 ULONG MaxExtent,
5044 LPINT Fit,
5045 LPINT Dx,
5046 LPSIZE Size,
5047 FLONG fl)
5048{
5049 PFONTGDI FontGDI;
5050 FT_BitmapGlyph realglyph;
5051 INT glyph_index, i, previous, nTenthsOfDegrees;
5052 ULONGLONG TotalWidth64 = 0;
5053 LOGFONTW *plf;
5054 BOOL use_kerning, bVerticalWriting;
5055 LONG ascender, descender;
5057 DWORD ch0, ch1;
5058 FONTLINK_CHAIN Chain;
5059
5060 FontGDI = ObjToGDI(TextObj->Font, FONT);
5061
5062 Cache.Hashed.Face = FontGDI->SharedFace->Face;
5063 if (NULL != Fit)
5064 {
5065 *Fit = 0;
5066 }
5067
5068 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
5069 Cache.Hashed.lfHeight = plf->lfHeight;
5070 Cache.Hashed.lfWidth = plf->lfWidth;
5071 Cache.Hashed.Aspect.Emu.Bold = EMUBOLD_NEEDED(FontGDI->OriginalWeight, plf->lfWeight);
5072 Cache.Hashed.Aspect.Emu.Italic = (plf->lfItalic && !FontGDI->OriginalItalic);
5073
5074 // Check vertical writing (tategaki)
5075 nTenthsOfDegrees = IntNormalizeAngle(plf->lfEscapement - plf->lfOrientation);
5076 bVerticalWriting = ((nTenthsOfDegrees == 90 * 10) || (nTenthsOfDegrees == 270 * 10));
5077
5079 Cache.Hashed.Aspect.RenderMode = (BYTE)IntGetFontRenderMode(plf);
5080 else
5081 Cache.Hashed.Aspect.RenderMode = (BYTE)FT_RENDER_MODE_MONO;
5082
5083 // NOTE: GetTextExtentPoint32 simply ignores lfEscapement and XFORM.
5085 TextIntUpdateSize(dc, TextObj, FontGDI, FALSE);
5086 Cache.Hashed.matTransform = identityMat;
5087 FT_Set_Transform(Cache.Hashed.Face, NULL, NULL);
5088
5089 FontLink_Chain_Init(&Chain, TextObj, Cache.Hashed.Face);
5090
5091 use_kerning = FT_HAS_KERNING(Cache.Hashed.Face);
5092 previous = 0;
5093
5094 for (i = 0; i < Count; i++)
5095 {
5096 ch0 = *String++;
5097 if (IS_HIGH_SURROGATE(ch0))
5098 {
5099 ++i;
5100 if (i >= Count)
5101 break;
5102
5103 ch1 = *String++;
5104 if (IS_LOW_SURROGATE(ch1))
5105 ch0 = Utf32FromSurrogatePair(ch0, ch1);
5106 }
5107
5108 glyph_index = FontLink_Chain_FindGlyph(&Chain, &Cache, &Cache.Hashed.Face, ch0,
5109 (fl & GTEF_INDICES));
5110 Cache.Hashed.GlyphIndex = glyph_index;
5111
5112 realglyph = IntGetRealGlyph(&Cache);
5113 if (!realglyph)
5114 break;
5115
5116 /* Retrieve kerning distance */
5117 if (use_kerning && previous && glyph_index)
5118 {
5119 FT_Vector delta;
5120 FT_Get_Kerning(Cache.Hashed.Face, previous, glyph_index, 0, &delta);
5121 TotalWidth64 += delta.x;
5122 }
5123
5124 TotalWidth64 += realglyph->root.advance.x >> 10;
5125
5126 if (((TotalWidth64 + 32) >> 6) <= MaxExtent && NULL != Fit)
5127 {
5128 *Fit = i + 1;
5129 }
5130 if (NULL != Dx)
5131 {
5132 Dx[i] = (TotalWidth64 + 32) >> 6;
5133 }
5134
5135 previous = glyph_index;
5136 }
5137 ASSERT(FontGDI->Magic == FONTGDI_MAGIC);
5138 ascender = FontGDI->tmAscent; /* Units above baseline */
5139 descender = FontGDI->tmDescent; /* Units below baseline */
5141
5142 if (bVerticalWriting)
5143 {
5144 Size->cx = ascender + descender;
5145 Size->cy = (TotalWidth64 + 32) >> 6;
5146 }
5147 else
5148 {
5149 Size->cx = (TotalWidth64 + 32) >> 6;
5150 Size->cy = ascender + descender;
5151 }
5152
5153 FontLink_Chain_Finish(&Chain);
5154
5155 return TRUE;
5156}
5157
5158
5159INT
5162 PDC Dc,
5163 LPFONTSIGNATURE lpSig,
5164 DWORD dwFlags)
5165{
5166 PDC_ATTR pdcattr;
5167 UINT Ret = DEFAULT_CHARSET;
5168 INT i;
5169 HFONT hFont;
5170 PTEXTOBJ TextObj;
5171 PFONTGDI FontGdi;
5173 TT_OS2 *pOS2;
5174 FT_Face Face;
5175 CHARSETINFO csi;
5176 DWORD cp, fs0;
5177 USHORT usACP, usOEM;
5178
5179 pdcattr = Dc->pdcattr;
5180 hFont = pdcattr->hlfntNew;
5181 TextObj = RealizeFontInit(hFont);
5182
5183 if (!TextObj)
5184 {
5186 return Ret;
5187 }
5188 FontGdi = ObjToGDI(TextObj->Font, FONT);
5189 Face = FontGdi->SharedFace->Face;
5190 TEXTOBJ_UnlockText(TextObj);
5191
5192 memset(&fs, 0, sizeof(FONTSIGNATURE));
5194 pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
5195 if (NULL != pOS2)
5196 {
5197 fs.fsCsb[0] = pOS2->ulCodePageRange1;
5198 fs.fsCsb[1] = pOS2->ulCodePageRange2;
5199 fs.fsUsb[0] = pOS2->ulUnicodeRange1;
5200 fs.fsUsb[1] = pOS2->ulUnicodeRange2;
5201 fs.fsUsb[2] = pOS2->ulUnicodeRange3;
5202 fs.fsUsb[3] = pOS2->ulUnicodeRange4;
5203 if (pOS2->version == 0)
5204 {
5205 FT_UInt dummy;
5206
5207 if (FT_Get_First_Char( Face, &dummy ) < 0x100)
5208 fs.fsCsb[0] |= FS_LATIN1;
5209 else
5210 fs.fsCsb[0] |= FS_SYMBOL;
5211 }
5212 }
5213 pOS2 = NULL;
5215 DPRINT("Csb 1=%x 0=%x\n", fs.fsCsb[1],fs.fsCsb[0]);
5216 if (fs.fsCsb[0] == 0)
5217 { /* Let's see if we can find any interesting cmaps */
5218 for (i = 0; i < Face->num_charmaps; i++)
5219 {
5220 switch (Face->charmaps[i]->encoding)
5221 {
5222 case FT_ENCODING_UNICODE:
5223 case FT_ENCODING_APPLE_ROMAN:
5224 fs.fsCsb[0] |= FS_LATIN1;
5225 break;
5226 case FT_ENCODING_MS_SYMBOL:
5227 fs.fsCsb[0] |= FS_SYMBOL;
5228 break;
5229 default:
5230 break;
5231 }
5232 }
5233 }
5234 if (lpSig)
5235 {
5236 RtlCopyMemory(lpSig, &fs, sizeof(FONTSIGNATURE));
5237 }
5238
5239 RtlGetDefaultCodePage(&usACP, &usOEM);
5240 cp = usACP;
5241
5243 if (csi.fs.fsCsb[0] & fs.fsCsb[0])
5244 {
5245 DPRINT("Hit 1\n");
5246 Ret = csi.ciCharset;
5247 goto Exit;
5248 }
5249
5250 for (i = 0; i < MAXTCIINDEX; i++)
5251 {
5252 fs0 = 1L << i;
5253 if (fs.fsCsb[0] & fs0)
5254 {
5255 if (IntTranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG))
5256 {
5257 // *cp = csi.ciACP;
5258 DPRINT("Hit 2\n");
5259 Ret = csi.ciCharset;
5260 goto Exit;
5261 }
5262 else
5263 DPRINT1("TCI failing on %x\n", fs0);
5264 }
5265 }
5266Exit:
5267 DPRINT("CharSet %u CodePage %u\n", csi.ciCharset, csi.ciACP);
5268 return (MAKELONG(csi.ciACP, csi.ciCharset));
5269}
5270
5271
5272DWORD
5275{
5276 DWORD size = 0;
5277 DWORD num_ranges = 0;
5278 FT_Face face = Font->SharedFace->Face;
5279
5280 if (face->charmap == NULL)
5281 {
5282 DPRINT1("FIXME: No charmap selected! This is a BUG!\n");
5283 return 0;
5284 }
5285
5286 if (face->charmap->encoding == FT_ENCODING_UNICODE)
5287 {
5288 FT_UInt glyph_code = 0;
5289 FT_ULong char_code, char_code_prev;
5290
5291 char_code_prev = char_code = FT_Get_First_Char(face, &glyph_code);
5292
5293 DPRINT("Face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
5294 face->num_glyphs, glyph_code, char_code);
5295
5296 if (!glyph_code) return 0;
5297
5298 if (glyphset)
5299 {
5300 glyphset->ranges[0].wcLow = (USHORT)char_code;
5301 glyphset->ranges[0].cGlyphs = 0;
5302 glyphset->cGlyphsSupported = 0;
5303 }
5304
5305 num_ranges = 1;
5306 while (glyph_code)
5307 {
5308 if (char_code < char_code_prev)
5309 {
5310 DPRINT1("Expected increasing char code from FT_Get_Next_Char\n");
5311 return 0;
5312 }
5313 if (char_code - char_code_prev > 1)
5314 {
5315 num_ranges++;
5316 if (glyphset)
5317 {
5318 glyphset->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
5319 glyphset->ranges[num_ranges - 1].cGlyphs = 1;
5320 glyphset->cGlyphsSupported++;
5321 }
5322 }
5323 else if (glyphset)
5324 {
5325 glyphset->ranges[num_ranges - 1].cGlyphs++;
5326 glyphset->cGlyphsSupported++;
5327 }
5328 char_code_prev = char_code;
5329 char_code = FT_Get_Next_Char(face, char_code, &glyph_code);
5330 }
5331 }
5332 else
5333 DPRINT1("Encoding %i not supported\n", face->charmap->encoding);
5334
5335 size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
5336 if (glyphset)
5337 {
5338 glyphset->cbThis = size;
5339 glyphset->cRanges = num_ranges;
5340 glyphset->flAccel = 0;
5341 }
5342 return size;
5343}
5344
5345
5346BOOL
5349 HDC hDC,
5350 PTMW_INTERNAL ptmwi)
5351{
5352 PDC dc;
5353 PDC_ATTR pdcattr;
5354 PTEXTOBJ TextObj;
5355 PFONTGDI FontGDI;
5356 FT_Face Face;
5357 TT_OS2 *pOS2;
5358 TT_HoriHeader *pHori;
5360 ULONG Error;
5362 LOGFONTW *plf;
5363
5364 if (!ptmwi)
5365 {
5367 return FALSE;
5368 }
5369 RtlZeroMemory(ptmwi, sizeof(TMW_INTERNAL));
5370
5371 if (!(dc = DC_LockDc(hDC)))
5372 {
5374 return FALSE;
5375 }
5376 pdcattr = dc->pdcattr;
5377 TextObj = RealizeFontInit(pdcattr->hlfntNew);
5378 if (NULL != TextObj)
5379 {
5380 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
5381 FontGDI = ObjToGDI(TextObj->Font, FONT);
5382
5383 Face = FontGDI->SharedFace->Face;
5384
5385 // NOTE: GetTextMetrics simply ignores lfEscapement and XFORM.
5387 Error = IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
5388 FT_Set_Transform(Face, NULL, NULL);
5389
5391
5392 if (0 != Error)
5393 {
5394 DPRINT1("Error in setting pixel sizes: %u\n", Error);
5396 }
5397 else
5398 {
5400
5402
5403 Error = FT_Get_WinFNT_Header(Face, &Win);
5404 pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
5405 pHori = FT_Get_Sfnt_Table(Face, ft_sfnt_hhea);
5406
5407 if (!pOS2 && Error)
5408 {
5409 DPRINT1("Can't find OS/2 table - not TT font?\n");
5411 }
5412
5413 if (!pHori && Error)
5414 {
5415 DPRINT1("Can't find HHEA table - not TT font?\n");
5417 }
5418
5419 if (NT_SUCCESS(Status))
5420 {
5421 FillTM(&ptmwi->TextMetric, FontGDI, pOS2, pHori, (Error ? NULL : &Win));
5422
5423 /* FIXME: Fill Diff member */
5424 }
5425
5427 }
5428 TEXTOBJ_UnlockText(TextObj);
5429 }
5430 else
5431 {
5433 }
5434 DC_UnlockDc(dc);
5435
5436 if (!NT_SUCCESS(Status))
5437 {
5439 return FALSE;
5440 }
5441 return TRUE;
5442}
5443
5444DWORD
5447 PFONTGDI FontGdi,
5448 DWORD Table,
5449 DWORD Offset,
5450 PVOID Buffer,
5451 DWORD Size)
5452{
5454 FT_Face Face = FontGdi->SharedFace->Face;
5455
5457
5458 if (FT_IS_SFNT(Face))
5459 {
5460 if (Table)
5461 Table = Table >> 24 | Table << 24 | (Table >> 8 & 0xFF00) |
5462 (Table << 8 & 0xFF0000);
5463
5464 if (!Buffer) Size = 0;
5465
5466 if (Buffer && Size)
5467 {
5469 FT_ULong Needed = 0;
5470
5471 Error = FT_Load_Sfnt_Table(Face, Table, Offset, NULL, &Needed);
5472
5473 if ( !Error && Needed < Size) Size = Needed;
5474 }
5475 if (!FT_Load_Sfnt_Table(Face, Table, Offset, Buffer, &Size))
5476 Result = Size;
5477 }
5478
5480
5481 return Result;
5482}
5483
5484#define GOT_PENALTY(name, value) Penalty += (value)
5485
5486// NOTE: See Table 1. of https://learn.microsoft.com/en-us/previous-versions/ms969909(v=msdn.10)
5487static UINT
5488GetFontPenalty(const LOGFONTW * LogFont,
5489 const OUTLINETEXTMETRICW * Otm,
5490 const char * style_name)
5491{
5492 ULONG Penalty = 0;
5493 BYTE Byte;
5494 LONG Long;
5495 BOOL fNeedScaling = FALSE;
5496 const BYTE UserCharSet = CharSetFromLangID(gusLanguageID);
5497 const TEXTMETRICW * TM = &Otm->otmTextMetrics;
5498 WCHAR* ActualNameW;
5499
5500 ASSERT(Otm);
5501 ASSERT(LogFont);
5502
5503 /* FIXME: IntSizeSynth Penalty 20 */
5504 /* FIXME: SmallPenalty Penalty 1 */
5505 /* FIXME: FaceNameSubst Penalty 500 */
5506
5507 Byte = LogFont->lfCharSet;
5508
5509 if (Byte != TM->tmCharSet)
5510 {
5512 {
5513 /* CharSet Penalty 65000 */
5514 /* Requested charset does not match the candidate's. */
5515 GOT_PENALTY("CharSet", 65000);
5516 }
5517 else
5518 {
5519 if (UserCharSet != TM->tmCharSet)
5520 {
5521 /* UNDOCUMENTED: Not user language */
5522 GOT_PENALTY("UNDOCUMENTED:NotUserLanguage", 100);
5523
5524 if (ANSI_CHARSET != TM->tmCharSet)
5525 {
5526 /* UNDOCUMENTED: Not ANSI charset */
5527 GOT_PENALTY("UNDOCUMENTED:NotAnsiCharSet", 100);
5528 }
5529 }
5530 }
5531 }
5532
5533 Byte = LogFont->lfOutPrecision;
5534 switch (Byte)
5535 {
5536 case OUT_DEFAULT_PRECIS:
5537 /* nothing to do */
5538 break;
5539 case OUT_DEVICE_PRECIS:
5540 if (!(TM->tmPitchAndFamily & TMPF_DEVICE) ||
5542 {
5543 /* OutputPrecision Penalty 19000 */
5544 /* Requested OUT_STROKE_PRECIS, but the device can't do it
5545 or the candidate is not a vector font. */
5546 GOT_PENALTY("OutputPrecision", 19000);
5547 }
5548 break;
5549 default:
5551 {
5552 /* OutputPrecision Penalty 19000 */
5553 /* Or OUT_STROKE_PRECIS not requested, and the candidate
5554 is a vector font that requires GDI support. */
5555 GOT_PENALTY("OutputPrecision", 19000);
5556 }
5557 break;
5558 }
5559
5560 Byte = (LogFont->lfPitchAndFamily & 0x0F);
5561 if (Byte == DEFAULT_PITCH)
5563 if (Byte == FIXED_PITCH)
5564 {
5566 {
5567 /* FixedPitch Penalty 15000 */
5568 /* Requested a fixed pitch font, but the candidate is a
5569 variable pitch font. */
5570 GOT_PENALTY("FixedPitch", 15000);
5571 }
5572 }
5573 if (Byte == VARIABLE_PITCH)
5574 {
5576 {
5577 /* PitchVariable Penalty 350 */
5578 /* Requested a variable pitch font, but the candidate is not a
5579 variable pitch font. */
5580 GOT_PENALTY("PitchVariable", 350);
5581 }
5582 }
5583
5584 Byte = (LogFont->lfPitchAndFamily & 0x0F);
5585 if (Byte == DEFAULT_PITCH)
5586 {
5588 {
5589 /* DefaultPitchFixed Penalty 1 */
5590 /* Requested DEFAULT_PITCH, but the candidate is fixed pitch. */
5591 GOT_PENALTY("DefaultPitchFixed", 1);
5592 }
5593 }
5594
5595 ActualNameW = (WCHAR*)((ULONG_PTR)Otm + (ULONG_PTR)Otm->otmpFamilyName);
5596
5597 if (LogFont->lfFaceName[0] != UNICODE_NULL)
5598 {
5599 BOOL Found = FALSE;
5600
5601 /* localized family name */
5602 if (!Found)
5603 {
5604 Found = (_wcsicmp(LogFont->lfFaceName, ActualNameW) == 0);
5605 }
5606 /* localized full name */
5607 if (!Found)
5608 {
5609 ActualNameW = (WCHAR*)((ULONG_PTR)Otm + (ULONG_PTR)Otm->otmpFaceName);
5610 Found = (_wcsicmp(LogFont->lfFaceName, ActualNameW) == 0);
5611 }
5612 if (!Found)
5613 {
5614 /* FaceName Penalty 10000 */
5615 /* Requested a face name, but the candidate's face name
5616 does not match. */
5617 GOT_PENALTY("FaceName", 10000);
5618 }
5619 }
5620
5621 Byte = (LogFont->lfPitchAndFamily & 0xF0);
5622 if (Byte != FF_DONTCARE)
5623 {
5624 if (Byte != (TM->tmPitchAndFamily & 0xF0))
5625 {
5626 /* Family Penalty 9000 */
5627 /* Requested a family, but the candidate's family is different. */
5628 GOT_PENALTY("Family", 9000);
5629 }
5630 }
5631
5632 if ((TM->tmPitchAndFamily & 0xF0) == FF_DONTCARE)
5633 {
5634 /* FamilyUnknown Penalty 8000 */
5635 /* Requested a family, but the candidate has no family. */
5636 GOT_PENALTY("FamilyUnknown", 8000);
5637 }
5638
5639 /* Is the candidate a non-vector font? */
5641 {
5642 /* Is lfHeight specified? */
5643 if (LogFont->lfHeight != 0)
5644 {
5645 if (labs(LogFont->lfHeight) < TM->tmHeight)
5646 {
5647 /* HeightBigger Penalty 600 */
5648 /* The candidate is a nonvector font and is bigger than the
5649 requested height. */
5650 GOT_PENALTY("HeightBigger", 600);
5651 /* HeightBiggerDifference Penalty 150 */
5652 /* The candidate is a raster font and is larger than the
5653 requested height. Penalty * height difference */
5654 GOT_PENALTY("HeightBiggerDifference", 150 * labs(TM->tmHeight - labs(LogFont->lfHeight)));
5655
5656 fNeedScaling = TRUE;
5657 }
5658 if (TM->tmHeight < labs(LogFont->lfHeight))
5659 {
5660 /* HeightSmaller Penalty 150 */
5661 /* The candidate is a raster font and is smaller than the
5662 requested height. Penalty * height difference */
5663 GOT_PENALTY("HeightSmaller", 150 * labs(TM->tmHeight - labs(LogFont->lfHeight)));
5664
5665 fNeedScaling = TRUE;
5666 }
5667 }
5668 }
5669
5670 switch (LogFont->lfPitchAndFamily & 0xF0)
5671 {
5672 case FF_ROMAN: case FF_MODERN: case FF_SWISS:
5673 switch (TM->tmPitchAndFamily & 0xF0)
5674 {
5675 case FF_DECORATIVE: case FF_SCRIPT:
5676 /* FamilyUnlikely Penalty 50 */
5677 /* Requested a roman/modern/swiss family, but the
5678 candidate is decorative/script. */
5679 GOT_PENALTY("FamilyUnlikely", 50);
5680 break;
5681 default:
5682 break;
5683 }
5684 break;
5685 case FF_DECORATIVE: case FF_SCRIPT:
5686 switch (TM->tmPitchAndFamily & 0xF0)
5687 {
5688 case FF_ROMAN: case FF_MODERN: case FF_SWISS:
5689 /* FamilyUnlikely Penalty 50 */
5690 /* Or requested decorative/script, and the candidate is
5691 roman/modern/swiss. */
5692 GOT_PENALTY("FamilyUnlikely", 50);
5693 break;
5694 default:
5695 break;
5696 }
5697 default:
5698 break;
5699 }
5700
5701 if (LogFont->lfWidth != 0)
5702 {
5703 if (LogFont->lfWidth != TM->tmAveCharWidth)
5704 {
5705 /* Width Penalty 50 */
5706 /* Requested a nonzero width, but the candidate's width
5707 doesn't match. Penalty * width difference */
5708 GOT_PENALTY("Width", 50 * labs(LogFont->lfWidth - TM->tmAveCharWidth));
5709
5711 fNeedScaling = TRUE;
5712 }
5713 }
5714
5715 if (fNeedScaling)
5716 {
5717 /* SizeSynth Penalty 50 */
5718 /* The candidate is a raster font that needs scaling by GDI. */
5719 GOT_PENALTY("SizeSynth", 50);
5720 }
5721
5722 if (!LogFont->lfItalic && TM->tmItalic)
5723 {
5724 /* Italic Penalty 4 */
5725 /* Requested font and candidate font do not agree on italic status,
5726 and the desired result cannot be simulated. */
5727 /* Adjusted to 40 to satisfy (Oblique Penalty > Book Penalty). */
5728 GOT_PENALTY("Italic", 40);
5729 }
5730 else if (LogFont->lfItalic && !TM->tmItalic)
5731 {
5732 /* ItalicSim Penalty 1 */
5733 /* Requested italic font but the candidate is not italic,
5734 although italics can be simulated. */
5735 GOT_PENALTY("ItalicSim", 1);
5736 }
5737
5738 if (LogFont->lfOutPrecision == OUT_TT_PRECIS)
5739 {
5740 if (!(TM->tmPitchAndFamily & TMPF_TRUETYPE))
5741 {
5742 /* NotTrueType Penalty 4 */
5743 /* Requested OUT_TT_PRECIS, but the candidate is not a
5744 TrueType font. */
5745 GOT_PENALTY("NotTrueType", 4);
5746 }
5747 }
5748
5749 Long = LogFont->lfWeight;
5750 if (LogFont->lfWeight == FW_DONTCARE)
5751 Long = FW_NORMAL;
5752 if (Long != TM->tmWeight)
5753 {
5754 /* Weight Penalty 3 */
5755 /* The candidate's weight does not match the requested weight.
5756 Penalty * (weight difference/10) */
5757 GOT_PENALTY("Weight", 3 * (labs(Long - TM->tmWeight) / 10));
5758 }
5759
5760 if (!LogFont->lfUnderline && TM->tmUnderlined)
5761 {
5762 /* Underline Penalty 3 */
5763 /* Requested font has no underline, but the candidate is
5764 underlined. */
5765 GOT_PENALTY("Underline", 3);
5766 }
5767
5768 if (!LogFont->lfStrikeOut && TM->tmStruckOut)
5769 {
5770 /* StrikeOut Penalty 3 */
5771 /* Requested font has no strike-out, but the candidate is
5772 struck out. */
5773 GOT_PENALTY("StrikeOut", 3);
5774 }
5775
5776 /* Is the candidate a non-vector font? */
5778 {
5779 if (LogFont->lfHeight != 0 && TM->tmHeight < LogFont->lfHeight)
5780 {
5781 /* VectorHeightSmaller Penalty 2 */
5782 /* Candidate is a vector font that is smaller than the
5783 requested height. Penalty * height difference */
5784 GOT_PENALTY("VectorHeightSmaller", 2 * labs(TM->tmHeight - LogFont->lfHeight));
5785 }
5786 if (LogFont->lfHeight != 0 && TM->tmHeight > LogFont->lfHeight)
5787 {
5788 /* VectorHeightBigger Penalty 1 */
5789 /* Candidate is a vector font that is bigger than the
5790 requested height. Penalty * height difference */
5791 GOT_PENALTY("VectorHeightBigger", 1 * labs(TM->tmHeight - LogFont->lfHeight));
5792 }
5793 }
5794
5795 if (!(TM->tmPitchAndFamily & TMPF_DEVICE))
5796 {
5797 /* DeviceFavor Penalty 2 */
5798 /* Extra penalty for all nondevice fonts. */
5799 GOT_PENALTY("DeviceFavor", 2);
5800 }
5801
5802 if (TM->tmAveCharWidth >= 5 && TM->tmHeight >= 5)
5803 {
5804 if (TM->tmAveCharWidth / TM->tmHeight >= 3)
5805 {
5806 /* Aspect Penalty 30 */
5807 /* The aspect rate is >= 3. It seems like a bad font. */
5808 GOT_PENALTY("Aspect", ((TM->tmAveCharWidth / TM->tmHeight) - 2) * 30);
5809 }
5810 else if (TM->tmHeight / TM->tmAveCharWidth >= 3)
5811 {
5812 /* Aspect Penalty 30 */
5813 /* The aspect rate is >= 3. It seems like a bad font. */
5814 GOT_PENALTY("Aspect", ((TM->tmHeight / TM->tmAveCharWidth) - 2) * 30);
5815 }
5816 }
5817
5818 if (Penalty < 200)
5819 {
5820 DPRINT("WARNING: Penalty:%ld < 200: RequestedNameW:%ls, "
5821 "ActualNameW:%ls, lfCharSet:%d, lfWeight:%ld, "
5822 "tmCharSet:%d, tmWeight:%ld\n",
5823 Penalty, LogFont->lfFaceName, ActualNameW,
5824 LogFont->lfCharSet, LogFont->lfWeight,
5825 TM->tmCharSet, TM->tmWeight);
5826 }
5827
5828 return Penalty; /* success */
5829}
5830
5831#undef GOT_PENALTY
5832
5833static __inline VOID
5834FindBestFontFromList(FONTOBJ **FontObj, ULONG *MatchPenalty,
5835 const LOGFONTW *LogFont,
5836 const PLIST_ENTRY Head)
5837{
5838 ULONG Penalty;
5840 PFONT_ENTRY CurrentEntry;
5841 FONTGDI *FontGDI;
5842 OUTLINETEXTMETRICW *Otm = NULL;
5843 UINT OtmSize, OldOtmSize = 0;
5844 FT_Face Face;
5845
5846 ASSERT(FontObj);
5847 ASSERT(MatchPenalty);
5848 ASSERT(LogFont);
5849 ASSERT(Head);
5850
5851 /* Start with a pretty big buffer */
5852 OldOtmSize = 0x200;
5853 Otm = ExAllocatePoolWithTag(PagedPool, OldOtmSize, GDITAG_TEXT);
5854
5855 /* get the FontObj of lowest penalty */
5856 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
5857 {
5858 CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
5859
5860 FontGDI = CurrentEntry->Font;
5861 ASSERT(FontGDI);
5862 Face = FontGDI->SharedFace->Face;
5863
5864 /* get text metrics */
5866 OtmSize = IntGetOutlineTextMetrics(FontGDI, 0, NULL, TRUE);
5867 if (OtmSize > OldOtmSize)
5868 {
5869 if (Otm)
5872 }
5873
5874 /* update FontObj if lowest penalty */
5875 if (Otm)
5876 {
5878 IntRequestFontSize(NULL, FontGDI, LogFont->lfWidth, LogFont->lfHeight);
5879
5881 OtmSize = IntGetOutlineTextMetrics(FontGDI, OtmSize, Otm, TRUE);
5882 if (!OtmSize)
5883 continue;
5884
5885 OldOtmSize = OtmSize;
5886
5887 Penalty = GetFontPenalty(LogFont, Otm, Face->style_name);
5888 if (*MatchPenalty == MAXULONG || Penalty < *MatchPenalty)
5889 {
5890 *FontObj = GDIToObj(FontGDI, FONT);
5891 *MatchPenalty = Penalty;
5892 }
5893 }
5894 }
5895
5896 if (Otm)
5898}
5899
5900static
5901VOID
5904{
5905 PS_FontInfoRec psfInfo;
5906 FT_ULong tmp_size = 0;
5907 FT_Face Face = Font->SharedFace->Face;
5908
5911
5912 if (FT_HAS_MULTIPLE_MASTERS(Face))
5913 Font->FontObj.flFontType |= FO_MULTIPLEMASTER;
5914 if (FT_HAS_VERTICAL(Face))
5915 Font->FontObj.flFontType |= FO_VERT_FACE;
5916 if (!FT_IS_SCALABLE(Face))
5917 Font->FontObj.flFontType |= FO_TYPE_RASTER;
5918 if (FT_IS_SFNT(Face))
5919 {
5920 Font->FontObj.flFontType |= FO_TYPE_TRUETYPE;
5922 Font->FontObj.flFontType |= FO_POSTSCRIPT;
5923 }
5924 if (!FT_Get_PS_Font_Info(Face, &psfInfo ))
5925 {
5926 Font->FontObj.flFontType |= FO_POSTSCRIPT;
5927 }
5928 /* Check for the presence of the 'CFF ' table to check if the font is Type1 */
5929 if (!FT_Load_Sfnt_Table(Face, TTAG_CFF, 0, NULL, &tmp_size))
5930 {
5931 Font->FontObj.flFontType |= (FO_CFF|FO_POSTSCRIPT);
5932 }
5933
5935}
5936
5937static BOOL
5939{
5942
5944 Status = IntGetFontLocalizedName(&Name2, SharedFace, NameID, LangID);
5945
5946 if (NT_SUCCESS(Status))
5947 {
5948 if (RtlCompareUnicodeString(Name1, &Name2, TRUE) == 0)
5949 {
5951 return TRUE;
5952 }
5953
5955 }
5956
5957 return FALSE;
5958}
5959
5960static BOOL
5961MatchFontNames(PSHARED_FACE SharedFace, LPCWSTR lfFaceName)
5962{
5963 UNICODE_STRING Name1;
5964
5965 if (lfFaceName[0] == UNICODE_NULL)
5966 return FALSE;
5967
5968 RtlInitUnicodeString(&Name1, lfFaceName);
5969
5970 if (MatchFontName(SharedFace, &Name1, TT_NAME_ID_FONT_FAMILY, LANG_ENGLISH) ||
5971 MatchFontName(SharedFace, &Name1, TT_NAME_ID_FULL_NAME, LANG_ENGLISH))
5972 {
5973 return TRUE;
5974 }
5976 {
5977 if (MatchFontName(SharedFace, &Name1, TT_NAME_ID_FONT_FAMILY, gusLanguageID) ||
5978 MatchFontName(SharedFace, &Name1, TT_NAME_ID_FULL_NAME, gusLanguageID))
5979 {
5980 return TRUE;
5981 }
5982 }
5983 return FALSE;
5984}
5985
5988TextIntRealizeFont(HFONT FontHandle, PTEXTOBJ pTextObj)
5989{
5991 PTEXTOBJ TextObj;
5992 PPROCESSINFO Win32Process;
5993 ULONG MatchPenalty;
5994 LOGFONTW *pLogFont;
5995 LOGFONTW SubstitutedLogFont;
5996
5997 if (!pTextObj)
5998 {
5999 TextObj = TEXTOBJ_LockText(FontHandle);
6000 if (NULL == TextObj)
6001 {
6002 return STATUS_INVALID_HANDLE;
6003 }
6004
6005 if (TextObj->fl & TEXTOBJECT_INIT)
6006 {
6007 TEXTOBJ_UnlockText(TextObj);
6008 return STATUS_SUCCESS;
6009 }
6010 }
6011 else
6012 {
6013 TextObj = pTextObj;
6014 }
6015
6016 pLogFont = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
6017
6018 /* substitute */
6019 SubstitutedLogFont = *pLogFont;
6020 SubstituteFontRecurse(&SubstitutedLogFont);
6021 DPRINT("Font '%S,%u' is substituted by '%S,%u'.\n",
6022 pLogFont->lfFaceName, pLogFont->lfCharSet,
6023 SubstitutedLogFont.lfFaceName, SubstitutedLogFont.lfCharSet);
6024
6025 MatchPenalty = 0xFFFFFFFF;
6026 TextObj->Font = NULL;
6027
6028 Win32Process = PsGetCurrentProcessWin32Process();
6029
6030 /* Search private fonts */
6032 IntLockProcessPrivateFonts(Win32Process);
6033 FindBestFontFromList(&TextObj->Font, &MatchPenalty, &SubstitutedLogFont,
6034 &Win32Process->PrivateFontListHead);
6035 IntUnLockProcessPrivateFonts(Win32Process);
6036
6037 /* Search system fonts */
6038 FindBestFontFromList(&TextObj->Font, &MatchPenalty, &SubstitutedLogFont,
6039 &g_FontListHead);
6041
6042 if (NULL == TextObj->Font)
6043 {
6044 DPRINT1("Request font %S not found, no fonts loaded at all\n",
6045 pLogFont->lfFaceName);
6047 }
6048 else
6049 {
6051 PFONTGDI FontGdi = ObjToGDI(TextObj->Font, FONT);
6052 PSHARED_FACE SharedFace = FontGdi->SharedFace;
6053
6054 TextObj->TextFace[0] = UNICODE_NULL;
6056 if (MatchFontNames(SharedFace, SubstitutedLogFont.lfFaceName))
6057 {
6059 RtlStringCchCopyW(TextObj->TextFace, _countof(TextObj->TextFace), pLogFont->lfFaceName);
6060 }
6061 else
6062 {
6066 if (NT_SUCCESS(Status))
6067 {
6068 /* truncated copy */
6069 IntUnicodeStringToBuffer(TextObj->TextFace, sizeof(TextObj->TextFace), &Name);
6071 }
6072 }
6073
6074 // Need hdev, when freetype is loaded need to create DEVOBJ for
6075 // Consumer and Producer.
6076 TextObj->Font->iUniq = 1; // Now it can be cached.
6077 IntFontType(FontGdi);
6078 FontGdi->flType = TextObj->Font->flFontType;
6079 FontGdi->RequestUnderline = pLogFont->lfUnderline ? 0xFF : 0;
6080 FontGdi->RequestStrikeOut = pLogFont->lfStrikeOut ? 0xFF : 0;
6081 FontGdi->RequestItalic = pLogFont->lfItalic ? 0xFF : 0;
6082 if (pLogFont->lfWeight != FW_DONTCARE)
6083 FontGdi->RequestWeight = pLogFont->lfWeight;
6084 else
6085 FontGdi->RequestWeight = FW_NORMAL;
6086
6087 TextObj->fl |= TEXTOBJECT_INIT;
6089 }
6090
6091 if (!pTextObj) TEXTOBJ_UnlockText(TextObj);
6092
6093 ASSERT((NT_SUCCESS(Status) ^ (NULL == TextObj->Font)) != 0);
6094
6095 return Status;
6096}
6097
6098static
6099BOOL
6102 POBJECT_NAME_INFORMATION NameInfo,
6103 ULONG Size,
6105{
6108 HANDLE hFile;
6110 ULONG Desired;
6111
6113 FileName,
6115 NULL,
6116 NULL);
6117
6119 &hFile,
6120 0, // FILE_READ_ATTRIBUTES,
6124 0);
6125
6126 if (!NT_SUCCESS(Status))
6127 {
6128 DPRINT("ZwOpenFile() failed (Status = 0x%lx)\n", Status);
6129 return FALSE;
6130 }
6131
6132 Status = ZwQueryObject(hFile, ObjectNameInformation, NameInfo, Size, &Desired);
6133 ZwClose(hFile);
6134 if (!NT_SUCCESS(Status))
6135 {
6136 DPRINT("ZwQueryObject() failed (Status = %lx)\n", Status);
6137 return FALSE;
6138 }
6139
6140 return TRUE;
6141}
6142
6143static BOOL
6144EqualFamilyInfo(const FONTFAMILYINFO *pInfo1, const FONTFAMILYINFO *pInfo2)
6145{
6146 const ENUMLOGFONTEXW *pLog1 = &pInfo1->EnumLogFontEx;
6147 const ENUMLOGFONTEXW *pLog2 = &pInfo2->EnumLogFontEx;
6148 const LOGFONTW *plf1 = &pLog1->elfLogFont;
6149 const LOGFONTW *plf2 = &pLog2->elfLogFont;
6150
6151 if (_wcsicmp(plf1->lfFaceName, plf2->lfFaceName) != 0)
6152 {
6153 return FALSE;
6154 }
6155
6156 if (_wcsicmp(pLog1->elfStyle, pLog2->elfStyle) != 0)
6157 {
6158 return FALSE;
6159 }
6160
6161 return TRUE;
6162}
6163
6164static VOID
6166{
6168 if (FamInfo->EnumLogFontEx.elfStyle[0] &&
6169 _wcsicmp(FamInfo->EnumLogFontEx.elfStyle, L"Regular") != 0)
6170 {
6171 wcscat(psz, L" ");
6172 wcscat(psz, FamInfo->EnumLogFontEx.elfStyle);
6173 }
6174}
6175
6176BOOL
6180 PVOID pBuffer,
6181 DWORD *pdwBytes,
6182 DWORD dwType)
6183{
6184 UNICODE_STRING EntryFileName;
6185 POBJECT_NAME_INFORMATION NameInfo1 = NULL, NameInfo2 = NULL;
6186 PLIST_ENTRY ListEntry;
6187 PFONT_ENTRY FontEntry;
6188 ULONG Size, i, Count;
6189 LPBYTE pbBuffer;
6190 BOOL IsEqual;
6191 FONTFAMILYINFO *FamInfo;
6192 const ULONG MaxFamInfo = 64;
6193 const ULONG MAX_FAM_INFO_BYTES = sizeof(FONTFAMILYINFO) * MaxFamInfo;
6194 BOOL bSuccess;
6195 const ULONG NAMEINFO_SIZE = sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR);
6196
6197 DPRINT("IntGdiGetFontResourceInfo: dwType == %lu\n", dwType);
6198
6199 do
6200 {
6201 /* Create buffer for full path name */
6202 NameInfo1 = ExAllocatePoolWithTag(PagedPool, NAMEINFO_SIZE, TAG_FINF);
6203 if (!NameInfo1)
6204 break;
6205
6206 /* Get the full path name */
6207 if (!IntGetFullFileName(NameInfo1, NAMEINFO_SIZE, FileName))
6208 break;
6209
6210 /* Create a buffer for the entries' names */
6211 NameInfo2 = ExAllocatePoolWithTag(PagedPool, NAMEINFO_SIZE, TAG_FINF);
6212 if (!NameInfo2)
6213 break;
6214
6215 FamInfo = ExAllocatePoolWithTag(PagedPool, MAX_FAM_INFO_BYTES, TAG_FINF);
6216 } while (0);
6217
6218 if (!NameInfo1 || !NameInfo2 || !FamInfo)
6219 {
6220 if (NameInfo2)
6221 ExFreePoolWithTag(NameInfo2, TAG_FINF);
6222
6223 if (NameInfo1)
6224 ExFreePoolWithTag(NameInfo1, TAG_FINF);
6225
6227 return FALSE;
6228 }
6229
6230 Count = 0;
6231
6232 /* Try to find the pathname in the global font list */
6234 for (ListEntry = g_FontListHead.Flink; ListEntry != &g_FontListHead;
6235 ListEntry = ListEntry->Flink)
6236 {
6237 FontEntry = CONTAINING_RECORD(ListEntry, FONT_ENTRY, ListEntry);
6238 if (FontEntry->Font->Filename == NULL)
6239 continue;
6240
6241 RtlInitUnicodeString(&EntryFileName , FontEntry->Font->Filename);
6242 if (!IntGetFullFileName(NameInfo2, NAMEINFO_SIZE, &EntryFileName))
6243 continue;
6244
6245 if (!RtlEqualUnicodeString(&NameInfo1->Name, &NameInfo2->Name, FALSE))
6246 continue;
6247
6248 IsEqual = FALSE;
6249 FontFamilyFillInfo(&FamInfo[Count], FontEntry->FaceName.Buffer,
6250 NULL, FontEntry->Font);
6251 for (i = 0; i < Count; ++i)
6252 {
6253 if (EqualFamilyInfo(&FamInfo[i], &FamInfo[Count]))
6254 {
6255 IsEqual = TRUE;
6256 break;
6257 }
6258 }
6259 if (!IsEqual)
6260 {
6261 /* Found */
6262 ++Count;
6263 if (Count >= MaxFamInfo)
6264 break;
6265 }
6266 }
6268
6269 /* Free the buffers */
6270 ExFreePoolWithTag(NameInfo1, TAG_FINF);
6271 ExFreePoolWithTag(NameInfo2, TAG_FINF);
6272
6273 if (Count == 0 && dwType != 5)
6274 {
6275 /* Font could not be found in system table
6276 dwType == 5 will still handle this */
6277 ExFreePoolWithTag(FamInfo, TAG_FINF);
6278 return FALSE;
6279 }
6280
6281 bSuccess = FALSE;
6282 switch (dwType)
6283 {
6284 case 0: /* FIXME: Returns 1 or 2, don't know what this is atm */
6285 Size = sizeof(DWORD);
6286 if (*pdwBytes == 0)
6287 {
6288 *pdwBytes = Size;
6289 bSuccess = TRUE;
6290 }
6291 else if (pBuffer)
6292 {
6293 if (*pdwBytes >= Size)
6294 {
6295 *(DWORD*)pBuffer = Count;
6296 }
6297 *pdwBytes = Size;
6298 bSuccess = TRUE;
6299 }
6300 break;
6301
6302 case 1: /* copy the font title */
6303 /* calculate the required size */
6304 Size = 0;
6305 for (i = 0; i < Count; ++i)
6306 {
6307 if (i > 0)
6308 Size += 3; /* " & " */
6309 Size += wcslen(FamInfo[i].EnumLogFontEx.elfLogFont.lfFaceName);
6310 if (FamInfo[i].EnumLogFontEx.elfStyle[0] &&
6311 _wcsicmp(FamInfo[i].EnumLogFontEx.elfStyle, L"Regular") != 0)
6312 {
6313 Size += 1 + wcslen(FamInfo[i].EnumLogFontEx.elfStyle);
6314 }
6315 }
6316 Size += 2; /* "\0\0" */
6317 Size *= sizeof(WCHAR);
6318
6319 if (*pdwBytes == 0)
6320 {
6321 *pdwBytes = Size;
6322 bSuccess = TRUE;
6323 }
6324 else if (pBuffer)
6325 {
6326 if (*pdwBytes >= Size)
6327 {
6328 /* store font title to buffer */
6329 WCHAR *psz = pBuffer;
6330 *psz = 0;
6331 for (i = 0; i < Count; ++i)
6332 {
6333 if (i > 0)
6334 wcscat(psz, L" & ");
6335 IntAddNameFromFamInfo(psz, &FamInfo[i]);
6336 }
6337 psz[wcslen(psz) + 1] = UNICODE_NULL;
6338 *pdwBytes = Size;
6339 bSuccess = TRUE;
6340 }
6341 else
6342 {
6343 *pdwBytes = 1024; /* this is confirmed value */
6344 }
6345 }
6346 break;
6347
6348 case 2: /* Copy an array of LOGFONTW */
6349 Size = Count * sizeof(LOGFONTW);
6350 if (*pdwBytes == 0)
6351 {
6352 *pdwBytes = Size;
6353 bSuccess = TRUE;
6354 }
6355 else if (pBuffer)
6356 {
6357 if (*pdwBytes >= Size)
6358 {
6359 pbBuffer = (LPBYTE)pBuffer;
6360 for (i = 0; i < Count; ++i)
6361 {
6362 FamInfo[i].EnumLogFontEx.elfLogFont.lfWidth = 0;
6363 RtlCopyMemory(pbBuffer, &FamInfo[i].EnumLogFontEx.elfLogFont, sizeof(LOGFONTW));
6364 pbBuffer += sizeof(LOGFONTW);
6365 }
6366 }
6367 *pdwBytes = Size;
6368 bSuccess = TRUE;
6369 }
6370 else
6371 {
6372 *pdwBytes = 1024; /* this is confirmed value */
6373 }
6374 break;
6375
6376 case 3:
6377 Size = sizeof(DWORD);
6378 if (*pdwBytes == 0)
6379 {
6380 *pdwBytes = Size;
6381 bSuccess = TRUE;
6382 }
6383 else if (pBuffer)
6384 {
6385 if (*pdwBytes >= Size)
6386 {
6387 /* FIXME: What exactly is copied here? */
6388 *(DWORD*)pBuffer = 1;
6389 }
6390 *pdwBytes = Size;
6391 bSuccess = TRUE;
6392 }
6393 break;
6394
6395 case 4: /* full file path */
6396 if (FileName->Length >= 4 * sizeof(WCHAR))
6397 {
6398 /* The beginning of FileName is \??\ */
6399 LPWSTR pch = FileName->Buffer + 4;
6400 DWORD Length = FileName->Length - 4 * sizeof(WCHAR);
6401
6402 Size = Length + sizeof(WCHAR);
6403 if (*pdwBytes == 0)
6404 {
6405 *pdwBytes = Size;
6406 bSuccess = TRUE;
6407 }
6408 else if (pBuffer)
6409 {
6410 if (*pdwBytes >= Size)
6411 {
6413 }
6414 *pdwBytes = Size;
6415 bSuccess = TRUE;
6416 }
6417 }
6418 break;
6419
6420 case 5: /* Looks like a BOOL that is copied, TRUE, if the font was not found */
6421 Size = sizeof(BOOL);
6422 if (*pdwBytes == 0)
6423 {
6424 *pdwBytes = Size;
6425 bSuccess = TRUE;
6426 }
6427 else if (pBuffer)
6428 {
6429 if (*pdwBytes >= Size)
6430 {
6431 *(BOOL*)pBuffer = Count == 0;
6432 }
6433 *pdwBytes = Size;
6434 bSuccess = TRUE;
6435 }
6436 break;
6437 }
6438 ExFreePoolWithTag(FamInfo, TAG_FINF);
6439
6440 return bSuccess;
6441}
6442
6443
6444BOOL
6447{
6448 if (FT_HAS_FIXED_SIZES(Font->SharedFace->Face))
6449 Info->iTechnology = RI_TECH_BITMAP;
6450 else
6451 {
6452 if (FT_IS_SCALABLE(Font->SharedFace->Face))
6453 Info->iTechnology = RI_TECH_SCALABLE;
6454 else
6455 Info->iTechnology = RI_TECH_FIXED;
6456 }
6457 Info->iUniq = Font->FontObj.iUniq;
6458 Info->dwUnknown = -1;
6459 return TRUE;
6460}
6461
6462
6463DWORD
6466 DWORD cPairs,
6467 LPKERNINGPAIR pKerningPair)
6468{
6469 DWORD Count = 0;
6470 INT i = 0;
6471 FT_Face face = Font->SharedFace->Face;
6472
6473 if (FT_HAS_KERNING(face) && face->charmap->encoding == FT_ENCODING_UNICODE)
6474 {
6475 FT_UInt previous_index = 0, glyph_index = 0;
6476 FT_ULong char_code, char_previous;
6477 FT_Vector delta;
6478
6479 char_previous = char_code = FT_Get_First_Char(face, &glyph_index);
6480
6482
6483 while (glyph_index)
6484 {
6485 if (previous_index && glyph_index)
6486 {
6487 FT_Get_Kerning(face, previous_index, glyph_index, FT_KERNING_DEFAULT, &delta);
6488
6489 if (pKerningPair && cPairs)
6490 {
6491 pKerningPair[i].wFirst = char_previous;
6492 pKerningPair[i].wSecond = char_code;
6493 pKerningPair[i].iKernAmount = delta.x;
6494 i++;
6495 if (i == cPairs) break;
6496 }
6497 Count++;
6498 }
6499 previous_index = glyph_index;
6500 char_previous = char_code;
6501 char_code = FT_Get_Next_Char(face, char_code, &glyph_index);
6502 }
6504 }
6505 return Count;
6506}
6507
6508
6510//
6511// Functions needing sorting.
6512//
6514
6517 const LOGFONTW *SafeLogFont,
6518 PFONTFAMILYINFO SafeInfo,
6519 LONG InfoCount)
6520{
6521 LONG AvailCount = 0;
6522 PPROCESSINFO Win32Process;
6523
6524 /* Enumerate font families in the global list */
6526 if (!GetFontFamilyInfoForList(SafeLogFont, SafeInfo, NULL, &AvailCount,
6527 InfoCount, &g_FontListHead))
6528 {
6530 return -1;
6531 }
6532
6533 /* Enumerate font families in the process local list */
6534 Win32Process = PsGetCurrentProcessWin32Process();
6535 IntLockProcessPrivateFonts(Win32Process);
6536 if (!GetFontFamilyInfoForList(SafeLogFont, SafeInfo, NULL, &AvailCount, InfoCount,
6537 &Win32Process->PrivateFontListHead))
6538 {
6539 IntUnLockProcessPrivateFonts(Win32Process);
6541 return -1;
6542 }
6543 IntUnLockProcessPrivateFonts(Win32Process);
6545
6546 /* Enumerate font families in the registry */
6547 if (!GetFontFamilyInfoForSubstitutes(SafeLogFont, SafeInfo, &AvailCount, InfoCount))
6548 {
6549 return -1;
6550 }
6551
6552 return AvailCount;
6553}
6554
6555LONG NTAPI
6557 const LOGFONTW *UnsafeLogFont,
6558 PFONTFAMILYINFO UnsafeInfo,
6559 LPLONG UnsafeInfoCount)
6560{
6562 LOGFONTW LogFont;
6564 LONG GotCount, AvailCount, SafeInfoCount;
6566
6567 if (UnsafeLogFont == NULL || UnsafeInfo == NULL || UnsafeInfoCount == NULL)
6568 {
6570 return -1;
6571 }
6572
6573 Status = MmCopyFromCaller(&SafeInfoCount, UnsafeInfoCount, sizeof(SafeInfoCount));
6574 if (!NT_SUCCESS(Status))
6575 {
6577 return -1;
6578 }
6579 GotCount = 0;
6580 Status = MmCopyToCaller(UnsafeInfoCount, &GotCount, sizeof(*UnsafeInfoCount));
6581 if (!NT_SUCCESS(Status))
6582 {
6584 return -1;
6585 }
6586 Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW));
6587 if (!NT_SUCCESS(Status))
6588 {
6590 return -1;
6591 }
6592 if (SafeInfoCount <= 0)
6593 {
6595 return -1;
6596 }
6597
6598 /* Allocate space for a safe copy */
6599 Status = RtlULongMult(SafeInfoCount, sizeof(FONTFAMILYINFO), &DataSize);
6601 {
6602 DPRINT1("Overflowed.\n");
6604 return -1;
6605 }
6607 if (Info == NULL)
6608 {
6610 return -1;
6611 }
6612
6613 /* Retrieve the information */
6614 AvailCount = IntGetFontFamilyInfo(Dc, &LogFont, Info, SafeInfoCount);
6615 GotCount = min(AvailCount, SafeInfoCount);
6616 SafeInfoCount = AvailCount;
6617
6618 /* Return data to caller */
6619 if (GotCount > 0)
6620 {
6621 Status = RtlULongMult(GotCount, sizeof(FONTFAMILYINFO), &DataSize);
6623 {
6624 DPRINT1("Overflowed.\n");
6627 return -1;
6628 }
6629 Status = MmCopyToCaller(UnsafeInfo, Info, DataSize);
6630 if (!NT_SUCCESS(Status))
6631 {
6634 return -1;
6635 }
6636 Status = MmCopyToCaller(UnsafeInfoCount, &SafeInfoCount, sizeof(*UnsafeInfoCount));
6637 if (!NT_SUCCESS(Status))
6638 {
6641 return -1;
6642 }
6643 }
6644
6646
6647 return GotCount;
6648}
6649
6650static inline
6651LONG
6653{
6654 FLOATOBJ efTemp;
6655
6656 /* Check if we have scaling different from 1 */
6657 if (!FLOATOBJ_Equal(pef, (PFLOATOBJ)&gef1))
6658 {
6659 /* Need to multiply */
6660 FLOATOBJ_SetLong(&efTemp, lValue);
6661 FLOATOBJ_Mul(&efTemp, pef);
6662 lValue = FLOATOBJ_GetLong(&efTemp);
6663 }
6664
6665 return lValue;
6666}
6667
6668/*
6669 * Calculate X and Y disposition of the text.
6670 * NOTE: The disposition can be negative.
6671 */
6672static BOOL
6674 OUT LONGLONG *pX64,
6675 OUT LONGLONG *pY64,
6677 IN INT Count,
6678 IN OPTIONAL LPINT Dx,
6680 IN UINT fuOptions,
6681 IN BOOL bNoTransform,
6682 IN OUT PFONTLINK_CHAIN pChain)
6683{
6684 LONGLONG X64 = 0, Y64 = 0;
6685 INT i, glyph_index;
6686 FT_BitmapGlyph realglyph;
6687 FT_Face face = Cache->Hashed.Face;
6688 BOOL use_kerning = FT_HAS_KERNING(face);
6689 ULONG previous = 0;
6690 FT_Vector delta, vec;
6691 DWORD ch0, ch1;
6692
6694
6695 for (i = 0; i < Count; ++i)
6696 {
6697 ch0 = *String++;
6698 if (IS_HIGH_SURROGATE(ch0))
6699 {
6700 ++i;
6701 if (i >= Count)
6702 return TRUE;
6703
6704 ch1 = *String++;
6705 if (IS_LOW_SURROGATE(ch1))
6706 ch0 = Utf32FromSurrogatePair(ch0, ch1);
6707 }
6708
6709 glyph_index = FontLink_Chain_FindGlyph(pChain, Cache, &face, ch0,
6710 (fuOptions & ETO_GLYPH_INDEX));
6711 Cache->Hashed.GlyphIndex = glyph_index;
6712
6713 realglyph = IntGetRealGlyph(Cache);
6714 if (!realglyph)
6715 return FALSE;
6716
6717 /* Retrieve kerning distance */
6718 if (use_kerning && previous && glyph_index)
6719 {
6720 FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
6721 X64 += delta.x;
6722 Y64 -= delta.y;
6723 }
6724
6725 if (NULL == Dx)
6726 {
6727 X64 += realglyph->root.advance.x >> 10;
6728 Y64 -= realglyph->root.advance.y >> 10;
6729 }
6730 else if (fuOptions & ETO_PDY)
6731 {
6732 vec.x = (Dx[2 * i + 0] << 6);
6733 vec.y = (Dx[2 * i + 1] << 6);
6734 if (!bNoTransform)
6735 FT_Vector_Transform(&vec, &Cache->Hashed.matTransform);
6736 X64 += vec.x;
6737 Y64 -= vec.y;
6738 }
6739 else
6740 {
6741 vec.x = (Dx[i] << 6);
6742 vec.y = 0;
6743 if (!bNoTransform)
6744 FT_Vector_Transform(&vec, &Cache->Hashed.matTransform);
6745 X64 += vec.x;
6746 Y64 -= vec.y;
6747 }
6748
6749 previous = glyph_index;
6750 }
6751
6752 *pX64 = X64;
6753 *pY64 = Y64;
6754 return TRUE;
6755}
6756
6759 IN OUT PDC dc,
6760 IN POINTL *pPoints,
6761 IN UINT cPoints,
6762 IN BRUSHOBJ *BrushObj)
6763{
6764 SURFACE *psurf = dc->dclevel.pSurface;
6765 RECT Rect;
6766 UINT i;
6767 INT x, y;
6768
6770 ASSERT(psurf != NULL);
6771
6772 Rect.left = Rect.right = pPoints[0].x;
6773 Rect.top = Rect.bottom = pPoints[0].y;
6774 for (i = 1; i < cPoints; ++i)
6775 {
6776 x = pPoints[i].x;
6777 if (x < Rect.left)
6778 Rect.left = x;
6779 else if (Rect.right < x)
6780 Rect.right = x;
6781
6782 y = pPoints[i].y;
6783 if (y < Rect.top)
6784 Rect.top = y;
6785 else if (Rect.bottom < y)
6786 Rect.bottom = y;
6787 }
6788
6789 IntFillPolygon(dc, dc->dclevel.pSurface, BrushObj, pPoints, cPoints, Rect, &PointZero);
6790}
6791
6792VOID
6795 IN OUT PDC dc,
6796 IN INT X,
6797 IN INT Y,
6798 IN INT Width,
6799 IN INT Height,
6800 IN BRUSHOBJ *BrushObj)
6801{
6802 RECTL DestRect;
6803 SURFACE *psurf = dc->dclevel.pSurface;
6804
6806 ASSERT(psurf != NULL);
6807
6808 if (Width < 0)
6809 {
6810 X += Width;
6811 Width = -Width;
6812 }
6813
6814 if (Height < 0)
6815 {
6816 Y += Height;
6817 Height = -Height;
6818 }
6819
6820 DestRect.left = X;
6821 DestRect.right = X + Width;
6822 DestRect.top = Y;
6823 DestRect.bottom = Y + Height;
6824
6825 IntEngBitBlt(&psurf->SurfObj,
6826 NULL,
6827 NULL,
6828 (CLIPOBJ *)&dc->co,
6829 NULL,
6830 &DestRect,
6831 NULL,
6832 NULL,
6833 BrushObj,
6834 &PointZero,
6836}
6837
6838
6839BOOL
6842 IN PDC dc,
6843 IN INT XStart,
6844 IN INT YStart,
6845 IN UINT fuOptions,
6848 IN INT Count,
6849 IN OPTIONAL LPINT Dx,
6850 IN DWORD dwCodePage)
6851{
6852 /*
6853 * FIXME:
6854 * Call EngTextOut, which does the real work (calling DrvTextOut where
6855 * appropriate)
6856 */
6857
6858 PDC_ATTR pdcattr;
6859 SURFOBJ *psoDest, *psoGlyph;
6860 SURFACE *psurf;
6861 INT glyph_index, i;
6862 FT_Face face;
6863 FT_BitmapGlyph realglyph;
6864 LONGLONG X64, Y64, RealXStart64, RealYStart64, DeltaX64, DeltaY64;
6865 ULONG previous;
6866 RECTL DestRect, MaskRect;
6867 HBITMAP hbmGlyph;
6868 SIZEL glyphSize;
6869 FONTOBJ *FontObj;
6870 PFONTGDI FontGDI;
6871 PTEXTOBJ TextObj = NULL;
6872 EXLATEOBJ exloRGB2Dst, exloDst2RGB;
6873 POINT Start;
6874 PMATRIX pmxWorldToDevice;
6875 FT_Vector delta, vecAscent64, vecDescent64, vec;
6876 LOGFONTW *plf;
6877 BOOL use_kerning, bResult, DoBreak;
6879 FT_Matrix mat;
6880 BOOL bNoTransform;
6881 DWORD ch0, ch1;
6882 const DWORD del = 0x7f, nbsp = 0xa0; // DEL is ASCII DELETE and nbsp is a non-breaking space
6883 FONTLINK_CHAIN Chain;
6884 SIZE spaceWidth;
6885
6886 /* Check if String is valid */
6887 if (Count > 0xFFFF || (Count > 0 && String == NULL))
6888 {
6890 return FALSE;
6891 }
6892
6893 if (PATH_IsPathOpen(dc->dclevel))
6894 {
6895 return PATH_ExtTextOut(dc,
6896 XStart, YStart,
6897 fuOptions,
6898 lprc,
6899 String, Count,
6900 Dx);
6901 }
6902
6904
6905 if (!dc->dclevel.pSurface)
6906 {
6907 /* Memory DC with no surface selected */
6908 bResult = TRUE;
6909 goto Cleanup;
6910 }
6911
6912 pdcattr = dc->pdcattr;
6913 if (pdcattr->flTextAlign & TA_UPDATECP)
6914 {
6915 Start.x = pdcattr->ptlCurrent.x;
6916 Start.y = pdcattr->ptlCurrent.y;
6917 }
6918 else
6919 {
6920 Start.x = XStart;
6921 Start.y = YStart;
6922 }
6923
6924 IntLPtoDP(dc, &Start, 1);
6925 RealXStart64 = ((LONGLONG)Start.x + dc->ptlDCOrig.x) << 6;
6926 RealYStart64 = ((LONGLONG)Start.y + dc->ptlDCOrig.y) << 6;
6927
6928 MaskRect.left = 0;
6929 MaskRect.top = 0;
6930
6931 psurf = dc->dclevel.pSurface;
6932 psoDest = &psurf->SurfObj;
6933
6934 if (pdcattr->iGraphicsMode == GM_ADVANCED)
6935 pmxWorldToDevice = DC_pmxWorldToDevice(dc);
6936 else
6937 pmxWorldToDevice = (PMATRIX)&gmxWorldToDeviceDefault;
6938
6939 if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
6941
6942 if (lprc && (fuOptions & (ETO_CLIPPED | ETO_OPAQUE)))
6943 {
6944 IntLPtoDP(dc, (POINT*)lprc, 2);
6945 lprc->left += dc->ptlDCOrig.x;
6946 lprc->top += dc->ptlDCOrig.y;
6947 lprc->right += dc->ptlDCOrig.x;
6948 lprc->bottom += dc->ptlDCOrig.y;
6949 }
6950
6951 if (lprc && (fuOptions & ETO_OPAQUE))
6952 {
6954 lprc->left, lprc->top,
6955 lprc->right - lprc->left, lprc->bottom - lprc->top,
6956 &dc->eboBackground.BrushObject);
6957 fuOptions &= ~ETO_OPAQUE;
6958 }
6959 else
6960 {
6961 if (pdcattr->jBkMode == OPAQUE)
6962 {
6963 fuOptions |= ETO_OPAQUE;
6964 }
6965 }
6966
6967 TextObj = RealizeFontInit(pdcattr->hlfntNew);
6968 if (TextObj == NULL)
6969 {
6970 bResult = FALSE;
6971 goto Cleanup;
6972 }
6973
6974 FontObj = TextObj->Font;
6975 ASSERT(FontObj);
6976 FontGDI = ObjToGDI(FontObj, FONT);
6977 ASSERT(FontGDI);
6978
6980 Cache.Hashed.Face = face = FontGDI->SharedFace->Face;
6981
6982 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
6983 Cache.Hashed.lfHeight = plf->lfHeight;
6984 Cache.Hashed.lfWidth = plf->lfWidth;
6985 Cache.Hashed.Aspect.Emu.Bold = EMUBOLD_NEEDED(FontGDI->OriginalWeight, plf->lfWeight);
6986 Cache.Hashed.Aspect.Emu.Italic = (plf->lfItalic && !FontGDI->OriginalItalic);
6987
6989 Cache.Hashed.Aspect.RenderMode = (BYTE)IntGetFontRenderMode(plf);
6990 else
6991 Cache.Hashed.Aspect.RenderMode = (BYTE)FT_RENDER_MODE_MONO;
6992
6993 if (!TextIntUpdateSize(dc, TextObj, FontGDI, FALSE))
6994 {
6996 bResult = FALSE;
6997 goto Cleanup;
6998 }
6999
7000 FontLink_Chain_Init(&Chain, TextObj, face);
7001
7002 /* Apply lfEscapement */
7003 if (FT_IS_SCALABLE(face) && plf->lfEscapement != 0)
7004 IntEscapeMatrix(&Cache.Hashed.matTransform, plf->lfEscapement);
7005 else
7006 Cache.Hashed.matTransform = identityMat;
7007
7008 /* Apply the world transformation */
7009 IntMatrixFromMx(&mat, pmxWorldToDevice);
7010 FT_Matrix_Multiply(&mat, &Cache.Hashed.matTransform);
7011 FT_Set_Transform(face, &Cache.Hashed.matTransform, NULL);
7012
7013 /* Is there no transformation? */
7014 bNoTransform = ((mat.xy == 0) && (mat.yx == 0) &&
7015 (mat.xx == (1 << 16)) && (mat.yy == (1 << 16)));
7016
7017 /* Calculate the ascent point and the descent point */
7018 vecAscent64.x = 0;
7019 vecAscent64.y = (FontGDI->tmAscent << 6);
7020 FT_Vector_Transform(&vecAscent64, &Cache.Hashed.matTransform);
7021 vecDescent64.x = 0;
7022 vecDescent64.y = -(FontGDI->tmDescent << 6);
7023 FT_Vector_Transform(&vecDescent64, &Cache.Hashed.matTransform);
7024
7025 /* Process the vertical alignment and fix the real starting point. */
7026#define VALIGN_MASK (TA_TOP | TA_BASELINE | TA_BOTTOM)
7027 if ((pdcattr->flTextAlign & VALIGN_MASK) == TA_BASELINE)
7028 {
7029 NOTHING;
7030 }
7031 else if ((pdcattr->flTextAlign & VALIGN_MASK) == TA_BOTTOM)
7032 {
7033 RealXStart64 -= vecDescent64.x;
7034 RealYStart64 += vecDescent64.y;
7035 }
7036 else /* TA_TOP */
7037 {
7038 RealXStart64 -= vecAscent64.x;
7039 RealYStart64 += vecAscent64.y;
7040 }
7041#undef VALIGN_MASK
7042
7043 use_kerning = FT_HAS_KERNING(face);
7044
7045 /* Calculate the text width if necessary */
7046 if ((fuOptions & ETO_OPAQUE) || (pdcattr->flTextAlign & (TA_CENTER | TA_RIGHT)))
7047 {
7048 if (!IntGetTextDisposition(&DeltaX64, &DeltaY64, String, Count, Dx, &Cache,
7049 fuOptions, bNoTransform, &Chain))
7050 {
7051 FontLink_Chain_Finish(&Chain);
7053 bResult = FALSE;
7054 goto Cleanup;
7055 }
7056
7057 /* Adjust the horizontal position by horizontal alignment */
7058 if ((pdcattr->flTextAlign & TA_CENTER) == TA_CENTER)
7059 {
7060 RealXStart64 -= DeltaX64 / 2;
7061 RealYStart64 -= DeltaY64 / 2;
7062 }
7063 else if ((pdcattr->flTextAlign & TA_RIGHT) == TA_RIGHT)
7064 {
7065 RealXStart64 -= DeltaX64;
7066 RealYStart64 -= DeltaY64;
7067 }
7068
7069 /* Fill background */
7070 if (fuOptions & ETO_OPAQUE)
7071 {
7072 INT X0 = (RealXStart64 + vecAscent64.x + 32) >> 6;
7073 INT Y0 = (RealYStart64 - vecAscent64.y + 32) >> 6;
7074 INT DX = (DeltaX64 >> 6);
7075 if (Cache.Hashed.matTransform.xy == 0 && Cache.Hashed.matTransform.yx == 0)
7076 {
7077 INT CY = (vecAscent64.y - vecDescent64.y + 32) >> 6;
7078 IntEngFillBox(dc, X0, Y0, DX, CY, &dc->eboBackground.BrushObject);
7079 }
7080 else
7081 {
7082 INT DY = (DeltaY64 >> 6);
7083 INT X1 = ((RealXStart64 + vecDescent64.x + 32) >> 6);
7084 INT Y1 = ((RealYStart64 - vecDescent64.y + 32) >> 6);
7085 POINT Points[4] =
7086 {
7087 { X0, Y0 },
7088 { X0 + DX, Y0 + DY },
7089 { X1 + DX, Y1 + DY },
7090 { X1, Y1 },
7091 };
7092 IntEngFillPolygon(dc, Points, 4, &dc->eboBackground.BrushObject);
7093 }
7094 }
7095 }
7096
7097 EXLATEOBJ_vInitialize(&exloRGB2Dst, &gpalRGB, psurf->ppal, 0, 0, 0);
7098 EXLATEOBJ_vInitialize(&exloDst2RGB, psurf->ppal, &gpalRGB, 0, 0, 0);
7099
7100 if (pdcattr->ulDirty_ & DIRTY_TEXT)
7102
7103 /*
7104 * The main rendering loop.
7105 */
7106 X64 = RealXStart64;
7107 Y64 = RealYStart64;
7108 previous = 0;
7109 DoBreak = FALSE;
7110 bResult = TRUE; /* Assume success */
7111 for (i = 0; i < Count; ++i)
7112 {
7113 ch0 = *String++;
7114 if (IS_HIGH_SURROGATE(ch0))
7115 {
7116 ++i;
7117 if (i >= Count)
7118 break;
7119
7120 ch1 = *String++;
7121 if (IS_LOW_SURROGATE(ch1))
7122 ch0 = Utf32FromSurrogatePair(ch0, ch1);
7123 }
7124
7125 glyph_index = FontLink_Chain_FindGlyph(&Chain, &Cache, &face, ch0,
7126 (fuOptions & ETO_GLYPH_INDEX));
7127 Cache.Hashed.GlyphIndex = glyph_index;
7128
7129 realglyph = IntGetRealGlyph(&Cache);
7130 if (!realglyph)
7131 {
7132 bResult = FALSE;
7133 break;
7134 }
7135
7136 /* retrieve kerning distance and move pen position */
7137 if (use_kerning && previous && glyph_index && NULL == Dx)
7138 {
7139 FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
7140 X64 += delta.x;
7141 Y64 -= delta.y;
7142 }
7143
7144 DPRINT("X64, Y64: %I64d, %I64d\n", X64, Y64);
7145 DPRINT("Advance: %d, %d\n", realglyph->root.advance.x, realglyph->root.advance.y);
7146
7147 glyphSize.cx = realglyph->bitmap.width;
7148 glyphSize.cy = realglyph->bitmap.rows;
7149
7150 /* Do chars > space & not DEL & not nbsp have a glyphSize.cx of zero? */
7151 if (ch0 > L' ' && ch0 != del && ch0 != nbsp && glyphSize.cx == 0)
7152 DPRINT1("WARNING: WChar 0x%04x has a glyphSize.cx of zero\n", ch0);
7153
7154 /* Don't ignore spaces or non-breaking spaces when computing offset.
7155 * This completes the fix of CORE-11787. */
7156 if ((pdcattr->flTextAlign & TA_UPDATECP) && glyphSize.cx == 0 &&
7157 (ch0 == L' ' || ch0 == nbsp)) // Space chars needing x-dim widths
7158 {
7160 /* Get the width of the space character */
7161 TextIntGetTextExtentPoint(dc, TextObj, L" ", 1, 0, NULL, 0, &spaceWidth, 0);
7163 glyphSize.cx = spaceWidth.cx;
7164 realglyph->left = 0;
7165 }
7166
7167 MaskRect.right = realglyph->bitmap.width;
7168 MaskRect.bottom = realglyph->bitmap.rows;
7169
7170 DestRect.left = ((X64 + 32) >> 6) + realglyph->left;
7171 DestRect.right = DestRect.left + glyphSize.cx;
7172 DestRect.top = ((Y64 + 32) >> 6) - realglyph->top;
7173 DestRect.bottom = DestRect.top + glyphSize.cy;
7174
7175 /* Check if the bitmap has any pixels */
7176 if ((glyphSize.cx != 0) && (glyphSize.cy != 0))
7177 {
7178 /*
7179 * We should create the bitmap out of the loop at the biggest possible
7180 * glyph size. Then use memset with 0 to clear it and sourcerect to
7181 * limit the work of the transbitblt.
7182 */
7183 hbmGlyph = EngCreateBitmap(glyphSize, realglyph->bitmap.pitch,
7185 realglyph->bitmap.buffer);
7186 if (!hbmGlyph)
7187 {
7188 DPRINT1("WARNING: EngCreateBitmap() failed!\n");
7189 bResult = FALSE;
7190 break;
7191 }
7192
7193 psoGlyph = EngLockSurface((HSURF)hbmGlyph);
7194 if (!psoGlyph)
7195 {
7196 EngDeleteSurface((HSURF)hbmGlyph);
7197 DPRINT1("WARNING: EngLockSurface() failed!\n");
7198 bResult = FALSE;
7199 break;
7200 }
7201
7202 /*
7203 * Use the font data as a mask to paint onto the DCs surface using a
7204 * brush.
7205 */
7206 if (lprc && (fuOptions & ETO_CLIPPED))
7207 {
7208 // We do the check '>=' instead of '>' to possibly save an iteration
7209 // through this loop, since it's breaking after the drawing is done,
7210 // and x is always incremented.
7211 if (DestRect.right >= lprc->right)
7212 {
7213 DestRect.right = lprc->right;
7214 DoBreak = TRUE;
7215 }
7216
7217 if (DestRect.bottom >= lprc->bottom)
7218 {
7219 DestRect.bottom = lprc->bottom;
7220 }
7221 }
7222
7223 if (!IntEngMaskBlt(psoDest,
7224 psoGlyph,
7225 (CLIPOBJ *)&dc->co,
7226 &exloRGB2Dst.xlo,
7227 &exloDst2RGB.xlo,
7228 &DestRect,
7229 (PPOINTL)&MaskRect,
7230 &dc->eboText.BrushObject,
7231 &PointZero))
7232 {
7233 DPRINT1("Failed to MaskBlt a glyph!\n");
7234 }
7235
7236 EngUnlockSurface(psoGlyph);
7237 EngDeleteSurface((HSURF)hbmGlyph);
7238 }
7239
7240 if (DoBreak)
7241 break;
7242
7243 if (NULL == Dx)
7244 {
7245 X64 += realglyph->root.advance.x >> 10;
7246 Y64 -= realglyph->root.advance.y >> 10;
7247 }
7248 else if (fuOptions & ETO_PDY)
7249 {
7250 vec.x = (Dx[2 * i + 0] << 6);
7251 vec.y = (Dx[2 * i + 1] << 6);
7252 if (!bNoTransform)
7253 FT_Vector_Transform(&vec, &Cache.Hashed.matTransform);
7254 X64 += vec.x;
7255 Y64 -= vec.y;
7256 }
7257 else
7258 {
7259 vec.x = (Dx[i] << 6);
7260 vec.y = 0;
7261 if (!bNoTransform)
7262 FT_Vector_Transform(&vec, &Cache.Hashed.matTransform);
7263 X64 += vec.x;
7264 Y64 -= vec.y;
7265 }
7266
7267 DPRINT("New X64, New Y64: %I64d, %I64d\n", X64, Y64);
7268
7269 previous = glyph_index;
7270 }
7271 /* Don't update position if String == NULL. Fixes CORE-19721. */
7272 if ((pdcattr->flTextAlign & TA_UPDATECP) && String)
7273 pdcattr->ptlCurrent.x = DestRect.right - dc->ptlDCOrig.x;
7274
7275 if (plf->lfUnderline || plf->lfStrikeOut) /* Underline or strike-out? */
7276 {
7277 /* Calculate the position and the thickness */
7278 INT underline_position, thickness;
7279 FT_Vector vecA64, vecB64;
7280
7281 DeltaX64 = X64 - RealXStart64;
7282 DeltaY64 = Y64 - RealYStart64;
7283
7284 if (!face->units_per_EM)
7285 {
7287 thickness = 1;
7288 }
7289 else
7290 {
7292 face->underline_position * face->size->metrics.y_ppem / face->units_per_EM;
7293 thickness =
7294 face->underline_thickness * face->size->metrics.y_ppem / face->units_per_EM;
7295 if (thickness <= 0)
7296 thickness = 1;
7297 }
7298
7299 if (plf->lfUnderline) /* Draw underline */
7300 {
7301 vecA64.x = 0;
7302 vecA64.y = (-underline_position - thickness / 2) << 6;
7303 vecB64.x = 0;
7304 vecB64.y = vecA64.y + (thickness << 6);
7305 FT_Vector_Transform(&vecA64, &Cache.Hashed.matTransform);
7306 FT_Vector_Transform(&vecB64, &Cache.Hashed.matTransform);
7307 {
7308 INT X0 = (RealXStart64 - vecA64.x + 32) >> 6;
7309 INT Y0 = (RealYStart64 + vecA64.y + 32) >> 6;
7310 INT DX = (DeltaX64 >> 6);
7311 if (Cache.Hashed.matTransform.xy == 0 && Cache.Hashed.matTransform.yx == 0)
7312 {
7313 INT CY = (vecB64.y - vecA64.y + 32) >> 6;
7314 IntEngFillBox(dc, X0, Y0, DX, CY, &dc->eboText.BrushObject);
7315 }
7316 else
7317 {
7318 INT DY = (DeltaY64 >> 6);
7319 INT X1 = X0 + ((vecA64.x - vecB64.x + 32) >> 6);
7320 INT Y1 = Y0 + ((vecB64.y - vecA64.y + 32) >> 6);
7321 POINT Points[4] =
7322 {
7323 { X0, Y0 },
7324 { X0 + DX, Y0 + DY },
7325 { X1 + DX, Y1 + DY },
7326 { X1, Y1 },
7327 };
7328 IntEngFillPolygon(dc, Points, 4, &dc->eboText.BrushObject);
7329 }
7330 }
7331 }
7332
7333 if (plf->lfStrikeOut) /* Draw strike-out */
7334 {
7335 vecA64.x = 0;
7336 vecA64.y = -(FontGDI->tmAscent << 6) / 3;
7337 vecB64.x = 0;
7338 vecB64.y = vecA64.y + (thickness << 6);
7339 FT_Vector_Transform(&vecA64, &Cache.Hashed.matTransform);
7340 FT_Vector_Transform(&vecB64, &Cache.Hashed.matTransform);
7341 {
7342 INT X0 = (RealXStart64 - vecA64.x + 32) >> 6;
7343 INT Y0 = (RealYStart64 + vecA64.y + 32) >> 6;
7344 INT DX = (DeltaX64 >> 6);
7345 if (Cache.Hashed.matTransform.xy == 0 && Cache.Hashed.matTransform.yx == 0)
7346 {
7347 INT CY = (vecB64.y - vecA64.y + 32) >> 6;
7348 IntEngFillBox(dc, X0, Y0, DX, CY, &dc->eboText.BrushObject);
7349 }
7350 else
7351 {
7352 INT DY = (DeltaY64 >> 6);
7353 INT X1 = X0 + ((vecA64.x - vecB64.x + 32) >> 6);
7354 INT Y1 = Y0 + ((vecB64.y - vecA64.y + 32) >> 6);
7355 POINT Points[4] =
7356 {
7357 { X0, Y0 },
7358 { X0 + DX, Y0 + DY },
7359 { X1 + DX, Y1 + DY },
7360 { X1, Y1 },
7361 };
7362 IntEngFillPolygon(dc, Points, 4, &dc->eboText.BrushObject);
7363 }
7364 }
7365 }
7366 }
7367
7368 FontLink_Chain_Finish(&Chain);
7369
7371
7372 EXLATEOBJ_vCleanup(&exloRGB2Dst);
7373 EXLATEOBJ_vCleanup(&exloDst2RGB);
7374
7375Cleanup:
7377
7378 if (TextObj != NULL)
7379 TEXTOBJ_UnlockText(TextObj);
7380
7381 return bResult;
7382}
7383
7384
7385BOOL
7388 IN HDC hDC,
7389 IN INT XStart,
7390 IN INT YStart,
7391 IN UINT fuOptions,
7394 IN INT Count,
7395 IN OPTIONAL LPINT Dx,
7396 IN DWORD dwCodePage)
7397{
7398 BOOL bResult;
7399 DC *dc;
7400
7401 // TODO: Write test-cases to exactly match real Windows in different
7402 // bad parameters (e.g. does Windows check the DC or the RECT first?).
7403 dc = DC_LockDc(hDC);
7404 if (!dc)
7405 {
7407 return FALSE;
7408 }
7409
7410 bResult = IntExtTextOutW( dc,
7411 XStart,
7412 YStart,
7413 fuOptions,
7414 lprc,
7415 String,
7416 Count,
7417 Dx,
7418 dwCodePage );
7419
7420 DC_UnlockDc(dc);
7421
7422 return bResult;
7423}
7424
7425#define STACK_TEXT_BUFFER_SIZE 512
7426
7427BOOL
7430 IN HDC hDC,
7431 IN INT XStart,
7432 IN INT YStart,
7433 IN UINT fuOptions,
7434 IN OPTIONAL LPCRECT UnsafeRect,
7435 IN LPCWSTR UnsafeString,
7436 IN UINT Count,
7437 IN OPTIONAL const INT *UnsafeDx,
7438 IN DWORD dwCodePage)
7439{
7440 BOOL Result = FALSE;
7442 RECTL SafeRect;
7443 BYTE LocalBuffer[STACK_TEXT_BUFFER_SIZE];
7444 PVOID Buffer = LocalBuffer;
7445 LPCWSTR SafeString = NULL;
7446 LPINT SafeDx = NULL;
7447 ULONG BufSize, StringSize, DxSize = 0;
7448
7449 /* Check if String is valid */
7450 if ((Count > 0xFFFF) || (Count > 0 && UnsafeString == NULL))
7451 {
7453 return FALSE;
7454 }
7455
7456 if (Count > 0)
7457 {
7458 /* Calculate buffer size for string and Dx values */
7459 BufSize = StringSize = Count * sizeof(WCHAR);
7460 if (UnsafeDx)
7461 {
7462 /* If ETO_PDY is specified, we have pairs of INTs */
7463 DxSize = (Count * sizeof(INT)) * ((fuOptions & ETO_PDY) ? 2 : 1);
7464 BufSize += DxSize;
7465 }
7466
7467 /* Check if our local buffer is large enough */
7468 if (BufSize > sizeof(LocalBuffer))
7469 {
7470 /* It's not, allocate a temp buffer */
7472 if (!Buffer)
7473 {
7474 return FALSE;
7475 }
7476 }
7477
7478 /* Probe and copy user mode data to the buffer */
7479 _SEH2_TRY
7480 {
7481 /* Put the Dx before the String to assure alignment of 4 */
7482 SafeString = (LPCWSTR)(((ULONG_PTR)Buffer) + DxSize);
7483
7484 /* Probe and copy the string */
7485 ProbeForRead(UnsafeString, StringSize, 1);
7486 RtlCopyMemory((PVOID)SafeString, UnsafeString, StringSize);
7487
7488 /* If we have Dx values... */
7489 if (UnsafeDx)
7490 {
7491 /* ... probe and copy them */
7492 SafeDx = Buffer;
7493 ProbeForRead(UnsafeDx, DxSize, 1);
7494 RtlCopyMemory(SafeDx, UnsafeDx, DxSize);
7495 }
7496 }
7498 {
7500 }
7501 _SEH2_END
7502 if (!NT_SUCCESS(Status))
7503 {
7504 goto cleanup;
7505 }
7506 }
7507
7508 /* If we have a rect, copy it */
7509 if (UnsafeRect)
7510 {
7511 _SEH2_TRY
7512 {
7513 ProbeForRead(UnsafeRect, sizeof(RECT), 1);
7514 SafeRect = *UnsafeRect;
7515 }
7517 {
7519 }
7520 _SEH2_END
7521 if (!NT_SUCCESS(Status))
7522 {
7523 goto cleanup;
7524 }
7525 }
7526
7527 /* Finally call the internal routine */
7529 XStart,
7530 YStart,
7531 fuOptions,
7532 &SafeRect,
7533 SafeString,
7534 Count,
7535 SafeDx,
7536 dwCodePage);
7537
7538cleanup:
7539 /* If we allocated a buffer, free it */
7540 if (Buffer != LocalBuffer)
7541 {
7543 }
7544
7545 return Result;
7546}
7547
7548
7549/*
7550* @implemented
7551*/
7552BOOL
7555 IN HDC hDC,
7556 IN UINT FirstChar,
7557 IN ULONG Count,
7558 IN OPTIONAL PWCHAR UnSafepwch,
7559 IN FLONG fl,
7561{
7562 LPABC SafeBuff;
7563 LPABCFLOAT SafeBuffF = NULL;
7564 PDC dc;
7565 PDC_ATTR pdcattr;
7566 PTEXTOBJ TextObj;
7567 PFONTGDI FontGDI;
7568 FT_Face face;
7569 FT_CharMap charmap, found = NULL;
7570 UINT i, glyph_index, BufferSize;
7571 HFONT hFont = 0;
7573 PWCHAR Safepwch = NULL;
7574 LOGFONTW *plf;
7575
7576 if (!Buffer)
7577 {
7579 return FALSE;
7580 }
7581
7582 if (UnSafepwch)
7583 {
7584 UINT pwchSize = Count * sizeof(WCHAR);
7585 Safepwch = ExAllocatePoolWithTag(PagedPool, pwchSize, GDITAG_TEXT);
7586
7587 if(!Safepwch)
7588 {
7590 return FALSE;
7591 }
7592
7593 _SEH2_TRY
7594 {
7595 ProbeForRead(UnSafepwch, pwchSize, 1);
7596 RtlCopyMemory(Safepwch, UnSafepwch, pwchSize);
7597 }
7599 {
7601 }
7602 _SEH2_END;
7603 }
7604
7605 if (!NT_SUCCESS(Status))
7606 {
7607 if(Safepwch)
7608 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
7609
7611 return FALSE;
7612 }
7613
7614 BufferSize = Count * sizeof(ABC); // Same size!
7616 if (!fl) SafeBuffF = (LPABCFLOAT) SafeBuff;
7617 if (SafeBuff == NULL)
7618 {
7619
7620 if(Safepwch)
7621 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
7622
7624 return FALSE;
7625 }
7626
7627 dc = DC_LockDc(hDC);
7628 if (dc == NULL)
7629 {
7630 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7631
7632 if(Safepwch)
7633 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
7634
7636 return FALSE;
7637 }
7638 pdcattr = dc->pdcattr;
7639 hFont = pdcattr->hlfntNew;
7640 TextObj = RealizeFontInit(hFont);
7641
7642 DC_UnlockDc(dc);
7643
7644 if (TextObj == NULL)
7645 {
7646 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7647
7648 if(Safepwch)
7649 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
7650
7652 return FALSE;
7653 }
7654
7655 FontGDI = ObjToGDI(TextObj->Font, FONT);
7656
7657 face = FontGDI->SharedFace->Face;
7658 if (face->charmap == NULL)
7659 {
7660 for (i = 0; i < (UINT)face->num_charmaps; i++)
7661 {
7662 charmap = face->charmaps[i];
7663 if (charmap->encoding != 0)
7664 {
7665 found = charmap;
7666 break;
7667 }
7668 }
7669
7670 if (!found)
7671 {
7672 DPRINT1("WARNING: Could not find desired charmap!\n");
7673 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7674
7675 if(Safepwch)
7676 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
7677
7679 return FALSE;
7680 }
7681
7683 FT_Set_Charmap(face, found);
7685 }
7686
7687 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
7688
7689 // NOTE: GetCharABCWidths simply ignores lfEscapement and XFORM.
7691 IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
7693
7694 for (i = FirstChar; i < FirstChar+Count; i++)
7695 {
7696 int adv, lsb, bbx, left, right;
7697
7698 if (Safepwch)
7699 {
7700 glyph_index = get_glyph_index_flagged(face, Safepwch[i - FirstChar], (fl & GCABCW_INDICES));
7701 }
7702 else
7703 {
7704 glyph_index = get_glyph_index_flagged(face, i, (fl & GCABCW_INDICES));
7705 }
7706 FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
7707
7708 left = (INT)face->glyph->metrics.horiBearingX & -64;
7709 right = (INT)((face->glyph->metrics.horiBearingX + face->glyph->metrics.width) + 63) & -64;
7710 adv = (face->glyph->advance.x + 32) >> 6;
7711
7712// int test = (INT)(face->glyph->metrics.horiAdvance + 63) >> 6;
7713// DPRINT1("Advance Wine %d and Advance Ros %d\n",test, adv ); /* It's the same! */
7714
7715 lsb = left >> 6;
7716 bbx = (right - left) >> 6;
7717 /*
7718 DPRINT1("lsb %d and bbx %d\n", lsb, bbx );
7719 */
7720 if (!fl)
7721 {
7722 SafeBuffF[i - FirstChar].abcfA = (FLOAT) lsb;
7723 SafeBuffF[i - FirstChar].abcfB = (FLOAT) bbx;
7724 SafeBuffF[i - FirstChar].abcfC = (FLOAT) (adv - lsb - bbx);
7725 }
7726 else
7727 {
7728 SafeBuff[i - FirstChar].abcA = lsb;
7729 SafeBuff[i - FirstChar].abcB = bbx;
7730 SafeBuff[i - FirstChar].abcC = adv - lsb - bbx;
7731 }
7732 }
7734 TEXTOBJ_UnlockText(TextObj);
7735 Status = MmCopyToCaller(Buffer, SafeBuff, BufferSize);
7736
7737 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7738
7739 if(Safepwch)
7740 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
7741
7742 if (!NT_SUCCESS(Status))
7743 {
7745 return FALSE;
7746 }
7747
7748 DPRINT("NtGdiGetCharABCWidths Worked!\n");
7749 return TRUE;
7750}
7751
7752/*
7753* @implemented
7754*/
7755BOOL
7758 IN HDC hDC,
7759 IN UINT FirstChar,
7760 IN UINT Count,
7761 IN OPTIONAL PWCHAR UnSafepwc,
7762 IN FLONG fl,
7764{
7766 LPINT SafeBuff;
7767 PFLOAT SafeBuffF = NULL;
7768 PDC dc;
7769 PDC_ATTR pdcattr;
7770 PTEXTOBJ TextObj;
7771 PFONTGDI FontGDI;
7772 FT_Face face;
7773 FT_CharMap charmap, found = NULL;
7774 UINT i, glyph_index, BufferSize;
7775 HFONT hFont = 0;
7776 PWCHAR Safepwc = NULL;
7777 LOGFONTW *plf;
7778
7779 if (UnSafepwc)
7780 {
7781 UINT pwcSize = Count * sizeof(WCHAR);
7782 Safepwc = ExAllocatePoolWithTag(PagedPool, pwcSize, GDITAG_TEXT);
7783
7784 if(!Safepwc)
7785 {
7787 return FALSE;
7788 }
7789 _SEH2_TRY
7790 {
7791 ProbeForRead(UnSafepwc, pwcSize, 1);
7792 RtlCopyMemory(Safepwc, UnSafepwc, pwcSize);
7793 }
7795 {
7797 }
7798 _SEH2_END;
7799 }
7800
7801 if (!NT_SUCCESS(Status))
7802 {
7804 return FALSE;
7805 }
7806
7807 BufferSize = Count * sizeof(INT); // Same size!
7809 if (!fl) SafeBuffF = (PFLOAT) SafeBuff;
7810 if (SafeBuff == NULL)
7811 {
7812 if(Safepwc)
7814
7816 return FALSE;
7817 }
7818
7819 dc = DC_LockDc(hDC);
7820 if (dc == NULL)
7821 {
7822 if(Safepwc)
7824
7825 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7827 return FALSE;
7828 }
7829 pdcattr = dc->pdcattr;
7830 hFont = pdcattr->hlfntNew;
7831 TextObj = RealizeFontInit(hFont);
7832 DC_UnlockDc(dc);
7833
7834 if (TextObj == NULL)
7835 {
7836 if(Safepwc)
7838
7839 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7841 return FALSE;
7842 }
7843
7844 FontGDI = ObjToGDI(TextObj->Font, FONT);
7845
7846 face = FontGDI->SharedFace->Face;
7847 if (face->charmap == NULL)
7848 {
7849 for (i = 0; i < (UINT)face->num_charmaps; i++)
7850 {
7851 charmap = face->charmaps[i];
7852 if (charmap->encoding != 0)
7853 {
7854 found = charmap;
7855 break;
7856 }
7857 }
7858
7859 if (!found)
7860 {
7861 DPRINT1("WARNING: Could not find desired charmap!\n");
7862
7863 if(Safepwc)
7865
7866 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7868 return FALSE;
7869 }
7870
7872 FT_Set_Charmap(face, found);
7874 }
7875
7876 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
7877
7878 // NOTE: GetCharWidth simply ignores lfEscapement and XFORM.
7880 IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
7882
7883 for (i = FirstChar; i < FirstChar+Count; i++)
7884 {
7885 if (Safepwc)
7886 {
7887 glyph_index = get_glyph_index_flagged(face, Safepwc[i - FirstChar], (fl & GCW_INDICES));
7888 }
7889 else
7890 {
7891 glyph_index = get_glyph_index_flagged(face, i, (fl & GCW_INDICES));
7892 }
7893 FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
7894 if (!fl)
7895 SafeBuffF[i - FirstChar] = (FLOAT) ((face->glyph->advance.x + 32) >> 6);
7896 else
7897 SafeBuff[i - FirstChar] = (face->glyph->advance.x + 32) >> 6;
7898 }
7900 TEXTOBJ_UnlockText(TextObj);
7901 MmCopyToCaller(Buffer, SafeBuff, BufferSize);
7902
7903 if(Safepwc)
7905
7906 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7907 return TRUE;
7908}
7909
7910
7911/*
7912* @implemented
7913*/
7914// TODO: Move this code into NtGdiGetGlyphIndicesWInternal and wrap
7915// NtGdiGetGlyphIndicesW around NtGdiGetGlyphIndicesWInternal instead.
7916// NOTE: See also GreGetGlyphIndicesW.
7918W32KAPI
7919DWORD
7922 _In_ HDC hdc,
7923 _In_reads_opt_(cwc) LPCWSTR pwc,
7924 _In_ INT cwc,
7927{
7928 PDC dc;
7929 PDC_ATTR pdcattr;
7930 PTEXTOBJ TextObj;
7931 PFONTGDI FontGDI;
7932 HFONT hFont = NULL;
7934 OUTLINETEXTMETRICW *potm;
7935 INT i;
7936 WCHAR DefChar = 0xffff;
7937 PWSTR Buffer = NULL;
7938 ULONG Size, pwcSize;
7939 PWSTR Safepwc = NULL;
7940 LPCWSTR UnSafepwc = pwc;
7941 LPWORD UnSafepgi = pgi;
7942 FT_Face Face;
7943 TT_OS2 *pOS2;
7944
7945 if (cwc < 0)
7946 {
7947 DPRINT1("cwc < 0\n");
7948 return GDI_ERROR;
7949 }
7950
7951 if (!UnSafepwc && !UnSafepgi && cwc > 0)
7952 {
7953 DPRINT1("!UnSafepwc && !UnSafepgi && cwc > 0\n");
7954 return GDI_ERROR;
7955 }
7956
7957 if (!UnSafepwc != !UnSafepgi)
7958 {
7959 DPRINT1("UnSafepwc == %p, UnSafepgi = %p\n", UnSafepwc, UnSafepgi);
7960 return GDI_ERROR;
7961 }
7962
7963 /* Get FontGDI */
7964 dc = DC_LockDc(hdc);
7965 if (!dc)
7966 {
7967 DPRINT1("!DC_LockDC\n");
7968 return GDI_ERROR;
7969 }
7970 pdcattr = dc->pdcattr;
7971 hFont = pdcattr->hlfntNew;
7972 TextObj = RealizeFontInit(hFont);
7973 DC_UnlockDc(dc);
7974 if (!TextObj)
7975 {
7976 DPRINT1("!TextObj\n");
7977 return GDI_ERROR;
7978 }
7979 FontGDI = ObjToGDI(TextObj->Font, FONT);
7980 TEXTOBJ_UnlockText(TextObj);
7981
7982 if (cwc == 0)
7983 {
7984 if (!UnSafepwc && !UnSafepgi)
7985 {
7986 Face = FontGDI->SharedFace->Face;
7987 return Face->num_glyphs;
7988 }
7989 else
7990 {
7992 goto ErrorRet;
7993 }
7994 }
7995
7997 if (!Buffer)
7998 {
7999 DPRINT1("ExAllocatePoolWithTag\n");
8000 return GDI_ERROR;
8001 }
8002
8003 /* Get DefChar */
8005 {
8006 DefChar = 0xffff;
8007 }
8008 else
8009 {
8010 Face = FontGDI->SharedFace->Face;
8011 if (FT_IS_SFNT(Face))
8012 {
8014 pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
8015 DefChar = (pOS2->usDefaultChar ? get_glyph_index(Face, pOS2->usDefaultChar) : 0);
8017 }
8018 else
8019 {
8021 Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL, FALSE);
8022 if (!Size)
8023 {
8025 DPRINT1("!Size\n");
8026 goto ErrorRet;
8027 }
8029 if (!potm)
8030 {
8032 DPRINT1("!potm\n");
8033 goto ErrorRet;
8034 }
8036 Size = IntGetOutlineTextMetrics(FontGDI, Size, potm, FALSE);
8037 if (Size)
8038 DefChar = potm->otmTextMetrics.tmDefaultChar;
8040 }
8041 }
8042
8043 /* Allocate for Safepwc */
8044 pwcSize = cwc * sizeof(WCHAR);
8045 Safepwc = ExAllocatePoolWithTag(PagedPool, pwcSize, GDITAG_TEXT);
8046 if (!Safepwc)
8047 {
8049 DPRINT1("!Safepwc\n");
8050 goto ErrorRet;
8051 }
8052
8053 _SEH2_TRY
8054 {
8055 ProbeForRead(UnSafepwc, pwcSize, 1);
8056 RtlCopyMemory(Safepwc, UnSafepwc, pwcSize);
8057 }
8059 {
8061 }
8062 _SEH2_END;
8063
8064 if (!NT_SUCCESS(Status))
8065 {
8066 DPRINT1("Status: %08lX\n", Status);
8067 goto ErrorRet;
8068 }
8069
8070 /* Get glyph indeces */
8072 for (i = 0; i < cwc; i++)
8073 {
8074 Buffer[i] = get_glyph_index(FontGDI->SharedFace->Face, Safepwc[i]);
8075 if (Buffer[i] == 0)
8076 {
8077 Buffer[i] = DefChar;
8078 }
8079 }
8081
8082 _SEH2_TRY
8083 {
8084 ProbeForWrite(UnSafepgi, cwc * sizeof(WORD), 1);
8085 RtlCopyMemory(UnSafepgi, Buffer, cwc * sizeof(WORD));
8086 }
8088 {
8090 }
8091 _SEH2_END;
8092
8093ErrorRet:
8094 if (Buffer != NULL)
8095 {
8097 }
8098 if (Safepwc != NULL)
8099 {
8101 }
8102
8103 if (NT_SUCCESS(Status))
8104 return cwc;
8105
8106 return GDI_ERROR;
8107}
8108
8109/* EOF */
static HDC hDC
Definition: 3dtext.c:33
@ IgnoreFiles
Definition: ACListISF.cpp:75
NTSTATUS NTAPI MmUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:2761
@ 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)
#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)
__kernel_entry W32KAPI DWORD APIENTRY NtGdiGetGlyphIndicesW(_In_ HDC hdc, _In_reads_opt_(cwc) LPCWSTR pwc, _In_ INT cwc, _Out_writes_opt_(cwc) LPWORD pgi, _In_ DWORD iMode)
Definition: freetype.c:7921
BOOL FASTCALL TextIntUpdateSize(PDC dc, PTEXTOBJ TextObj, PFONTGDI FontGDI, BOOL bDoLock)
Definition: freetype.c:4302
VOID APIENTRY IntEngFillPolygon(IN OUT PDC dc, IN POINTL *pPoints, IN UINT cPoints, IN BRUSHOBJ *BrushObj)
Definition: freetype.c:6758
static FT_UInt FASTCALL get_glyph_index_flagged(FT_Face face, FT_ULong code, BOOL fCodeAsIndex)
Definition: freetype.c:4420
#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:3707
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:4451
DWORD FASTCALL ftGdiGetKerningPairs(PFONTGDI Font, DWORD cPairs, LPKERNINGPAIR pKerningPair)
Definition: freetype.c:6465
#define ASSERT_FREETYPE_LOCK_NOT_HELD()
Definition: freetype.c:377
static const CHARSETINFO g_FontTci[MAXTCIINDEX]
Definition: freetype.c:425
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:6516
static PFAST_MUTEX g_FreeTypeLock
Definition: freetype.c:369
VOID FASTCALL IntGdiCleanupMemEntry(PFONT_ENTRY_MEM Head)
Definition: freetype.c:2586
static UINT GetFontPenalty(const LOGFONTW *LogFont, const OUTLINETEXTMETRICW *Otm, const char *style_name)
Definition: freetype.c:5488
static BOOL face_has_symbol_charmap(FT_Face ft_face)
Definition: freetype.c:2831
#define IS_HIGH_SURROGATE(ch0)
Definition: freetype.c:334
static DWORD IntGetHash(IN LPCVOID pv, IN DWORD cdw)
Definition: freetype.c:3847
static BOOL FASTCALL IntGetFullFileName(POBJECT_NAME_INFORMATION NameInfo, ULONG Size, PUNICODE_STRING FileName)
Definition: freetype.c:6101
static FT_Error IntRequestFontSize(PDC dc, PFONTGDI FontGDI, LONG lfWidth, LONG lfHeight)
Definition: freetype.c:4162
static INT FASTCALL IntGdiAddFontResourceSingle(_In_ PCUNICODE_STRING FileName, _In_ DWORD Characteristics, _In_ DWORD dwFlags)
Definition: freetype.c:2091
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:5348
BOOL FASTCALL IntGdiRemoveFontResource(_In_ PCUNICODE_STRING FileName, _In_ DWORD cFiles, _In_ DWORD dwFlags)
Definition: freetype.c:2338
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:5903
FT_Library g_FreeTypeLibrary
Definition: freetype.c:360
BOOL FASTCALL TextIntGetTextExtentPoint(PDC dc, PTEXTOBJ TextObj, LPCWSTR String, INT Count, ULONG MaxExtent, LPINT Fit, LPINT Dx, LPSIZE Size, FLONG fl)
Definition: freetype.c:5039
BOOL APIENTRY GreExtTextOutW(IN HDC hDC, IN INT XStart, IN INT YStart, IN UINT fuOptions, IN OPTIONAL PRECTL lprc, IN LPCWSTR String, IN INT Count, IN OPTIONAL LPINT Dx, IN DWORD dwCodePage)
Definition: freetype.c:7387
BOOL FASTCALL IntGdiGetFontResourceInfo(PUNICODE_STRING FileName, PVOID pBuffer, DWORD *pdwBytes, DWORD dwType)
Definition: freetype.c:6178
static PWCHAR g_ElfScripts[32]
Definition: freetype.c:397
static PSHARED_MEM SharedMem_Create(PBYTE Buffer, ULONG BufferSize, BOOL IsMapping)
Definition: freetype.c:593
ULONG FASTCALL ftGdiGetGlyphOutline(PDC dc, WCHAR wch, UINT iFormat, LPGLYPHMETRICS pgm, ULONG cjBuf, PVOID pvBuf, LPMAT2 pmat2, BOOL bIgnoreRotation)
Definition: freetype.c:4511
static BOOL EqualFamilyInfo(const FONTFAMILYINFO *pInfo1, const FONTFAMILYINFO *pInfo2)
Definition: freetype.c:6144
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:3104
#define CP_SYMBOL
Definition: freetype.c:423
const MATRIX gmxWorldToPageDefault
Definition: dclife.c:36
static UNICODE_STRING g_FontRegPath
Definition: freetype.c:363
BOOL APIENTRY NtGdiGetCharABCWidthsW(IN HDC hDC, IN UINT FirstChar, IN ULONG Count, IN OPTIONAL PWCHAR UnSafepwch, IN FLONG fl, OUT PVOID Buffer)
Definition: freetype.c:7554
VOID FASTCALL IntGdiCleanupPrivateFontsForProcess(VOID)
Definition: freetype.c:2658
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:4037
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:4391
static __inline VOID FindBestFontFromList(FONTOBJ **FontObj, ULONG *MatchPenalty, const LOGFONTW *LogFont, const PLIST_ENTRY Head)
Definition: freetype.c:5834
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 WCHAR s_szDefFontLinkFontName[MAX_PATH]
Definition: freetype.c:67
static LPCWSTR FASTCALL NameFromCharSet(BYTE CharSet)
Definition: freetype.c:2062
BOOL APIENTRY IntExtTextOutW(IN PDC dc, IN INT XStart, IN INT YStart, IN UINT fuOptions, IN OPTIONAL PRECTL lprc, IN LPCWSTR String, IN INT Count, IN OPTIONAL LPINT Dx, IN DWORD dwCodePage)
Definition: freetype.c:6841
VOID FASTCALL IntLoadSystemFonts(VOID)
Definition: freetype.c:1564
DWORD FASTCALL ftGetFontUnicodeRanges(PFONTGDI Font, PGLYPHSET glyphset)
Definition: freetype.c:5274
#define GOT_PENALTY(name, value)
Definition: freetype.c:5484
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:3833
static VOID FASTCALL UnlinkFontMemCollection(PFONT_ENTRY_COLL_MEM Collection)
Definition: freetype.c:2605
INT FASTCALL IntGdiAddFontResourceEx(_In_ PCUNICODE_STRING FileName, _In_ DWORD cFiles, _In_ DWORD Characteristics, _In_ DWORD dwFlags)
Definition: freetype.c:2291
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:4426
static void FASTCALL FontFamilyFillInfo(PFONTFAMILYINFO Info, LPCWSTR FaceName, LPCWSTR FullName, PFONTGDI FontGDI)
Definition: freetype.c:3524
static void SharedFace_Release(PSHARED_FACE Ptr)
Definition: freetype.c:678
static void SwapEndian(LPVOID pvData, DWORD Size)
Definition: freetype.c:3354
static __inline void FASTCALL IntInitFontNames(FONT_NAMES *Names, PSHARED_FACE SharedFace)
Definition: freetype.c:3076
static void RemoveCacheEntries(FT_Face Face)
Definition: freetype.c:629
LONG NTAPI NtGdiGetFontFamilyInfo(HDC Dc, const LOGFONTW *UnsafeLogFont, PFONTFAMILYINFO UnsafeInfo, LPLONG UnsafeInfoCount)
Definition: freetype.c:6556
#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:6446
#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:2714
#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:3964
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
static BOOL FASTCALL IntGdiRemoveFontResourceSingle(_In_ PCUNICODE_STRING FileName, _In_ DWORD dwFlags)
Definition: freetype.c:2330
static VOID FontLink_CleanupCache(VOID)
Definition: freetype.c:312
static __inline BYTE *FASTCALL IntStoreFontNames(const FONT_NAMES *Names, OUTLINETEXTMETRICW *Otm)
Definition: freetype.c:3112
struct _FONTLINK_CHAIN * PFONTLINK_CHAIN
static BOOLEAN IntTranslateCharsetInfo(PDWORD Src, LPCHARSETINFO Cs, DWORD Flags)
Definition: freetype.c:2784
static POINTL PointZero
Definition: freetype.c:355
static VOID IntAddNameFromFamInfo(LPWSTR psz, FONTFAMILYINFO *FamInfo)
Definition: freetype.c:6165
static void FASTCALL FillTM(TEXTMETRICW *TM, PFONTGDI FontGDI, TT_OS2 *pOS2, TT_HoriHeader *pHori, FT_WinFNT_HeaderRec *pFNT)
Definition: freetype.c:2847
#define IntLockFreeType()
Definition: freetype.c:380
static FT_BitmapGlyph IntFindGlyphCache(IN const FONT_CACHE_ENTRY *pCache)
Definition: freetype.c:3862
BOOL APIENTRY NtGdiGetCharWidthW(IN HDC hDC, IN UINT FirstChar, IN UINT Count, IN OPTIONAL PWCHAR UnSafepwc, IN FLONG fl, OUT PVOID Buffer)
Definition: freetype.c:7757
static FT_BitmapGlyph IntGetBitmapGlyphWithCache(IN OUT PFONT_CACHE_ENTRY Cache, IN FT_GlyphSlot GlyphSlot)
Definition: freetype.c:3899
#define STACK_TEXT_BUFFER_SIZE
Definition: freetype.c:7425
static __inline void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
Definition: freetype.c:728
NTSTATUS FASTCALL TextIntCreateFontIndirect(CONST LPLOGFONTW lf, HFONT *NewFont)
Definition: freetype.c:2742
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:2622
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:5988
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:4405
static const FT_Matrix identityMat
Definition: freetype.c:354
HANDLE FASTCALL IntGdiAddFontMemResource(PVOID Buffer, DWORD dwSize, PDWORD pNumAdded)
Definition: freetype.c:2536
static LONG ScaleLong(LONG lValue, PFLOATOBJ pef)
Definition: freetype.c:6652
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:5938
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:3771
struct _FONTLINK_CACHE FONTLINK_CACHE
#define SCALE_X(value)
static BOOL MatchFontNames(PSHARED_FACE SharedFace, LPCWSTR lfFaceName)
Definition: freetype.c:5961
#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:5161
static FT_BitmapGlyph IntGetRealGlyph(IN OUT PFONT_CACHE_ENTRY Cache)
Definition: freetype.c:4999
static void SharedMem_Release(PSHARED_MEM Ptr)
Definition: freetype.c:650
#define VALIGN_MASK
BOOL FASTCALL IntLoadFontsInRegistry(VOID)
Definition: freetype.c:2384
BOOL FASTCALL IntIsFontRenderingEnabled(VOID)
Definition: freetype.c:2708
DWORD FASTCALL ftGdiGetFontData(PFONTGDI FontGdi, DWORD Table, DWORD Offset, PVOID Buffer, DWORD Size)
Definition: freetype.c:5446
#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:3368
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:2720
static BOOL IntGetTextDisposition(OUT LONGLONG *pX64, OUT LONGLONG *pY64, IN LPCWSTR String, IN INT Count, IN OPTIONAL LPINT Dx, IN OUT PFONT_CACHE_ENTRY Cache, IN UINT fuOptions, IN BOOL bNoTransform, IN OUT PFONTLINK_CHAIN pChain)
Definition: freetype.c:6673
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:3149
static __inline void FASTCALL IntFreeFontNames(FONT_NAMES *Names)
Definition: freetype.c:3136
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 NtGdiExtTextOutW(IN HDC hDC, IN INT XStart, IN INT YStart, IN UINT fuOptions, IN OPTIONAL LPCRECT UnsafeRect, IN LPCWSTR UnsafeString, IN UINT Count, IN OPTIONAL const INT *UnsafeDx, IN DWORD dwCodePage)
Definition: freetype.c:7429
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:6794
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:3310
struct _FONTLINK_CACHE * PFONTLINK_CACHE
static VOID FASTCALL CleanupFontEntryEx(PFONT_ENTRY FontEntry, PFONTGDI FontGDI)
Definition: freetype.c:702
BOOL WINAPI PathIsRelativeW(LPCWSTR lpszPath)
Definition: freetype.c:2374
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 _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
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
#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
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
#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:4452
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:4625
#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
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
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:3071
UNICODE_STRING FamilyNameW
Definition: freetype.c:3068
UNICODE_STRING FaceNameW
Definition: freetype.c:3069
ULONG OtmSize
Definition: freetype.c:3072
UNICODE_STRING StyleNameW
Definition: freetype.c:3070
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
unsigned char * LPBYTE
Definition: typedefs.h:53
uint16_t * LPWORD
Definition: typedefs.h:56
int32_t * LPLONG
Definition: typedefs.h:58
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
#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
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(HFONT hFont)
Definition: font.c:422
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:154
FORCEINLINE VOID TEXTOBJ_UnlockText(PLFONT plfnt)
Definition: text.h:96
#define IntUnLockProcessPrivateFonts(W32Process)
Definition: text.h:157
#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
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