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