ReactOS 0.4.15-dev-7788-g1ad9096
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-2019 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
38/* TPMF_FIXED_PITCH is confusing; brain-dead api */
39#ifndef _TMPF_VARIABLE_PITCH
40 #define _TMPF_VARIABLE_PITCH TMPF_FIXED_PITCH
41#endif
42
43/* Is bold emulation necessary? */
44#define EMUBOLD_NEEDED(original, request) \
45 (((request) != FW_DONTCARE) && ((request) - (original) >= FW_BOLD - FW_MEDIUM))
46
48extern const MATRIX gmxWorldToPageDefault;
49static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
50static POINTL PointZero = { 0, 0 };
51
52/* HACK!! Fix XFORMOBJ then use 1:16 / 16:1 */
53#define gmxWorldToDeviceDefault gmxWorldToPageDefault
54
56
57/* registry */
59 RTL_CONSTANT_STRING(L"\\REGISTRY\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts");
60
61
62/* The FreeType library is not thread safe, so we have
63 to serialize access to it */
65
69
70#define IntLockGlobalFonts() \
71 ExEnterCriticalRegionAndAcquireFastMutexUnsafe(g_FontListLock)
72
73#define IntUnLockGlobalFonts() \
74 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(g_FontListLock)
75
76#define ASSERT_GLOBALFONTS_LOCK_HELD() \
77 ASSERT(g_FontListLock->Owner == KeGetCurrentThread())
78
79#define IntLockFreeType() \
80 ExEnterCriticalRegionAndAcquireFastMutexUnsafe(g_FreeTypeLock)
81
82#define IntUnLockFreeType() \
83 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(g_FreeTypeLock)
84
85#define ASSERT_FREETYPE_LOCK_HELD() \
86 ASSERT(g_FreeTypeLock->Owner == KeGetCurrentThread())
87
88#define ASSERT_FREETYPE_LOCK_NOT_HELD() \
89 ASSERT(g_FreeTypeLock->Owner != KeGetCurrentThread())
90
91#define MAX_FONT_CACHE 256
92
95
96static PWCHAR g_ElfScripts[32] = /* These are in the order of the fsCsb[0] bits */
97{
98 L"Western", /* 00 */
99 L"Central_European",
100 L"Cyrillic",
101 L"Greek",
102 L"Turkish",
103 L"Hebrew",
104 L"Arabic",
105 L"Baltic",
106 L"Vietnamese", /* 08 */
107 NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 15 */
108 L"Thai",
109 L"Japanese",
110 L"CHINESE_GB2312",
111 L"Hangul",
112 L"CHINESE_BIG5",
113 L"Hangul(Johab)",
114 NULL, NULL, /* 23 */
116 L"Symbol" /* 31 */
117};
118
119/*
120 * For TranslateCharsetInfo
121 */
122#define CP_SYMBOL 42
123#define MAXTCIINDEX 32
125{
126 /* ANSI */
127 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
128 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
129 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
130 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
131 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
132 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
133 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
134 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
135 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
136 /* reserved by ANSI */
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
142 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
144 /* ANSI and OEM */
145 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
146 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
147 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
148 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
149 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
150 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
151 /* Reserved for alternate ANSI and OEM */
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 /* Reserved for system */
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
163};
164
165#ifndef CP_OEMCP
166 #define CP_OEMCP 1
167 #define CP_MACCP 2
168#endif
169
170/* Get charset from specified codepage.
171 g_FontTci is used also in TranslateCharsetInfo. */
173{
174 UINT i;
175
176 if (uCodePage == CP_OEMCP)
177 return OEM_CHARSET;
178
179 if (uCodePage == CP_MACCP)
180 return MAC_CHARSET;
181
182 for (i = 0; i < MAXTCIINDEX; ++i)
183 {
184 if (g_FontTci[i].ciACP == 0)
185 continue;
186
187 if (g_FontTci[i].ciACP == uCodePage)
188 return g_FontTci[i].ciCharset;
189 }
190
191 return DEFAULT_CHARSET;
192}
193
194/* list head */
195static RTL_STATIC_LIST_HEAD(g_FontSubstListHead);
196
197static void
199{
201
202 ++Ptr->RefCount;
203}
204
205static void
207{
208 Cache->OutlineRequiredSize = 0;
209 RtlInitUnicodeString(&Cache->FontFamily, NULL);
210 RtlInitUnicodeString(&Cache->FullName, NULL);
211}
212
213static PSHARED_FACE
215{
218 if (Ptr)
219 {
220 Ptr->Face = Face;
221 Ptr->RefCount = 1;
222 Ptr->Memory = Memory;
223 SharedFaceCache_Init(&Ptr->EnglishUS);
224 SharedFaceCache_Init(&Ptr->UserLanguage);
225
227 DPRINT("Creating SharedFace for %s\n", Face->family_name ? Face->family_name : "<NULL>");
228 }
229 return Ptr;
230}
231
232static PSHARED_MEM
234{
237 if (Ptr)
238 {
239 Ptr->Buffer = Buffer;
240 Ptr->BufferSize = BufferSize;
241 Ptr->RefCount = 1;
242 Ptr->IsMapping = IsMapping;
243 DPRINT("Creating SharedMem for %p (%i, %p)\n", Buffer, IsMapping, Ptr);
244 }
245 return Ptr;
246}
247
248static void
250{
252
253 ++Ptr->RefCount;
254}
255
256static void
258{
260
261 FT_Done_Glyph((FT_Glyph)Entry->BitmapGlyph);
262 RemoveEntryList(&Entry->ListEntry);
266}
267
268static void
270{
271 PLIST_ENTRY CurrentEntry, NextEntry;
272 PFONT_CACHE_ENTRY FontEntry;
273
275
276 for (CurrentEntry = g_FontCacheListHead.Flink;
277 CurrentEntry != &g_FontCacheListHead;
278 CurrentEntry = NextEntry)
279 {
280 FontEntry = CONTAINING_RECORD(CurrentEntry, FONT_CACHE_ENTRY, ListEntry);
281 NextEntry = CurrentEntry->Flink;
282
283 if (FontEntry->Hashed.Face == Face)
284 {
285 RemoveCachedEntry(FontEntry);
286 }
287 }
288}
289
291{
293 ASSERT(Ptr->RefCount > 0);
294
295 if (Ptr->RefCount <= 0)
296 return;
297
298 --Ptr->RefCount;
299 if (Ptr->RefCount == 0)
300 {
301 DPRINT("Releasing SharedMem for %p (%i, %p)\n", Ptr->Buffer, Ptr->IsMapping, Ptr);
302 if (Ptr->IsMapping)
304 else
307 }
308}
309
310static void
312{
313 RtlFreeUnicodeString(&Cache->FontFamily);
314 RtlFreeUnicodeString(&Cache->FullName);
315}
316
317static void
319{
321 ASSERT(Ptr->RefCount > 0);
322
323 if (Ptr->RefCount <= 0)
324 return;
325
326 --Ptr->RefCount;
327 if (Ptr->RefCount == 0)
328 {
329 DPRINT("Releasing SharedFace for %s\n", Ptr->Face->family_name ? Ptr->Face->family_name : "<NULL>");
330 RemoveCacheEntries(Ptr->Face);
331 FT_Done_Face(Ptr->Face);
332 SharedMem_Release(Ptr->Memory);
333 SharedFaceCache_Release(&Ptr->EnglishUS);
334 SharedFaceCache_Release(&Ptr->UserLanguage);
336 }
338}
339
340
341static VOID FASTCALL
343{
344 // PFONTGDI FontGDI = FontEntry->Font;
345 PSHARED_FACE SharedFace = FontGDI->SharedFace;
346
347 if (FontGDI->Filename)
349
350 if (FontEntry->StyleName.Buffer)
351 RtlFreeUnicodeString(&FontEntry->StyleName);
352
353 if (FontEntry->FaceName.Buffer)
354 RtlFreeUnicodeString(&FontEntry->FaceName);
355
356 EngFreeMem(FontGDI);
357 SharedFace_Release(SharedFace);
358 ExFreePoolWithTag(FontEntry, TAG_FONT);
359}
360
361static __inline VOID FASTCALL
363{
364 CleanupFontEntryEx(FontEntry, FontEntry->Font);
365}
366
367
368static __inline void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
369{
370 pt->x.value = vec->x >> 6;
371 pt->x.fract = (vec->x & 0x3f) << 10;
372 pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
373 pt->y.value = vec->y >> 6;
374 pt->y.fract = (vec->y & 0x3f) << 10;
375 pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
376}
377
378/*
379 This function builds an FT_Fixed from a FIXED. It simply put f.value
380 in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed.
381*/
383{
384 return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract);
385}
386
387
388#if DBG
389VOID DumpFontEntry(PFONT_ENTRY FontEntry)
390{
391 const char *family_name;
392 const char *style_name;
393 FT_Face Face;
394 PFONTGDI FontGDI = FontEntry->Font;
395
396 if (!FontGDI)
397 {
398 DPRINT("FontGDI NULL\n");
399 return;
400 }
401
402 Face = (FontGDI->SharedFace ? FontGDI->SharedFace->Face : NULL);
403 if (Face)
404 {
405 family_name = Face->family_name;
406 style_name = Face->style_name;
407 }
408 else
409 {
410 family_name = "<invalid>";
411 style_name = "<invalid>";
412 }
413
414 DPRINT("family_name '%s', style_name '%s', FaceName '%wZ', StyleName '%wZ', FontGDI %p, "
415 "FontObj %p, iUnique %lu, SharedFace %p, Face %p, CharSet %u, Filename '%S'\n",
417 style_name,
418 &FontEntry->FaceName,
419 &FontEntry->StyleName,
420 FontGDI,
421 &FontGDI->FontObj,
422 FontGDI->iUnique,
423 FontGDI->SharedFace,
424 Face,
425 FontGDI->CharSet,
426 FontGDI->Filename);
427}
428
429VOID DumpFontList(PLIST_ENTRY Head)
430{
432 PFONT_ENTRY CurrentEntry;
433
434 DPRINT("## DumpFontList(%p)\n", Head);
435
436 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
437 {
438 CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
439 DumpFontEntry(CurrentEntry);
440 }
441}
442
443VOID DumpFontSubstEntry(PFONTSUBST_ENTRY pSubstEntry)
444{
445 DPRINT("%wZ,%u -> %wZ,%u\n",
446 &pSubstEntry->FontNames[FONTSUBST_FROM],
447 pSubstEntry->CharSets[FONTSUBST_FROM],
448 &pSubstEntry->FontNames[FONTSUBST_TO],
449 pSubstEntry->CharSets[FONTSUBST_TO]);
450}
451
452VOID DumpFontSubstList(VOID)
453{
454 PLIST_ENTRY pHead = &g_FontSubstListHead;
455 PLIST_ENTRY pListEntry;
456 PFONTSUBST_ENTRY pSubstEntry;
457
458 DPRINT("## DumpFontSubstList\n");
459
460 for (pListEntry = pHead->Flink;
461 pListEntry != pHead;
462 pListEntry = pListEntry->Flink)
463 {
464 pSubstEntry =
465 (PFONTSUBST_ENTRY)CONTAINING_RECORD(pListEntry, FONT_ENTRY, ListEntry);
466
467 DumpFontSubstEntry(pSubstEntry);
468 }
469}
470
471VOID DumpPrivateFontList(BOOL bDoLock)
472{
474
475 if (!Win32Process)
476 return;
477
478 if (bDoLock)
479 IntLockProcessPrivateFonts(Win32Process);
480
481 DumpFontList(&Win32Process->PrivateFontListHead);
482
483 if (bDoLock)
484 IntUnLockProcessPrivateFonts(Win32Process);
485}
486
487VOID DumpGlobalFontList(BOOL bDoLock)
488{
489 if (bDoLock)
491
492 DumpFontList(&g_FontListHead);
493
494 if (bDoLock)
496}
497
498VOID DumpFontInfo(BOOL bDoLock)
499{
500 DumpGlobalFontList(bDoLock);
501 DumpPrivateFontList(bDoLock);
502 DumpFontSubstList();
503}
504#endif
505
506/*
507 * IntLoadFontSubstList --- loads the list of font substitutes
508 */
511{
515 KEY_FULL_INFORMATION KeyFullInfo;
516 ULONG i, Length;
517 UNICODE_STRING FromW, ToW;
518 BYTE InfoBuffer[128];
520 BYTE CharSets[FONTSUBST_FROM_AND_TO];
521 LPWSTR pch;
523
524 /* the FontSubstitutes registry key */
525 static UNICODE_STRING FontSubstKey =
526 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\"
527 L"Microsoft\\Windows NT\\CurrentVersion\\"
528 L"FontSubstitutes");
529
530 /* open registry key */
533 NULL, NULL);
534 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
535 if (!NT_SUCCESS(Status))
536 {
537 DPRINT("ZwOpenKey failed: 0x%08X\n", Status);
538 return FALSE; /* failure */
539 }
540
541 /* query count of values */
542 Status = ZwQueryKey(KeyHandle, KeyFullInformation,
543 &KeyFullInfo, sizeof(KeyFullInfo), &Length);
544 if (!NT_SUCCESS(Status))
545 {
546 DPRINT("ZwQueryKey failed: 0x%08X\n", Status);
548 return FALSE; /* failure */
549 }
550
551 /* for each value */
552 for (i = 0; i < KeyFullInfo.Values; ++i)
553 {
554 /* get value name */
555 Status = ZwEnumerateValueKey(KeyHandle, i, KeyValueFullInformation,
556 InfoBuffer, sizeof(InfoBuffer), &Length);
557 if (!NT_SUCCESS(Status))
558 {
559 DPRINT("ZwEnumerateValueKey failed: 0x%08X\n", Status);
560 break; /* failure */
561 }
562
563 /* create FromW string */
564 pInfo = (PKEY_VALUE_FULL_INFORMATION)InfoBuffer;
565 Length = pInfo->NameLength / sizeof(WCHAR);
566 pInfo->Name[Length] = UNICODE_NULL; /* truncate */
567 if (!RtlCreateUnicodeString(&FromW, pInfo->Name))
568 {
570 DPRINT("RtlCreateUnicodeString failed\n");
571 break; /* failure */
572 }
573
574 /* query value */
575 Status = ZwQueryValueKey(KeyHandle, &FromW, KeyValueFullInformation,
576 InfoBuffer, sizeof(InfoBuffer), &Length);
577 pInfo = (PKEY_VALUE_FULL_INFORMATION)InfoBuffer;
578 if (!NT_SUCCESS(Status) || !pInfo->DataLength)
579 {
580 DPRINT("ZwQueryValueKey failed: 0x%08X\n", Status);
581 RtlFreeUnicodeString(&FromW);
582 break; /* failure */
583 }
584
585 /* create ToW string */
586 pch = (LPWSTR)((PUCHAR)pInfo + pInfo->DataOffset);
587 Length = pInfo->DataLength / sizeof(WCHAR);
588 pch[Length] = UNICODE_NULL; /* truncate */
589 if (!RtlCreateUnicodeString(&ToW, pch))
590 {
592 DPRINT("RtlCreateUnicodeString failed\n");
593 RtlFreeUnicodeString(&FromW);
594 break; /* failure */
595 }
596
597 /* does charset exist? (from) */
599 pch = wcsrchr(FromW.Buffer, L',');
600 if (pch)
601 {
602 /* truncate */
603 *pch = UNICODE_NULL;
604 FromW.Length = (pch - FromW.Buffer) * sizeof(WCHAR);
605 /* parse charset number */
606 CharSets[FONTSUBST_FROM] = (BYTE)_wtoi(pch + 1);
607 }
608
609 /* does charset exist? (to) */
610 CharSets[FONTSUBST_TO] = DEFAULT_CHARSET;
611 pch = wcsrchr(ToW.Buffer, L',');
612 if (pch)
613 {
614 /* truncate */
615 *pch = UNICODE_NULL;
616 ToW.Length = (pch - ToW.Buffer) * sizeof(WCHAR);
617 /* parse charset number */
618 CharSets[FONTSUBST_TO] = (BYTE)_wtoi(pch + 1);
619 }
620
621 /* is it identical? */
622 if (RtlEqualUnicodeString(&FromW, &ToW, TRUE) &&
623 CharSets[FONTSUBST_FROM] == CharSets[FONTSUBST_TO])
624 {
625 RtlFreeUnicodeString(&FromW);
627 continue;
628 }
629
630 /* allocate an entry */
632 if (pEntry == NULL)
633 {
634 DPRINT("ExAllocatePoolWithTag failed\n");
635 RtlFreeUnicodeString(&FromW);
637 break; /* failure */
638 }
639
640 /* store to *pEntry */
641 pEntry->FontNames[FONTSUBST_FROM] = FromW;
642 pEntry->FontNames[FONTSUBST_TO] = ToW;
643 pEntry->CharSets[FONTSUBST_FROM] = CharSets[FONTSUBST_FROM];
644 pEntry->CharSets[FONTSUBST_TO] = CharSets[FONTSUBST_TO];
645
646 /* insert pEntry to *pHead */
647 InsertTailList(pHead, &pEntry->ListEntry);
648 }
649
650 /* close now */
652
653 return NT_SUCCESS(Status);
654}
655
658{
659 ULONG ulError;
660
664 /* Fast Mutexes must be allocated from non paged pool */
666 if (g_FontListLock == NULL)
667 {
668 return FALSE;
669 }
670
673 if (g_FreeTypeLock == NULL)
674 {
675 return FALSE;
676 }
678
680 if (ulError)
681 {
682 DPRINT1("FT_Init_FreeType failed with error code 0x%x\n", ulError);
683 return FALSE;
684 }
685
687 {
688 DPRINT1("Fonts registry is empty.\n");
689
690 /* Load font(s) with writing registry */
692 }
693
694 IntLoadFontSubstList(&g_FontSubstListHead);
695
696#if DBG
697 DumpFontInfo(TRUE);
698#endif
699
700 return TRUE;
701}
702
703static LONG IntNormalizeAngle(LONG nTenthsOfDegrees)
704{
705 nTenthsOfDegrees %= 360 * 10;
706 if (nTenthsOfDegrees >= 0)
707 return nTenthsOfDegrees;
708 return nTenthsOfDegrees + 360 * 10;
709}
710
711static VOID FASTCALL IntEscapeMatrix(FT_Matrix *pmat, LONG lfEscapement)
712{
713 FT_Vector vecAngle;
714 /* Convert the angle in tenths of degrees into degrees as a 16.16 fixed-point value */
715 FT_Angle angle = INT_TO_FIXED(lfEscapement) / 10;
716 FT_Vector_Unit(&vecAngle, angle);
717 pmat->xx = vecAngle.x;
718 pmat->xy = -vecAngle.y;
719 pmat->yx = -pmat->xy;
720 pmat->yy = pmat->xx;
721}
722
723static VOID FASTCALL
725{
726 FLOATOBJ ef;
727
728 /* Create a freetype matrix, by converting to 16.16 fixpoint format */
729 ef = pmx->efM11;
730 FLOATOBJ_MulLong(&ef, 0x00010000);
731 pmat->xx = FLOATOBJ_GetLong(&ef);
732
733 ef = pmx->efM21;
734 FLOATOBJ_MulLong(&ef, 0x00010000);
735 pmat->xy = -FLOATOBJ_GetLong(&ef); /* (*1) See below */
736
737 ef = pmx->efM12;
738 FLOATOBJ_MulLong(&ef, 0x00010000);
739 pmat->yx = -FLOATOBJ_GetLong(&ef); /* (*1) See below */
740
741 ef = pmx->efM22;
742 FLOATOBJ_MulLong(&ef, 0x00010000);
743 pmat->yy = FLOATOBJ_GetLong(&ef);
744
745 // (*1): Y direction is mirrored as follows:
746 //
747 // [ M11 -M12 ] [ X ] [ M11*X + M12*Y ]
748 // [ ] * [ ] == [ ]
749 // [ -M21 M22 ] [ -Y ] [ -(M21*X + M22*Y) ].
750}
751
752static BOOL
754 PUNICODE_STRING pOutputName,
755 PUNICODE_STRING pInputName,
756 BYTE RequestedCharSet,
757 BYTE CharSetMap[FONTSUBST_FROM_AND_TO])
758{
759 PLIST_ENTRY pListEntry;
760 PFONTSUBST_ENTRY pSubstEntry;
761 BYTE CharSets[FONTSUBST_FROM_AND_TO];
762
763 CharSetMap[FONTSUBST_FROM] = DEFAULT_CHARSET;
764 CharSetMap[FONTSUBST_TO] = RequestedCharSet;
765
766 /* for each list entry */
767 for (pListEntry = pHead->Flink;
768 pListEntry != pHead;
769 pListEntry = pListEntry->Flink)
770 {
771 pSubstEntry =
772 (PFONTSUBST_ENTRY)CONTAINING_RECORD(pListEntry, FONT_ENTRY, ListEntry);
773
774 CharSets[FONTSUBST_FROM] = pSubstEntry->CharSets[FONTSUBST_FROM];
775
776 if (CharSets[FONTSUBST_FROM] != DEFAULT_CHARSET &&
777 CharSets[FONTSUBST_FROM] != RequestedCharSet)
778 {
779 continue; /* not matched */
780 }
781
782 /* does charset number exist? (to) */
783 if (pSubstEntry->CharSets[FONTSUBST_TO] != DEFAULT_CHARSET)
784 {
785 CharSets[FONTSUBST_TO] = pSubstEntry->CharSets[FONTSUBST_TO];
786 }
787 else
788 {
789 CharSets[FONTSUBST_TO] = RequestedCharSet;
790 }
791
792 /* does font name match? */
794 pInputName, TRUE))
795 {
796 continue; /* not matched */
797 }
798
799 /* update *pOutputName */
800 *pOutputName = pSubstEntry->FontNames[FONTSUBST_TO];
801
802 if (CharSetMap[FONTSUBST_FROM] == DEFAULT_CHARSET)
803 {
804 /* update CharSetMap */
805 CharSetMap[FONTSUBST_FROM] = CharSets[FONTSUBST_FROM];
806 CharSetMap[FONTSUBST_TO] = CharSets[FONTSUBST_TO];
807 }
808 return TRUE; /* success */
809 }
810
811 return FALSE;
812}
813
814static VOID
816{
817 SIZE_T cbLength = pString->Length;
818
819 if (cbBuffer < sizeof(UNICODE_NULL))
820 return;
821
822 if (cbLength > cbBuffer - sizeof(UNICODE_NULL))
823 cbLength = cbBuffer - sizeof(UNICODE_NULL);
824
825 RtlCopyMemory(pszBuffer, pString->Buffer, cbLength);
826 pszBuffer[cbLength / sizeof(WCHAR)] = UNICODE_NULL;
827}
828
829static NTSTATUS
831{
833 UNICODE_STRING Tmp;
834
835 Tmp.Buffer = ExAllocatePoolWithTag(PagedPool, Source->MaximumLength, TAG_USTR);
836 if (Tmp.Buffer)
837 {
838 Tmp.MaximumLength = Source->MaximumLength;
839 Tmp.Length = 0;
841
845
847 }
848
849 return Status;
850}
851
852static BOOL
854{
855 UINT RecurseCount = 5;
856 UNICODE_STRING OutputNameW = { 0 };
857 BYTE CharSetMap[FONTSUBST_FROM_AND_TO];
858 BOOL Found;
859 UNICODE_STRING InputNameW;
860
861 if (pLogFont->lfFaceName[0] == UNICODE_NULL)
862 return FALSE;
863
864 RtlInitUnicodeString(&InputNameW, pLogFont->lfFaceName);
865
866 while (RecurseCount-- > 0)
867 {
868 Found = SubstituteFontByList(&g_FontSubstListHead,
869 &OutputNameW, &InputNameW,
870 pLogFont->lfCharSet, CharSetMap);
871 if (!Found)
872 break;
873
874 IntUnicodeStringToBuffer(pLogFont->lfFaceName, sizeof(pLogFont->lfFaceName), &OutputNameW);
875
876 if (CharSetMap[FONTSUBST_FROM] == DEFAULT_CHARSET ||
877 CharSetMap[FONTSUBST_FROM] == pLogFont->lfCharSet)
878 {
879 pLogFont->lfCharSet = CharSetMap[FONTSUBST_TO];
880 }
881 }
882
883 return TRUE; /* success */
884}
885
886/*
887 * IntLoadSystemFonts
888 *
889 * Search the system font directory and adds each font found.
890 */
893{
895 UNICODE_STRING Directory, FileName, TempString;
897 HANDLE hDirectory;
898 BYTE *DirInfoBuffer;
900 BOOLEAN bRestartScan = TRUE;
902 INT i;
903 static UNICODE_STRING SearchPatterns[] =
904 {
905 RTL_CONSTANT_STRING(L"*.ttf"),
906 RTL_CONSTANT_STRING(L"*.ttc"),
907 RTL_CONSTANT_STRING(L"*.otf"),
908 RTL_CONSTANT_STRING(L"*.otc"),
909 RTL_CONSTANT_STRING(L"*.fon"),
910 RTL_CONSTANT_STRING(L"*.fnt")
911 };
912 static UNICODE_STRING IgnoreFiles[] =
913 {
916 };
917
918 RtlInitUnicodeString(&Directory, L"\\SystemRoot\\Fonts\\");
919
922 &Directory,
924 NULL,
925 NULL);
926
928 &hDirectory,
931 &Iosb,
934
935 if (NT_SUCCESS(Status))
936 {
937 for (i = 0; i < _countof(SearchPatterns); ++i)
938 {
939 DirInfoBuffer = ExAllocatePoolWithTag(PagedPool, 0x4000, TAG_FONT);
940 if (DirInfoBuffer == NULL)
941 {
942 ZwClose(hDirectory);
943 return;
944 }
945
947 if (FileName.Buffer == NULL)
948 {
949 ExFreePoolWithTag(DirInfoBuffer, TAG_FONT);
950 ZwClose(hDirectory);
951 return;
952 }
953 FileName.Length = 0;
954 FileName.MaximumLength = MAX_PATH * sizeof(WCHAR);
955
956 while (1)
957 {
958 Status = ZwQueryDirectoryFile(
959 hDirectory,
960 NULL,
961 NULL,
962 NULL,
963 &Iosb,
964 DirInfoBuffer,
965 0x4000,
967 FALSE,
968 &SearchPatterns[i],
969 bRestartScan);
970
972 {
973 break;
974 }
975
976 DirInfo = (PFILE_DIRECTORY_INFORMATION)DirInfoBuffer;
977 while (1)
978 {
979 SIZE_T ign;
980
981 TempString.Buffer = DirInfo->FileName;
982 TempString.Length = TempString.MaximumLength = DirInfo->FileNameLength;
983
984 /* Should we ignore this file? */
985 for (ign = 0; ign < _countof(IgnoreFiles); ++ign)
986 {
987 /* Yes.. */
988 if (RtlEqualUnicodeString(IgnoreFiles + ign, &TempString, FALSE))
989 break;
990 }
991
992 /* If we tried all Ignore patterns and there was no match, try to create a font */
993 if (ign == _countof(IgnoreFiles))
994 {
998 {
999 DPRINT1("ERR: Failed to load %wZ\n", &FileName);
1000 }
1001 }
1002
1003 if (DirInfo->NextEntryOffset == 0)
1004 break;
1005
1006 DirInfo = (PFILE_DIRECTORY_INFORMATION)((ULONG_PTR)DirInfo + DirInfo->NextEntryOffset);
1007 }
1008
1009 bRestartScan = FALSE;
1010 }
1011
1013 ExFreePoolWithTag(DirInfoBuffer, TAG_FONT);
1014 }
1015 ZwClose(hDirectory);
1016 }
1017}
1018
1019/* NOTE: If nIndex < 0 then return the number of charsets. */
1020UINT FASTCALL IntGetCharSet(INT nIndex, FT_ULong CodePageRange1)
1021{
1022 UINT BitIndex, CharSet;
1023 UINT nCount = 0;
1024
1025 if (CodePageRange1 == 0)
1026 {
1027 return (nIndex < 0) ? 1 : DEFAULT_CHARSET;
1028 }
1029
1030 for (BitIndex = 0; BitIndex < MAXTCIINDEX; ++BitIndex)
1031 {
1032 if (CodePageRange1 & (1 << BitIndex))
1033 {
1034 CharSet = g_FontTci[BitIndex].ciCharset;
1035 if ((nIndex >= 0) && (nCount == (UINT)nIndex))
1036 {
1037 return CharSet;
1038 }
1039 ++nCount;
1040 }
1041 }
1042
1043 return (nIndex < 0) ? nCount : ANSI_CHARSET;
1044}
1045
1046/* pixels to points */
1047#define PX2PT(pixels) FT_MulDiv((pixels), 72, 96)
1048
1049static INT FASTCALL
1051 PSHARED_FACE SharedFace, FT_Long FontIndex, INT CharSetIndex)
1052{
1055 FONT_ENTRY_MEM* PrivateEntry = NULL;
1056 FONTGDI * FontGDI;
1058 FT_Face Face;
1060 FT_WinFNT_HeaderRec WinFNT;
1061 INT FaceCount = 0, CharSetCount = 0;
1062 PUNICODE_STRING pFileName = pLoadFont->pFileName;
1063 DWORD Characteristics = pLoadFont->Characteristics;
1064 PUNICODE_STRING pValueName = &pLoadFont->RegValueName;
1065 TT_OS2 * pOS2;
1066 INT BitIndex;
1067 FT_UShort os2_version;
1068 FT_ULong os2_ulCodePageRange1;
1069 FT_UShort os2_usWeightClass;
1070
1071 if (SharedFace == NULL && CharSetIndex == -1)
1072 {
1073 /* load a face from memory */
1077 pLoadFont->Memory->Buffer,
1078 pLoadFont->Memory->BufferSize,
1079 ((FontIndex != -1) ? FontIndex : 0),
1080 &Face);
1081
1082 if (!Error)
1083 SharedFace = SharedFace_Create(Face, pLoadFont->Memory);
1084
1086
1087 if (!Error && FT_IS_SFNT(Face))
1088 pLoadFont->IsTrueType = TRUE;
1089
1090 if (Error || SharedFace == NULL)
1091 {
1092 if (SharedFace)
1093 SharedFace_Release(SharedFace);
1094
1095 if (Error == FT_Err_Unknown_File_Format)
1096 DPRINT1("Unknown font file format\n");
1097 else
1098 DPRINT1("Error reading font (error code: %d)\n", Error);
1099 return 0; /* failure */
1100 }
1101 }
1102 else
1103 {
1104 Face = SharedFace->Face;
1106 SharedFace_AddRef(SharedFace);
1108 }
1109
1110 /* allocate a FONT_ENTRY */
1112 if (!Entry)
1113 {
1114 SharedFace_Release(SharedFace);
1116 return 0; /* failure */
1117 }
1118
1119 /* allocate a FONTGDI */
1120 FontGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(FONTGDI), GDITAG_RFONT);
1121 if (!FontGDI)
1122 {
1123 SharedFace_Release(SharedFace);
1126 return 0; /* failure */
1127 }
1128
1129 /* set file name */
1130 if (pFileName)
1131 {
1133 pFileName->Length + sizeof(UNICODE_NULL),
1134 GDITAG_PFF);
1135 if (FontGDI->Filename == NULL)
1136 {
1137 EngFreeMem(FontGDI);
1138 SharedFace_Release(SharedFace);
1141 return 0; /* failure */
1142 }
1143
1144 RtlCopyMemory(FontGDI->Filename, pFileName->Buffer, pFileName->Length);
1145 FontGDI->Filename[pFileName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1146 }
1147 else
1148 {
1149 FontGDI->Filename = NULL;
1150
1151 PrivateEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY_MEM), TAG_FONT);
1152 if (!PrivateEntry)
1153 {
1154 if (FontGDI->Filename)
1156 EngFreeMem(FontGDI);
1157 SharedFace_Release(SharedFace);
1159 return 0;
1160 }
1161
1162 PrivateEntry->Entry = Entry;
1163 if (pLoadFont->PrivateEntry)
1164 {
1165 InsertTailList(&pLoadFont->PrivateEntry->ListEntry, &PrivateEntry->ListEntry);
1166 }
1167 else
1168 {
1169 InitializeListHead(&PrivateEntry->ListEntry);
1170 pLoadFont->PrivateEntry = PrivateEntry;
1171 }
1172 }
1173
1174 /* set face */
1175 FontGDI->SharedFace = SharedFace;
1176 FontGDI->CharSet = ANSI_CHARSET;
1177 FontGDI->OriginalItalic = FALSE;
1178 FontGDI->RequestItalic = FALSE;
1179 FontGDI->OriginalWeight = FALSE;
1180 FontGDI->RequestWeight = FW_NORMAL;
1181
1183 pOS2 = (TT_OS2 *)FT_Get_Sfnt_Table(Face, FT_SFNT_OS2);
1184 if (pOS2)
1185 {
1186 FontGDI->OriginalItalic = !!(pOS2->fsSelection & 0x1);
1187 FontGDI->OriginalWeight = pOS2->usWeightClass;
1188 }
1189 else
1190 {
1191 Error = FT_Get_WinFNT_Header(Face, &WinFNT);
1192 if (!Error)
1193 {
1194 FontGDI->OriginalItalic = !!WinFNT.italic;
1195 FontGDI->OriginalWeight = WinFNT.weight;
1196 }
1197 }
1199
1202 if (NT_SUCCESS(Status))
1203 {
1204 if (Face->style_name && Face->style_name[0] &&
1205 strcmp(Face->style_name, "Regular") != 0)
1206 {
1209 if (!NT_SUCCESS(Status))
1210 {
1211 RtlFreeUnicodeString(&Entry->FaceName);
1212 }
1213 }
1214 else
1215 {
1216 RtlInitUnicodeString(&Entry->StyleName, NULL);
1217 }
1218 }
1219 if (!NT_SUCCESS(Status))
1220 {
1221 if (PrivateEntry)
1222 {
1223 if (pLoadFont->PrivateEntry == PrivateEntry)
1224 {
1225 pLoadFont->PrivateEntry = NULL;
1226 }
1227 else
1228 {
1229 RemoveEntryList(&PrivateEntry->ListEntry);
1230 }
1231 ExFreePoolWithTag(PrivateEntry, TAG_FONT);
1232 }
1233 if (FontGDI->Filename)
1235 EngFreeMem(FontGDI);
1236 SharedFace_Release(SharedFace);
1238 return 0;
1239 }
1240
1241 os2_version = 0;
1243 pOS2 = (TT_OS2 *)FT_Get_Sfnt_Table(Face, FT_SFNT_OS2);
1244 if (pOS2)
1245 {
1246 os2_version = pOS2->version;
1247 os2_ulCodePageRange1 = pOS2->ulCodePageRange1;
1248 os2_usWeightClass = pOS2->usWeightClass;
1249 }
1251
1252 if (pOS2 && os2_version >= 1)
1253 {
1254 /* get charset and weight from OS/2 header */
1255
1256 /* Make sure we do not use this pointer anymore */
1257 pOS2 = NULL;
1258
1259 for (BitIndex = 0; BitIndex < MAXTCIINDEX; ++BitIndex)
1260 {
1261 if (os2_ulCodePageRange1 & (1 << BitIndex))
1262 {
1263 if (g_FontTci[BitIndex].ciCharset == DEFAULT_CHARSET)
1264 continue;
1265
1266 if ((CharSetIndex == -1 && CharSetCount == 0) ||
1267 CharSetIndex == CharSetCount)
1268 {
1269 FontGDI->CharSet = g_FontTci[BitIndex].ciCharset;
1270 }
1271
1272 ++CharSetCount;
1273 }
1274 }
1275
1276 /* set actual weight */
1277 FontGDI->OriginalWeight = os2_usWeightClass;
1278 }
1279 else
1280 {
1281 /* get charset from WinFNT header */
1283 Error = FT_Get_WinFNT_Header(Face, &WinFNT);
1284 if (!Error)
1285 {
1286 FontGDI->CharSet = WinFNT.charset;
1287 }
1289 }
1290
1291 ++FaceCount;
1292 DPRINT("Font loaded: %s (%s)\n",
1293 Face->family_name ? Face->family_name : "<NULL>",
1294 Face->style_name ? Face->style_name : "<NULL>");
1295 DPRINT("Num glyphs: %d\n", Face->num_glyphs);
1296 DPRINT("CharSet: %d\n", FontGDI->CharSet);
1297
1298 /* Add this font resource to the font table */
1299 Entry->Font = FontGDI;
1300 Entry->NotEnum = (Characteristics & FR_NOT_ENUM);
1301
1302 if (Characteristics & FR_PRIVATE)
1303 {
1304 /* private font */
1306 IntLockProcessPrivateFonts(Win32Process);
1307 InsertTailList(&Win32Process->PrivateFontListHead, &Entry->ListEntry);
1308 IntUnLockProcessPrivateFonts(Win32Process);
1309 }
1310 else
1311 {
1312 /* global font */
1314 InsertTailList(&g_FontListHead, &Entry->ListEntry);
1316 }
1317
1318 if (FontIndex == -1)
1319 {
1320 if (FT_IS_SFNT(Face))
1321 {
1322 TT_Face TrueType = (TT_Face)Face;
1323 if (TrueType->ttc_header.count > 1)
1324 {
1325 FT_Long i;
1326 for (i = 1; i < TrueType->ttc_header.count; ++i)
1327 {
1328 FaceCount += IntGdiLoadFontsFromMemory(pLoadFont, NULL, i, -1);
1329 }
1330 }
1331 }
1332 FontIndex = 0;
1333 }
1334
1335 if (CharSetIndex == -1)
1336 {
1337 INT i;
1338 USHORT NameLength = Entry->FaceName.Length;
1339
1340 if (Entry->StyleName.Length)
1341 NameLength += Entry->StyleName.Length + sizeof(WCHAR);
1342
1343 if (pLoadFont->RegValueName.Length == 0)
1344 {
1345 pValueName->Length = 0;
1346 pValueName->MaximumLength = NameLength + sizeof(WCHAR);
1348 pValueName->MaximumLength,
1349 TAG_USTR);
1350 pValueName->Buffer[0] = UNICODE_NULL;
1351 RtlAppendUnicodeStringToString(pValueName, &Entry->FaceName);
1352 }
1353 else
1354 {
1355 UNICODE_STRING NewString;
1356 USHORT Length = pValueName->Length + 3 * sizeof(WCHAR) + NameLength;
1357 NewString.Length = 0;
1358 NewString.MaximumLength = Length + sizeof(WCHAR);
1360 NewString.MaximumLength,
1361 TAG_USTR);
1362 NewString.Buffer[0] = UNICODE_NULL;
1363
1364 RtlAppendUnicodeStringToString(&NewString, pValueName);
1365 RtlAppendUnicodeToString(&NewString, L" & ");
1366 RtlAppendUnicodeStringToString(&NewString, &Entry->FaceName);
1367
1368 RtlFreeUnicodeString(pValueName);
1369 *pValueName = NewString;
1370 }
1371 if (Entry->StyleName.Length)
1372 {
1373 RtlAppendUnicodeToString(pValueName, L" ");
1374 RtlAppendUnicodeStringToString(pValueName, &Entry->StyleName);
1375 }
1376
1377 for (i = 1; i < CharSetCount; ++i)
1378 {
1379 /* Do not count charsets towards 'faces' loaded */
1380 IntGdiLoadFontsFromMemory(pLoadFont, SharedFace, FontIndex, i);
1381 }
1382 }
1383
1384 return FaceCount; /* number of loaded faces */
1385}
1386
1387static LPCWSTR FASTCALL
1389{
1390 switch (CharSet)
1391 {
1392 case ANSI_CHARSET: return L"ANSI";
1393 case DEFAULT_CHARSET: return L"Default";
1394 case SYMBOL_CHARSET: return L"Symbol";
1395 case SHIFTJIS_CHARSET: return L"Shift_JIS";
1396 case HANGUL_CHARSET: return L"Hangul";
1397 case GB2312_CHARSET: return L"GB 2312";
1398 case CHINESEBIG5_CHARSET: return L"Chinese Big5";
1399 case OEM_CHARSET: return L"OEM";
1400 case JOHAB_CHARSET: return L"Johab";
1401 case HEBREW_CHARSET: return L"Hebrew";
1402 case ARABIC_CHARSET: return L"Arabic";
1403 case GREEK_CHARSET: return L"Greek";
1404 case TURKISH_CHARSET: return L"Turkish";
1405 case VIETNAMESE_CHARSET: return L"Vietnamese";
1406 case THAI_CHARSET: return L"Thai";
1407 case EASTEUROPE_CHARSET: return L"Eastern European";
1408 case RUSSIAN_CHARSET: return L"Russian";
1409 case MAC_CHARSET: return L"Mac";
1410 case BALTIC_CHARSET: return L"Baltic";
1411 default: return L"Unknown";
1412 }
1413}
1414
1415/*
1416 * IntGdiAddFontResource
1417 *
1418 * Adds the font resource from the specified file to the system.
1419 */
1420
1423 DWORD dwFlags)
1424{
1427 PVOID Buffer = NULL;
1430 SIZE_T ViewSize = 0, Length;
1431 LARGE_INTEGER SectionSize;
1434 INT FontCount;
1436 UNICODE_STRING PathName;
1437 LPWSTR pszBuffer;
1439 static const UNICODE_STRING TrueTypePostfix = RTL_CONSTANT_STRING(L" (TrueType)");
1440 static const UNICODE_STRING DosPathPrefix = RTL_CONSTANT_STRING(L"\\??\\");
1441
1442 /* Build PathName */
1444 {
1445 Length = DosPathPrefix.Length + FileName->Length + sizeof(UNICODE_NULL);
1447 if (!pszBuffer)
1448 return 0; /* failure */
1449
1450 RtlInitEmptyUnicodeString(&PathName, pszBuffer, Length);
1451 RtlAppendUnicodeStringToString(&PathName, &DosPathPrefix);
1453 }
1454 else
1455 {
1457 if (!NT_SUCCESS(Status))
1458 return 0; /* failure */
1459 }
1460
1461 /* Open the font file */
1465 &FileHandle,
1468 &Iosb,
1471 if (!NT_SUCCESS(Status))
1472 {
1473 DPRINT1("Could not load font file: %wZ\n", &PathName);
1474 RtlFreeUnicodeString(&PathName);
1475 return 0;
1476 }
1477
1480 if (!NT_SUCCESS(Status))
1481 {
1482 DPRINT1("ObReferenceObjectByHandle failed.\n");
1484 RtlFreeUnicodeString(&PathName);
1485 return 0;
1486 }
1487
1488 SectionSize.QuadPart = 0LL;
1491 NULL, &SectionSize, PAGE_READONLY,
1493 if (!NT_SUCCESS(Status))
1494 {
1495 DPRINT1("Could not map file: %wZ\n", &PathName);
1498 RtlFreeUnicodeString(&PathName);
1499 return 0;
1500 }
1502
1504 if (!NT_SUCCESS(Status))
1505 {
1506 DPRINT1("Could not map file: %wZ\n", &PathName);
1509 RtlFreeUnicodeString(&PathName);
1510 return 0;
1511 }
1512
1513 LoadFont.pFileName = &PathName;
1515 LoadFont.Characteristics = Characteristics;
1516 RtlInitUnicodeString(&LoadFont.RegValueName, NULL);
1517 LoadFont.IsTrueType = FALSE;
1518 LoadFont.CharSet = DEFAULT_CHARSET;
1519 LoadFont.PrivateEntry = NULL;
1520 FontCount = IntGdiLoadFontsFromMemory(&LoadFont, NULL, -1, -1);
1521
1522 /* Release our copy */
1526
1528
1530
1531 /* Save the loaded font name into the registry */
1532 if (FontCount > 0 && (dwFlags & AFRX_WRITE_REGISTRY))
1533 {
1534 UNICODE_STRING NewString;
1535 SIZE_T Length;
1536 PWCHAR pszBuffer;
1537 LPCWSTR CharSetName;
1538 if (LoadFont.IsTrueType)
1539 {
1540 /* Append " (TrueType)" */
1541 Length = LoadFont.RegValueName.Length + TrueTypePostfix.Length + sizeof(UNICODE_NULL);
1543 if (pszBuffer)
1544 {
1545 RtlInitEmptyUnicodeString(&NewString, pszBuffer, Length);
1546 NewString.Buffer[0] = UNICODE_NULL;
1547 RtlAppendUnicodeStringToString(&NewString, &LoadFont.RegValueName);
1548 RtlAppendUnicodeStringToString(&NewString, &TrueTypePostfix);
1549 RtlFreeUnicodeString(&LoadFont.RegValueName);
1550 LoadFont.RegValueName = NewString;
1551 }
1552 else
1553 {
1554 // FIXME!
1555 }
1556 }
1557 else if (LoadFont.CharSet != DEFAULT_CHARSET)
1558 {
1559 /* Append " (CharSetName)" */
1560 CharSetName = NameFromCharSet(LoadFont.CharSet);
1561 Length = LoadFont.RegValueName.Length +
1562 (wcslen(CharSetName) + 3) * sizeof(WCHAR) +
1563 sizeof(UNICODE_NULL);
1564
1566 if (pszBuffer)
1567 {
1568 RtlInitEmptyUnicodeString(&NewString, pszBuffer, Length);
1569 NewString.Buffer[0] = UNICODE_NULL;
1570 RtlAppendUnicodeStringToString(&NewString, &LoadFont.RegValueName);
1571 RtlAppendUnicodeToString(&NewString, L" (");
1572 RtlAppendUnicodeToString(&NewString, CharSetName);
1573 RtlAppendUnicodeToString(&NewString, L")");
1574 RtlFreeUnicodeString(&LoadFont.RegValueName);
1575 LoadFont.RegValueName = NewString;
1576 }
1577 else
1578 {
1579 // FIXME!
1580 }
1581 }
1582
1585 NULL, NULL);
1586 Status = ZwOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes);
1587 if (NT_SUCCESS(Status))
1588 {
1590 LPWSTR pFileName;
1591
1593 {
1594 pFileName = PathName.Buffer;
1595 }
1596 else
1597 {
1598 pFileName = wcsrchr(PathName.Buffer, L'\\');
1599 }
1600
1601 if (pFileName)
1602 {
1604 {
1605 pFileName++;
1606 }
1607 DataSize = (wcslen(pFileName) + 1) * sizeof(WCHAR);
1608 ZwSetValueKey(KeyHandle, &LoadFont.RegValueName, 0, REG_SZ,
1609 pFileName, DataSize);
1610 }
1612 }
1613 }
1614 RtlFreeUnicodeString(&LoadFont.RegValueName);
1615
1616 RtlFreeUnicodeString(&PathName);
1617 return FontCount;
1618}
1619
1622{
1623 return IntGdiAddFontResourceEx(FileName, Characteristics, 0);
1624}
1625
1626/* Borrowed from shlwapi!PathIsRelativeW */
1628{
1629 if (!lpszPath || !*lpszPath)
1630 return TRUE;
1631 if (*lpszPath == L'\\' || (*lpszPath && lpszPath[1] == L':'))
1632 return FALSE;
1633 return TRUE;
1634}
1635
1638{
1642 KEY_FULL_INFORMATION KeyFullInfo;
1643 ULONG i, Length;
1644 UNICODE_STRING FontTitleW, FileNameW;
1645 SIZE_T InfoSize;
1646 LPBYTE InfoBuffer;
1648 LPWSTR pchPath;
1650 INT nFontCount = 0;
1651 DWORD dwFlags;
1652
1653 /* open registry key */
1656 NULL, NULL);
1657 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
1658 if (!NT_SUCCESS(Status))
1659 {
1660 DPRINT1("ZwOpenKey failed: 0x%08X\n", Status);
1661 return FALSE; /* failure */
1662 }
1663
1664 /* query count of values */
1665 Status = ZwQueryKey(KeyHandle, KeyFullInformation,
1666 &KeyFullInfo, sizeof(KeyFullInfo), &Length);
1667 if (!NT_SUCCESS(Status))
1668 {
1669 DPRINT1("ZwQueryKey failed: 0x%08X\n", Status);
1671 return FALSE; /* failure */
1672 }
1673
1674 /* allocate buffer */
1675 InfoSize = (MAX_PATH + 256) * sizeof(WCHAR);
1676 InfoBuffer = ExAllocatePoolWithTag(PagedPool, InfoSize, TAG_FONT);
1677 if (!InfoBuffer)
1678 {
1679 DPRINT1("ExAllocatePoolWithTag failed\n");
1681 return FALSE;
1682 }
1683
1684 /* for each value */
1685 for (i = 0; i < KeyFullInfo.Values; ++i)
1686 {
1687 /* get value name */
1688 Status = ZwEnumerateValueKey(KeyHandle, i, KeyValueFullInformation,
1689 InfoBuffer, InfoSize, &Length);
1691 {
1692 /* too short buffer */
1693 ExFreePoolWithTag(InfoBuffer, TAG_FONT);
1694 InfoSize *= 2;
1695 InfoBuffer = ExAllocatePoolWithTag(PagedPool, InfoSize, TAG_FONT);
1696 if (!InfoBuffer)
1697 {
1698 DPRINT1("ExAllocatePoolWithTag failed\n");
1699 break;
1700 }
1701 /* try again */
1702 Status = ZwEnumerateValueKey(KeyHandle, i, KeyValueFullInformation,
1703 InfoBuffer, InfoSize, &Length);
1704 }
1705 if (!NT_SUCCESS(Status))
1706 {
1707 DPRINT1("ZwEnumerateValueKey failed: 0x%08X\n", Status);
1708 break; /* failure */
1709 }
1710
1711 /* create FontTitleW string */
1712 pInfo = (PKEY_VALUE_FULL_INFORMATION)InfoBuffer;
1713 Length = pInfo->NameLength / sizeof(WCHAR);
1714 pInfo->Name[Length] = UNICODE_NULL; /* truncate */
1715 if (!RtlCreateUnicodeString(&FontTitleW, pInfo->Name))
1716 {
1718 DPRINT1("RtlCreateUnicodeString failed\n");
1719 break; /* failure */
1720 }
1721
1722 /* query value */
1723 Status = ZwQueryValueKey(KeyHandle, &FontTitleW, KeyValueFullInformation,
1724 InfoBuffer, InfoSize, &Length);
1726 {
1727 /* too short buffer */
1728 ExFreePoolWithTag(InfoBuffer, TAG_FONT);
1729 InfoSize *= 2;
1730 InfoBuffer = ExAllocatePoolWithTag(PagedPool, InfoSize, TAG_FONT);
1731 if (!InfoBuffer)
1732 {
1733 DPRINT1("ExAllocatePoolWithTag failed\n");
1734 break;
1735 }
1736 /* try again */
1737 Status = ZwQueryValueKey(KeyHandle, &FontTitleW, KeyValueFullInformation,
1738 InfoBuffer, InfoSize, &Length);
1739 }
1740 pInfo = (PKEY_VALUE_FULL_INFORMATION)InfoBuffer;
1741 if (!NT_SUCCESS(Status) || !pInfo->DataLength)
1742 {
1743 DPRINT1("ZwQueryValueKey failed: 0x%08X\n", Status);
1744 RtlFreeUnicodeString(&FontTitleW);
1745 break; /* failure */
1746 }
1747
1748 /* Build pchPath */
1749 pchPath = (LPWSTR)((PUCHAR)pInfo + pInfo->DataOffset);
1750 Length = pInfo->DataLength / sizeof(WCHAR);
1751 pchPath[Length] = UNICODE_NULL; /* truncate */
1752
1753 /* Load font(s) without writing registry */
1754 if (PathIsRelativeW(pchPath))
1755 {
1756 dwFlags = 0;
1758 L"\\SystemRoot\\Fonts\\%s", pchPath);
1759 }
1760 else
1761 {
1763 Status = RtlStringCbCopyW(szPath, sizeof(szPath), pchPath);
1764 }
1765
1766 if (NT_SUCCESS(Status))
1767 {
1768 RtlCreateUnicodeString(&FileNameW, szPath);
1769 nFontCount += IntGdiAddFontResourceEx(&FileNameW, 0, dwFlags);
1770 RtlFreeUnicodeString(&FileNameW);
1771 }
1772
1773 RtlFreeUnicodeString(&FontTitleW);
1774 }
1775
1776 /* close now */
1778
1779 /* free memory block */
1780 if (InfoBuffer)
1781 {
1782 ExFreePoolWithTag(InfoBuffer, TAG_FONT);
1783 }
1784
1785 return (KeyFullInfo.Values != 0 && nFontCount != 0);
1786}
1787
1790{
1791 HANDLE Ret = NULL;
1793 PFONT_ENTRY_COLL_MEM EntryCollection;
1794 INT FaceCount;
1795
1797 if (!BufferCopy)
1798 {
1799 *pNumAdded = 0;
1800 return NULL;
1801 }
1802 RtlCopyMemory(BufferCopy, Buffer, dwSize);
1803
1804 LoadFont.pFileName = NULL;
1805 LoadFont.Memory = SharedMem_Create(BufferCopy, dwSize, FALSE);
1806 LoadFont.Characteristics = FR_PRIVATE | FR_NOT_ENUM;
1807 RtlInitUnicodeString(&LoadFont.RegValueName, NULL);
1808 LoadFont.IsTrueType = FALSE;
1809 LoadFont.PrivateEntry = NULL;
1811
1812 RtlFreeUnicodeString(&LoadFont.RegValueName);
1813
1814 /* Release our copy */
1818
1819 if (FaceCount > 0)
1820 {
1821 EntryCollection = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY_COLL_MEM), TAG_FONT);
1822 if (EntryCollection)
1823 {
1825 EntryCollection->Entry = LoadFont.PrivateEntry;
1826 IntLockProcessPrivateFonts(Win32Process);
1827 EntryCollection->Handle = ULongToHandle(++Win32Process->PrivateMemFontHandleCount);
1828 InsertTailList(&Win32Process->PrivateMemFontListHead, &EntryCollection->ListEntry);
1829 IntUnLockProcessPrivateFonts(Win32Process);
1830 Ret = EntryCollection->Handle;
1831 }
1832 }
1833 *pNumAdded = FaceCount;
1834
1835 return Ret;
1836}
1837
1838// FIXME: Add RemoveFontResource
1839
1842{
1844 PFONT_ENTRY_MEM FontEntry;
1845
1846 while (!IsListEmpty(&Head->ListEntry))
1847 {
1848 Entry = RemoveHeadList(&Head->ListEntry);
1849 FontEntry = CONTAINING_RECORD(Entry, FONT_ENTRY_MEM, ListEntry);
1850
1851 CleanupFontEntry(FontEntry->Entry);
1852 ExFreePoolWithTag(FontEntry, TAG_FONT);
1853 }
1854
1855 CleanupFontEntry(Head->Entry);
1857}
1858
1859static VOID FASTCALL
1861{
1862 PFONT_ENTRY_MEM FontMemEntry = Collection->Entry;
1863 PLIST_ENTRY ListEntry;
1864 RemoveEntryList(&Collection->ListEntry);
1865
1866 do {
1867 /* Also unlink the FONT_ENTRY stuff from the PrivateFontListHead */
1868 RemoveEntryList(&FontMemEntry->Entry->ListEntry);
1869
1870 ListEntry = FontMemEntry->ListEntry.Flink;
1871 FontMemEntry = CONTAINING_RECORD(ListEntry, FONT_ENTRY_MEM, ListEntry);
1872
1873 } while (FontMemEntry != Collection->Entry);
1874}
1875
1878{
1880 PFONT_ENTRY_COLL_MEM CurrentEntry;
1881 PFONT_ENTRY_COLL_MEM EntryCollection = NULL;
1883
1884 IntLockProcessPrivateFonts(Win32Process);
1885 for (Entry = Win32Process->PrivateMemFontListHead.Flink;
1886 Entry != &Win32Process->PrivateMemFontListHead;
1887 Entry = Entry->Flink)
1888 {
1889 CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY_COLL_MEM, ListEntry);
1890
1891 if (CurrentEntry->Handle == hMMFont)
1892 {
1893 EntryCollection = CurrentEntry;
1894 UnlinkFontMemCollection(CurrentEntry);
1895 break;
1896 }
1897 }
1898 IntUnLockProcessPrivateFonts(Win32Process);
1899
1900 if (EntryCollection)
1901 {
1902 IntGdiCleanupMemEntry(EntryCollection->Entry);
1903 ExFreePoolWithTag(EntryCollection, TAG_FONT);
1904 return TRUE;
1905 }
1906 return FALSE;
1907}
1908
1909
1912{
1915 PFONT_ENTRY_COLL_MEM EntryCollection;
1916
1917 DPRINT("IntGdiCleanupPrivateFontsForProcess()\n");
1918 do {
1919 Entry = NULL;
1920 EntryCollection = NULL;
1921
1922 IntLockProcessPrivateFonts(Win32Process);
1923 if (!IsListEmpty(&Win32Process->PrivateMemFontListHead))
1924 {
1925 Entry = Win32Process->PrivateMemFontListHead.Flink;
1926 EntryCollection = CONTAINING_RECORD(Entry, FONT_ENTRY_COLL_MEM, ListEntry);
1927 UnlinkFontMemCollection(EntryCollection);
1928 }
1929 IntUnLockProcessPrivateFonts(Win32Process);
1930
1931 if (EntryCollection)
1932 {
1933 IntGdiCleanupMemEntry(EntryCollection->Entry);
1934 ExFreePoolWithTag(EntryCollection, TAG_FONT);
1935 }
1936 else
1937 {
1938 /* No Mem fonts anymore, see if we have any other private fonts left */
1939 Entry = NULL;
1940 IntLockProcessPrivateFonts(Win32Process);
1941 if (!IsListEmpty(&Win32Process->PrivateFontListHead))
1942 {
1943 Entry = RemoveHeadList(&Win32Process->PrivateFontListHead);
1944 }
1945 IntUnLockProcessPrivateFonts(Win32Process);
1946
1947 if (Entry)
1948 {
1950 }
1951 }
1952
1953 } while (Entry);
1954}
1955
1958{
1959 return (gpsi->BitsPixel > 8) && g_RenderingEnabled;
1960}
1961
1964{
1966}
1967
1970{
1971 switch (logfont->lfQuality)
1972 {
1974 break;
1976 return FT_RENDER_MODE_MONO;
1977 case DRAFT_QUALITY:
1978 return FT_RENDER_MODE_LIGHT;
1979 case CLEARTYPE_QUALITY:
1980 if (!gspv.bFontSmoothing)
1981 break;
1983 break;
1984 return FT_RENDER_MODE_LCD;
1985 }
1986 return FT_RENDER_MODE_NORMAL;
1987}
1988
1989
1992{
1993 PLFONT plfont;
1994 LOGFONTW *plf;
1995
1996 ASSERT(lf);
1997 plfont = LFONT_AllocFontWithHandle();
1998 if (!plfont)
1999 {
2000 return STATUS_NO_MEMORY;
2001 }
2002
2003 ExInitializePushLock(&plfont->lock);
2004 *NewFont = plfont->BaseObject.hHmgr;
2005 plf = &plfont->logfont.elfEnumLogfontEx.elfLogFont;
2006 RtlCopyMemory(plf, lf, sizeof(LOGFONTW));
2007 if (lf->lfEscapement != lf->lfOrientation)
2008 {
2009 /* This should really depend on whether GM_ADVANCED is set */
2010 plf->lfOrientation = plf->lfEscapement;
2011 }
2012 LFONT_UnlockFont(plfont);
2013
2014 return STATUS_SUCCESS;
2015}
2016
2017/*************************************************************************
2018 * TranslateCharsetInfo
2019 *
2020 * Fills a CHARSETINFO structure for a character set, code page, or
2021 * font. This allows making the correspondance between different labelings
2022 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2023 * of the same encoding.
2024 *
2025 * Only one codepage will be set in Cs->fs. If TCI_SRCFONTSIG is used,
2026 * only one codepage should be set in *Src.
2027 *
2028 * RETURNS
2029 * TRUE on success, FALSE on failure.
2030 *
2031 */
2032static BOOLEAN
2034 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2035 if flags == TCI_SRCCHARSET: a character set value
2036 if flags == TCI_SRCCODEPAGE: a code page value */
2037 LPCHARSETINFO Cs, /* [out] structure to receive charset information */
2038 DWORD Flags /* [in] determines interpretation of lpSrc */)
2039{
2040 int Index = 0;
2041
2042 switch (Flags)
2043 {
2044 case TCI_SRCFONTSIG:
2045 while (Index < MAXTCIINDEX && 0 == (*Src >> Index & 0x0001))
2046 {
2047 Index++;
2048 }
2049 break;
2050 case TCI_SRCCODEPAGE:
2051 while (Index < MAXTCIINDEX && *Src != g_FontTci[Index].ciACP)
2052 {
2053 Index++;
2054 }
2055 break;
2056 case TCI_SRCCHARSET:
2057 while (Index < MAXTCIINDEX && *Src != g_FontTci[Index].ciCharset)
2058 {
2059 Index++;
2060 }
2061 break;
2062 case TCI_SRCLOCALE:
2064 return FALSE;
2065 default:
2066 return FALSE;
2067 }
2068
2069 if (Index >= MAXTCIINDEX || DEFAULT_CHARSET == g_FontTci[Index].ciCharset)
2070 {
2071 return FALSE;
2072 }
2073
2074 RtlCopyMemory(Cs, &g_FontTci[Index], sizeof(CHARSETINFO));
2075
2076 return TRUE;
2077}
2078
2079
2081{
2082 int i;
2083
2084 for(i = 0; i < ft_face->num_charmaps; i++)
2085 {
2086 if (ft_face->charmaps[i]->platform_id == TT_PLATFORM_MICROSOFT &&
2087 ft_face->charmaps[i]->encoding == FT_ENCODING_MS_SYMBOL)
2088 {
2089 return TRUE;
2090 }
2091 }
2092 return FALSE;
2093}
2094
2095static void FASTCALL
2097 TT_OS2 *pOS2, TT_HoriHeader *pHori,
2098 FT_WinFNT_HeaderRec *pFNT)
2099{
2100 FT_Fixed XScale, YScale;
2101 int Ascent, Descent;
2102 FT_Face Face = FontGDI->SharedFace->Face;
2103
2105
2106 XScale = Face->size->metrics.x_scale;
2107 YScale = Face->size->metrics.y_scale;
2108
2109 if (pFNT)
2110 {
2111 TM->tmHeight = pFNT->pixel_height;
2112 TM->tmAscent = pFNT->ascent;
2113 TM->tmDescent = TM->tmHeight - TM->tmAscent;
2116 TM->tmAveCharWidth = pFNT->avg_width;
2117 TM->tmMaxCharWidth = pFNT->max_width;
2118 TM->tmOverhang = 0;
2121 TM->tmFirstChar = pFNT->first_char;
2122 TM->tmLastChar = pFNT->last_char;
2123 TM->tmDefaultChar = pFNT->default_char + pFNT->first_char;
2124 TM->tmBreakChar = pFNT->break_char + pFNT->first_char;
2126 TM->tmWeight = FontGDI->RequestWeight;
2127 TM->tmItalic = FontGDI->RequestItalic;
2128 TM->tmUnderlined = FontGDI->RequestUnderline;
2129 TM->tmStruckOut = FontGDI->RequestStrikeOut;
2130 TM->tmCharSet = FontGDI->CharSet;
2131 return;
2132 }
2133
2134 ASSERT(pOS2);
2135 if (!pOS2)
2136 return;
2137
2138 if ((FT_Short)pOS2->usWinAscent + (FT_Short)pOS2->usWinDescent == 0)
2139 {
2140 Ascent = pHori->Ascender;
2141 Descent = -pHori->Descender;
2142 }
2143 else
2144 {
2145 Ascent = (FT_Short)pOS2->usWinAscent;
2146 Descent = (FT_Short)pOS2->usWinDescent;
2147 }
2148
2149 TM->tmAscent = FontGDI->tmAscent;
2150 TM->tmDescent = FontGDI->tmDescent;
2151 TM->tmHeight = TM->tmAscent + TM->tmDescent;
2152 TM->tmInternalLeading = FontGDI->tmInternalLeading;
2153
2154 /* MSDN says:
2155 * el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender)))
2156 */
2157 TM->tmExternalLeading = max(0, (FT_MulFix(pHori->Line_Gap
2158 - ((Ascent + Descent)
2159 - (pHori->Ascender - pHori->Descender)),
2160 YScale) + 32) >> 6);
2161 if (FontGDI->lfWidth != 0)
2162 TM->tmAveCharWidth = FontGDI->lfWidth;
2163 else
2164 TM->tmAveCharWidth = (FT_MulFix(pOS2->xAvgCharWidth, XScale) + 32) >> 6;
2165
2166 if (TM->tmAveCharWidth == 0)
2167 TM->tmAveCharWidth = 1;
2168
2169 /* Correct forumla to get the maxcharwidth from unicode and ansi font */
2170 TM->tmMaxCharWidth = (FT_MulFix(Face->max_advance_width, XScale) + 32) >> 6;
2171
2172 if (FontGDI->OriginalWeight != FW_DONTCARE &&
2173 FontGDI->OriginalWeight != FW_NORMAL)
2174 {
2175 TM->tmWeight = FontGDI->OriginalWeight;
2176 }
2177 else
2178 {
2179 TM->tmWeight = FontGDI->RequestWeight;
2180 }
2181
2182 TM->tmOverhang = 0;
2183 TM->tmDigitizedAspectX = 96;
2184 TM->tmDigitizedAspectY = 96;
2185 if (face_has_symbol_charmap(Face) ||
2186 (pOS2->usFirstCharIndex >= 0xf000 && pOS2->usFirstCharIndex < 0xf100))
2187 {
2188 USHORT cpOEM, cpAnsi;
2189
2190 EngGetCurrentCodePage(&cpOEM, &cpAnsi);
2191 TM->tmFirstChar = 0;
2192 switch(cpAnsi)
2193 {
2194 case 1257: /* Baltic */
2195 TM->tmLastChar = 0xf8fd;
2196 break;
2197 default:
2198 TM->tmLastChar = 0xf0ff;
2199 }
2200 TM->tmBreakChar = 0x20;
2201 TM->tmDefaultChar = 0x1f;
2202 }
2203 else
2204 {
2205 TM->tmFirstChar = pOS2->usFirstCharIndex; /* Should be the first char in the cmap */
2206 TM->tmLastChar = pOS2->usLastCharIndex; /* Should be min(cmap_last, os2_last) */
2207
2208 if(pOS2->usFirstCharIndex <= 1)
2209 TM->tmBreakChar = pOS2->usFirstCharIndex + 2;
2210 else if (pOS2->usFirstCharIndex > 0xff)
2211 TM->tmBreakChar = 0x20;
2212 else
2213 TM->tmBreakChar = pOS2->usFirstCharIndex;
2214 TM->tmDefaultChar = TM->tmBreakChar - 1;
2215 }
2216
2217 if (FontGDI->OriginalItalic || FontGDI->RequestItalic)
2218 {
2219 TM->tmItalic = 0xFF;
2220 }
2221 else
2222 {
2223 TM->tmItalic = 0;
2224 }
2225 TM->tmUnderlined = (FontGDI->RequestUnderline ? 0xFF : 0);
2226 TM->tmStruckOut = (FontGDI->RequestStrikeOut ? 0xFF : 0);
2227
2228 if (!FT_IS_FIXED_WIDTH(Face))
2229 {
2230 switch (pOS2->panose[PAN_PROPORTION_INDEX])
2231 {
2233 TM->tmPitchAndFamily = 0;
2234 break;
2235 default:
2237 break;
2238 }
2239 }
2240 else
2241 {
2242 TM->tmPitchAndFamily = 0;
2243 }
2244
2245 switch (pOS2->panose[PAN_FAMILYTYPE_INDEX])
2246 {
2247 case PAN_FAMILY_SCRIPT:
2249 break;
2252 break;
2253
2254 case PAN_ANY:
2255 case PAN_NO_FIT:
2257 case PAN_FAMILY_PICTORIAL: /* Symbol fonts get treated as if they were text */
2258 /* Which is clearly not what the panose spec says. */
2259 if (TM->tmPitchAndFamily == 0) /* Fixed */
2260 {
2262 }
2263 else
2264 {
2265 switch (pOS2->panose[PAN_SERIFSTYLE_INDEX])
2266 {
2267 case PAN_ANY:
2268 case PAN_NO_FIT:
2269 default:
2271 break;
2272
2273 case PAN_SERIF_COVE:
2277 case PAN_SERIF_SQUARE:
2278 case PAN_SERIF_THIN:
2279 case PAN_SERIF_BONE:
2281 case PAN_SERIF_TRIANGLE:
2283 break;
2284
2288 case PAN_SERIF_FLARED:
2289 case PAN_SERIF_ROUNDED:
2291 break;
2292 }
2293 }
2294 break;
2295 default:
2297 }
2298
2299 if (FT_IS_SCALABLE(Face))
2300 {
2302 }
2303 if (FT_IS_SFNT(Face))
2304 {
2306 }
2307
2308 TM->tmCharSet = FontGDI->CharSet;
2309}
2310
2311static NTSTATUS
2313 FT_UShort NameID, FT_UShort LangID);
2314
2315typedef struct FONT_NAMES
2316{
2317 UNICODE_STRING FamilyNameW; /* family name (TT_NAME_ID_FONT_FAMILY) */
2318 UNICODE_STRING FaceNameW; /* face name (TT_NAME_ID_FULL_NAME) */
2319 UNICODE_STRING StyleNameW; /* style name (TT_NAME_ID_FONT_SUBFAMILY) */
2320 UNICODE_STRING FullNameW; /* unique name (TT_NAME_ID_UNIQUE_ID) */
2321 ULONG OtmSize; /* size of OUTLINETEXTMETRICW with extra data */
2323
2324static __inline void FASTCALL
2326{
2327 ULONG OtmSize;
2328
2329 RtlInitUnicodeString(&Names->FamilyNameW, NULL);
2330 RtlInitUnicodeString(&Names->FaceNameW, NULL);
2331 RtlInitUnicodeString(&Names->StyleNameW, NULL);
2332 RtlInitUnicodeString(&Names->FullNameW, NULL);
2333
2334 /* family name */
2336 /* face name */
2338 /* style name */
2340 /* unique name (full name) */
2342
2343 /* Calculate the size of OUTLINETEXTMETRICW with extra data */
2344 OtmSize = sizeof(OUTLINETEXTMETRICW) +
2345 Names->FamilyNameW.Length + sizeof(UNICODE_NULL) +
2346 Names->FaceNameW.Length + sizeof(UNICODE_NULL) +
2347 Names->StyleNameW.Length + sizeof(UNICODE_NULL) +
2348 Names->FullNameW.Length + sizeof(UNICODE_NULL);
2349 Names->OtmSize = OtmSize;
2350}
2351
2352static __inline SIZE_T FASTCALL
2354{
2355 RtlCopyMemory(pb, pName->Buffer, pName->Length);
2356 *(WCHAR *)&pb[pName->Length] = UNICODE_NULL;
2357 return pName->Length + sizeof(UNICODE_NULL);
2358}
2359
2360static __inline BYTE *FASTCALL
2362{
2363 BYTE *pb = (BYTE *)Otm + sizeof(OUTLINETEXTMETRICW);
2364
2365 /* family name */
2366 Otm->otmpFamilyName = (LPSTR)(pb - (BYTE*) Otm);
2367 pb += IntStoreName(&Names->FamilyNameW, pb);
2368
2369 /* face name */
2370 Otm->otmpFaceName = (LPSTR)(pb - (BYTE*) Otm);
2371 pb += IntStoreName(&Names->FaceNameW, pb);
2372
2373 /* style name */
2374 Otm->otmpStyleName = (LPSTR)(pb - (BYTE*) Otm);
2375 pb += IntStoreName(&Names->StyleNameW, pb);
2376
2377 /* unique name (full name) */
2378 Otm->otmpFullName = (LPSTR)(pb - (BYTE*) Otm);
2379 pb += IntStoreName(&Names->FullNameW, pb);
2380
2381 return pb;
2382}
2383
2384static __inline void FASTCALL
2386{
2387 RtlFreeUnicodeString(&Names->FamilyNameW);
2388 RtlFreeUnicodeString(&Names->FaceNameW);
2389 RtlFreeUnicodeString(&Names->StyleNameW);
2390 RtlFreeUnicodeString(&Names->FullNameW);
2391}
2392
2393/*************************************************************
2394 * IntGetOutlineTextMetrics
2395 *
2396 */
2399 UINT Size,
2400 OUTLINETEXTMETRICW *Otm)
2401{
2402 TT_OS2 *pOS2;
2403 TT_HoriHeader *pHori;
2404 TT_Postscript *pPost;
2405 FT_Fixed XScale, YScale;
2406 FT_WinFNT_HeaderRec WinFNT;
2408 BYTE *pb;
2409 FONT_NAMES FontNames;
2410 PSHARED_FACE SharedFace = FontGDI->SharedFace;
2412 FT_Face Face = SharedFace->Face;
2413
2415 {
2416 Cache = &SharedFace->EnglishUS;
2417 }
2418 else
2419 {
2420 Cache = &SharedFace->UserLanguage;
2421 }
2422
2423 if (Size == 0 && Cache->OutlineRequiredSize > 0)
2424 {
2425 ASSERT(Otm == NULL);
2426 return Cache->OutlineRequiredSize;
2427 }
2428
2429 IntInitFontNames(&FontNames, SharedFace);
2430 Cache->OutlineRequiredSize = FontNames.OtmSize;
2431
2432 if (Size == 0)
2433 {
2434 ASSERT(Otm == NULL);
2435 IntFreeFontNames(&FontNames);
2436 return Cache->OutlineRequiredSize;
2437 }
2438
2439 ASSERT(Otm != NULL);
2440
2441 if (Size < Cache->OutlineRequiredSize)
2442 {
2443 DPRINT1("Size %u < OutlineRequiredSize %u\n", Size,
2444 Cache->OutlineRequiredSize);
2445 IntFreeFontNames(&FontNames);
2446 return 0; /* failure */
2447 }
2448
2449 XScale = Face->size->metrics.x_scale;
2450 YScale = Face->size->metrics.y_scale;
2451
2453
2454 pOS2 = FT_Get_Sfnt_Table(Face, FT_SFNT_OS2);
2455 pHori = FT_Get_Sfnt_Table(Face, FT_SFNT_HHEA);
2456 pPost = FT_Get_Sfnt_Table(Face, FT_SFNT_POST); /* We can live with this failing */
2457 Error = FT_Get_WinFNT_Header(Face, &WinFNT);
2458
2459 if (pOS2 == NULL && Error)
2460 {
2462 DPRINT1("Can't find OS/2 table - not TT font?\n");
2463 IntFreeFontNames(&FontNames);
2464 return 0;
2465 }
2466
2467 if (pHori == NULL && Error)
2468 {
2470 DPRINT1("Can't find HHEA table - not TT font?\n");
2471 IntFreeFontNames(&FontNames);
2472 return 0;
2473 }
2474
2475 Otm->otmSize = Cache->OutlineRequiredSize;
2476
2477 FillTM(&Otm->otmTextMetrics, FontGDI, pOS2, pHori, !Error ? &WinFNT : 0);
2478
2479 if (!pOS2)
2480 goto skip_os2;
2481
2482 Otm->otmFiller = 0;
2484 Otm->otmfsSelection = pOS2->fsSelection;
2485 Otm->otmfsType = pOS2->fsType;
2486 Otm->otmsCharSlopeRise = pHori->caret_Slope_Rise;
2487 Otm->otmsCharSlopeRun = pHori->caret_Slope_Run;
2488 Otm->otmItalicAngle = 0; /* POST table */
2489 Otm->otmEMSquare = Face->units_per_EM;
2490
2491#define SCALE_X(value) ((FT_MulFix((value), XScale) + 32) >> 6)
2492#define SCALE_Y(value) ((FT_MulFix((value), YScale) + 32) >> 6)
2493
2494 Otm->otmAscent = SCALE_Y(pOS2->sTypoAscender);
2495 Otm->otmDescent = SCALE_Y(pOS2->sTypoDescender);
2496 Otm->otmLineGap = SCALE_Y(pOS2->sTypoLineGap);
2497 Otm->otmsCapEmHeight = SCALE_Y(pOS2->sCapHeight);
2498 Otm->otmsXHeight = SCALE_Y(pOS2->sxHeight);
2499 Otm->otmrcFontBox.left = SCALE_X(Face->bbox.xMin);
2500 Otm->otmrcFontBox.right = SCALE_X(Face->bbox.xMax);
2501 Otm->otmrcFontBox.top = SCALE_Y(Face->bbox.yMax);
2502 Otm->otmrcFontBox.bottom = SCALE_Y(Face->bbox.yMin);
2505 Otm->otmMacLineGap = Otm->otmLineGap;
2506 Otm->otmusMinimumPPEM = 0; /* TT Header */
2517
2518 if (!pPost)
2519 {
2520 Otm->otmsUnderscoreSize = 0;
2521 Otm->otmsUnderscorePosition = 0;
2522 }
2523 else
2524 {
2527 }
2528
2529#undef SCALE_X
2530#undef SCALE_Y
2531
2532skip_os2:
2534
2535 pb = IntStoreFontNames(&FontNames, Otm);
2536 ASSERT(pb - (BYTE*)Otm == Cache->OutlineRequiredSize);
2537
2538 IntFreeFontNames(&FontNames);
2539
2540 return Cache->OutlineRequiredSize;
2541}
2542
2543/* See https://msdn.microsoft.com/en-us/library/bb165625(v=vs.90).aspx */
2544static BYTE
2546{
2547 /* FIXME: Add more and fix if wrong */
2548 switch (PRIMARYLANGID(LangID))
2549 {
2550 case LANG_CHINESE:
2551 switch (SUBLANGID(LangID))
2552 {
2554 return CHINESEBIG5_CHARSET;
2556 default:
2557 break;
2558 }
2559 return GB2312_CHARSET;
2560
2561 case LANG_CZECH: case LANG_HUNGARIAN: case LANG_POLISH:
2562 case LANG_SLOVAK: case LANG_SLOVENIAN: case LANG_ROMANIAN:
2563 return EASTEUROPE_CHARSET;
2564
2566 case LANG_SERBIAN: case LANG_UKRAINIAN:
2567 return RUSSIAN_CHARSET;
2568
2569 case LANG_ARABIC: return ARABIC_CHARSET;
2570 case LANG_GREEK: return GREEK_CHARSET;
2571 case LANG_HEBREW: return HEBREW_CHARSET;
2572 case LANG_JAPANESE: return SHIFTJIS_CHARSET;
2573 case LANG_KOREAN: return JOHAB_CHARSET;
2574 case LANG_TURKISH: return TURKISH_CHARSET;
2575 case LANG_THAI: return THAI_CHARSET;
2576 case LANG_LATVIAN: return BALTIC_CHARSET;
2578
2579 case LANG_ENGLISH: case LANG_BASQUE: case LANG_CATALAN:
2580 case LANG_DANISH: case LANG_DUTCH: case LANG_FINNISH:
2581 case LANG_FRENCH: case LANG_GERMAN: case LANG_ITALIAN:
2583 case LANG_SWEDISH: default:
2584 return ANSI_CHARSET;
2585 }
2586}
2587
2588static void
2590{
2591 BYTE b, *pb = pvData;
2592 Size /= 2;
2593 while (Size-- > 0)
2594 {
2595 b = pb[0];
2596 pb[0] = pb[1];
2597 pb[1] = b;
2598 ++pb; ++pb;
2599 }
2600}
2601
2602static NTSTATUS
2604 FT_UShort NameID, FT_UShort LangID)
2605{
2607 INT i, Count, BestIndex, Score, BestScore;
2610 ANSI_STRING AnsiName;
2612 FT_Face Face = SharedFace->Face;
2613
2614 RtlFreeUnicodeString(pNameW);
2615
2616 /* select cache */
2618 {
2619 Cache = &SharedFace->EnglishUS;
2620 }
2621 else
2622 {
2623 Cache = &SharedFace->UserLanguage;
2624 }
2625
2626 /* use cache if available */
2627 if (NameID == TT_NAME_ID_FONT_FAMILY && Cache->FontFamily.Buffer)
2628 {
2629 return DuplicateUnicodeString(&Cache->FontFamily, pNameW);
2630 }
2631 if (NameID == TT_NAME_ID_FULL_NAME && Cache->FullName.Buffer)
2632 {
2633 return DuplicateUnicodeString(&Cache->FullName, pNameW);
2634 }
2635
2636 BestIndex = -1;
2637 BestScore = 0;
2638
2640 for (i = 0; i < Count; ++i)
2641 {
2642 Error = FT_Get_Sfnt_Name(Face, i, &Name);
2643 if (Error)
2644 {
2645 continue; /* failure */
2646 }
2647
2648 if (Name.name_id != NameID)
2649 {
2650 continue; /* mismatched */
2651 }
2652
2653 if (Name.platform_id != TT_PLATFORM_MICROSOFT ||
2654 (Name.encoding_id != TT_MS_ID_UNICODE_CS &&
2655 Name.encoding_id != TT_MS_ID_SYMBOL_CS))
2656 {
2657 continue; /* not Microsoft Unicode name */
2658 }
2659
2660 if (Name.string == NULL || Name.string_len == 0 ||
2661 (Name.string[0] == 0 && Name.string[1] == 0))
2662 {
2663 continue; /* invalid string */
2664 }
2665
2666 if (Name.language_id == LangID)
2667 {
2668 Score = 30;
2669 BestIndex = i;
2670 break; /* best match */
2671 }
2672 else if (PRIMARYLANGID(Name.language_id) == PRIMARYLANGID(LangID))
2673 {
2674 Score = 20;
2675 }
2676 else if (PRIMARYLANGID(Name.language_id) == LANG_ENGLISH)
2677 {
2678 Score = 10;
2679 }
2680 else
2681 {
2682 Score = 0;
2683 }
2684
2685 if (Score > BestScore)
2686 {
2687 BestScore = Score;
2688 BestIndex = i;
2689 }
2690 }
2691
2692 if (BestIndex >= 0)
2693 {
2694 /* store the best name */
2695 Error = (Score == 30) ? 0 : FT_Get_Sfnt_Name(Face, BestIndex, &Name);
2696 if (!Error)
2697 {
2698 /* NOTE: Name.string is not null-terminated */
2699 UNICODE_STRING Tmp;
2700 Tmp.Buffer = (PWCH)Name.string;
2701 Tmp.Length = Tmp.MaximumLength = Name.string_len;
2702
2703 pNameW->Length = 0;
2704 pNameW->MaximumLength = Name.string_len + sizeof(WCHAR);
2706
2707 if (pNameW->Buffer)
2708 {
2709 Status = RtlAppendUnicodeStringToString(pNameW, &Tmp);
2710 if (Status == STATUS_SUCCESS)
2711 {
2712 /* Convert UTF-16 big endian to little endian */
2713 SwapEndian(pNameW->Buffer, pNameW->Length);
2714 }
2715 }
2716 else
2717 {
2719 }
2720 }
2721 }
2722
2723 if (!NT_SUCCESS(Status))
2724 {
2725 /* defaulted */
2726 if (NameID == TT_NAME_ID_FONT_SUBFAMILY)
2727 {
2728 RtlInitAnsiString(&AnsiName, Face->style_name);
2729 Status = RtlAnsiStringToUnicodeString(pNameW, &AnsiName, TRUE);
2730 }
2731 else
2732 {
2733 RtlInitAnsiString(&AnsiName, Face->family_name);
2734 Status = RtlAnsiStringToUnicodeString(pNameW, &AnsiName, TRUE);
2735 }
2736 }
2737
2738 if (NT_SUCCESS(Status))
2739 {
2740 /* make cache */
2741 if (NameID == TT_NAME_ID_FONT_FAMILY)
2742 {
2745 if (!Cache->FontFamily.Buffer)
2746 DuplicateUnicodeString(pNameW, &Cache->FontFamily);
2748 }
2749 else if (NameID == TT_NAME_ID_FULL_NAME)
2750 {
2753 if (!Cache->FullName.Buffer)
2754 DuplicateUnicodeString(pNameW, &Cache->FullName);
2756 }
2757 }
2758
2759 return Status;
2760}
2761
2762static void FASTCALL
2764 LPCWSTR FullName, PFONTGDI FontGDI)
2765{
2766 ANSI_STRING StyleA;
2767 UNICODE_STRING StyleW;
2768 TT_OS2 *pOS2;
2770 CHARSETINFO CharSetInfo;
2771 unsigned i, Size;
2772 OUTLINETEXTMETRICW *Otm;
2773 LOGFONTW *Lf;
2774 TEXTMETRICW *TM;
2775 NEWTEXTMETRICW *Ntm;
2776 DWORD fs0;
2778 PSHARED_FACE SharedFace = FontGDI->SharedFace;
2779 FT_Face Face = SharedFace->Face;
2780 UNICODE_STRING NameW;
2781
2782 RtlInitUnicodeString(&NameW, NULL);
2784 Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
2786 if (!Otm)
2787 {
2788 return;
2789 }
2790 Size = IntGetOutlineTextMetrics(FontGDI, Size, Otm);
2791 if (!Size)
2792 {
2794 return;
2795 }
2796
2797 Lf = &Info->EnumLogFontEx.elfLogFont;
2798 TM = &Otm->otmTextMetrics;
2799
2800 Lf->lfHeight = TM->tmHeight;
2801 Lf->lfWidth = TM->tmAveCharWidth;
2802 Lf->lfWeight = TM->tmWeight;
2803 Lf->lfItalic = TM->tmItalic;
2804 Lf->lfPitchAndFamily = (TM->tmPitchAndFamily & 0xf1) + 1;
2805 Lf->lfCharSet = TM->tmCharSet;
2809
2810 Ntm = &Info->NewTextMetricEx.ntmTm;
2811 Ntm->tmHeight = TM->tmHeight;
2812 Ntm->tmAscent = TM->tmAscent;
2813 Ntm->tmDescent = TM->tmDescent;
2816 Ntm->tmAveCharWidth = TM->tmAveCharWidth;
2817 Ntm->tmMaxCharWidth = TM->tmMaxCharWidth;
2818 Ntm->tmWeight = TM->tmWeight;
2819 Ntm->tmOverhang = TM->tmOverhang;
2822 Ntm->tmFirstChar = TM->tmFirstChar;
2823 Ntm->tmLastChar = TM->tmLastChar;
2824 Ntm->tmDefaultChar = TM->tmDefaultChar;
2825 Ntm->tmBreakChar = TM->tmBreakChar;
2826 Ntm->tmItalic = TM->tmItalic;
2827 Ntm->tmUnderlined = TM->tmUnderlined;
2828 Ntm->tmStruckOut = TM->tmStruckOut;
2830 Ntm->tmCharSet = TM->tmCharSet;
2831 Ntm->ntmFlags = TM->tmItalic ? NTM_ITALIC : 0;
2832
2833 if (550 < TM->tmWeight) Ntm->ntmFlags |= NTM_BOLD;
2834
2835 if (0 == Ntm->ntmFlags) Ntm->ntmFlags = NTM_REGULAR;
2836
2837 Info->FontType = (0 != (TM->tmPitchAndFamily & TMPF_TRUETYPE)
2838 ? TRUETYPE_FONTTYPE : 0);
2839
2840 if (0 == (TM->tmPitchAndFamily & TMPF_VECTOR))
2841 Info->FontType |= RASTER_FONTTYPE;
2842
2843
2844 /* face name */
2845 if (!FaceName)
2846 FaceName = (WCHAR*)((ULONG_PTR)Otm + (ULONG_PTR)Otm->otmpFamilyName);
2847
2848 RtlStringCbCopyW(Lf->lfFaceName, sizeof(Lf->lfFaceName), FaceName);
2849
2850 /* full name */
2851 if (!FullName)
2852 FullName = (WCHAR*)((ULONG_PTR) Otm + (ULONG_PTR)Otm->otmpFaceName);
2853
2854 RtlStringCbCopyW(Info->EnumLogFontEx.elfFullName,
2855 sizeof(Info->EnumLogFontEx.elfFullName),
2856 FullName);
2857
2858 RtlInitAnsiString(&StyleA, Face->style_name);
2859 StyleW.Buffer = Info->EnumLogFontEx.elfStyle;
2860 StyleW.MaximumLength = sizeof(Info->EnumLogFontEx.elfStyle);
2861 status = RtlAnsiStringToUnicodeString(&StyleW, &StyleA, FALSE);
2862 if (!NT_SUCCESS(status))
2863 {
2865 return;
2866 }
2867 Info->EnumLogFontEx.elfScript[0] = UNICODE_NULL;
2868
2870 pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
2871
2872 if (!pOS2)
2873 {
2876 return;
2877 }
2878
2879 Ntm->ntmSizeEM = Otm->otmEMSquare;
2881 Ntm->ntmAvgWidth = 0;
2882
2884
2885 fs.fsCsb[0] = pOS2->ulCodePageRange1;
2886 fs.fsCsb[1] = pOS2->ulCodePageRange2;
2887 fs.fsUsb[0] = pOS2->ulUnicodeRange1;
2888 fs.fsUsb[1] = pOS2->ulUnicodeRange2;
2889 fs.fsUsb[2] = pOS2->ulUnicodeRange3;
2890 fs.fsUsb[3] = pOS2->ulUnicodeRange4;
2891
2892 if (0 == pOS2->version)
2893 {
2894 FT_UInt Dummy;
2895
2896 if (FT_Get_First_Char(Face, &Dummy) < 0x100)
2897 fs.fsCsb[0] |= FS_LATIN1;
2898 else
2899 fs.fsCsb[0] |= FS_SYMBOL;
2900 }
2902
2903 if (fs.fsCsb[0] == 0)
2904 {
2905 /* Let's see if we can find any interesting cmaps */
2906 for (i = 0; i < (UINT)Face->num_charmaps; i++)
2907 {
2908 switch (Face->charmaps[i]->encoding)
2909 {
2910 case FT_ENCODING_UNICODE:
2911 case FT_ENCODING_APPLE_ROMAN:
2912 fs.fsCsb[0] |= FS_LATIN1;
2913 break;
2914 case FT_ENCODING_MS_SYMBOL:
2915 fs.fsCsb[0] |= FS_SYMBOL;
2916 break;
2917 default:
2918 break;
2919 }
2920 }
2921 }
2922
2923 for (i = 0; i < MAXTCIINDEX; i++)
2924 {
2925 fs0 = 1L << i;
2926 if (fs.fsCsb[0] & fs0)
2927 {
2928 if (!IntTranslateCharsetInfo(&fs0, &CharSetInfo, TCI_SRCFONTSIG))
2929 {
2930 CharSetInfo.ciCharset = DEFAULT_CHARSET;
2931 }
2932 if (DEFAULT_CHARSET != CharSetInfo.ciCharset)
2933 {
2934 if (g_ElfScripts[i])
2935 wcscpy(Info->EnumLogFontEx.elfScript, g_ElfScripts[i]);
2936 else
2937 {
2938 DPRINT1("Unknown elfscript for bit %u\n", i);
2939 }
2940 }
2941 }
2942 }
2943 Info->NewTextMetricEx.ntmFontSig = fs;
2944}
2945
2946static BOOLEAN FASTCALL
2949 LPCWSTR NominalName,
2950 LONG *pCount,
2951 LONG MaxCount,
2952 PLIST_ENTRY Head)
2953{
2955 PFONT_ENTRY CurrentEntry;
2956 FONTGDI *FontGDI;
2957 FONTFAMILYINFO InfoEntry;
2958 LONG Count = *pCount;
2959
2960 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
2961 {
2962 CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
2963 FontGDI = CurrentEntry->Font;
2964 ASSERT(FontGDI);
2965
2966 if (LogFont->lfCharSet != DEFAULT_CHARSET &&
2967 LogFont->lfCharSet != FontGDI->CharSet)
2968 {
2969 continue; /* charset mismatch */
2970 }
2971
2972 /* get one info entry */
2973 FontFamilyFillInfo(&InfoEntry, NULL, NULL, FontGDI);
2974
2975 if (LogFont->lfFaceName[0] != UNICODE_NULL)
2976 {
2977 /* check name */
2978 if (_wcsnicmp(LogFont->lfFaceName,
2980 RTL_NUMBER_OF(LogFont->lfFaceName) - 1) != 0 &&
2981 _wcsnicmp(LogFont->lfFaceName,
2982 InfoEntry.EnumLogFontEx.elfFullName,
2983 RTL_NUMBER_OF(LogFont->lfFaceName) - 1) != 0)
2984 {
2985 continue;
2986 }
2987 }
2988
2989 if (NominalName)
2990 {
2991 /* store the nominal name */
2993 sizeof(InfoEntry.EnumLogFontEx.elfLogFont.lfFaceName),
2994 NominalName);
2995 }
2996
2997 /* store one entry to Info */
2998 if (0 <= Count && Count < MaxCount)
2999 {
3000 RtlCopyMemory(&Info[Count], &InfoEntry, sizeof(InfoEntry));
3001 }
3002 Count++;
3003 }
3004
3005 *pCount = Count;
3006
3007 return TRUE;
3008}
3009
3010static BOOLEAN FASTCALL
3013 LONG *pCount,
3014 LONG MaxCount)
3015{
3016 PLIST_ENTRY pEntry, pHead = &g_FontSubstListHead;
3017 PFONTSUBST_ENTRY pCurrentEntry;
3018 PUNICODE_STRING pFromW, pToW;
3019 LOGFONTW lf = *LogFont;
3021
3022 for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink)
3023 {
3024 pCurrentEntry = CONTAINING_RECORD(pEntry, FONTSUBST_ENTRY, ListEntry);
3025
3026 pFromW = &pCurrentEntry->FontNames[FONTSUBST_FROM];
3027 if (LogFont->lfFaceName[0] != UNICODE_NULL)
3028 {
3029 /* check name */
3030 if (_wcsicmp(LogFont->lfFaceName, pFromW->Buffer) != 0)
3031 continue; /* mismatch */
3032 }
3033
3034 pToW = &pCurrentEntry->FontNames[FONTSUBST_TO];
3035 if (RtlEqualUnicodeString(pFromW, pToW, TRUE) &&
3036 pCurrentEntry->CharSets[FONTSUBST_FROM] ==
3037 pCurrentEntry->CharSets[FONTSUBST_TO])
3038 {
3039 /* identical mapping */
3040 continue;
3041 }
3042
3043 /* substitute and get the real name */
3044 IntUnicodeStringToBuffer(lf.lfFaceName, sizeof(lf.lfFaceName), pFromW);
3046 if (LogFont->lfCharSet != DEFAULT_CHARSET && LogFont->lfCharSet != lf.lfCharSet)
3047 continue;
3048
3049 /* search in global fonts */
3051 GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount, &g_FontListHead);
3053
3054 /* search in private fonts */
3055 IntLockProcessPrivateFonts(Win32Process);
3056 GetFontFamilyInfoForList(&lf, Info, pFromW->Buffer, pCount, MaxCount,
3057 &Win32Process->PrivateFontListHead);
3058 IntUnLockProcessPrivateFonts(Win32Process);
3059
3060 if (LogFont->lfFaceName[0] != UNICODE_NULL)
3061 {
3062 /* it's already matched to the exact name and charset if the name
3063 was specified at here, then so don't scan more for another name */
3064 break;
3065 }
3066 }
3067
3068 return TRUE;
3069}
3070
3071BOOL
3074{
3075 if ( lprs )
3076 {
3077 lprs->nSize = sizeof(RASTERIZER_STATUS);
3078 lprs->wFlags = TT_AVAILABLE | TT_ENABLED;
3079 lprs->nLanguageID = gusLanguageID;
3080 return TRUE;
3081 }
3083 return FALSE;
3084}
3085
3086static DWORD
3088{
3089 DWORD dwHash = cdw;
3090 const DWORD *pdw = pv;
3091
3092 while (cdw-- > 0)
3093 {
3094 dwHash *= 3;
3095 dwHash ^= *pdw++;
3096 }
3097
3098 return dwHash;
3099}
3100
3101static FT_BitmapGlyph
3103{
3104 PLIST_ENTRY CurrentEntry;
3105 PFONT_CACHE_ENTRY FontEntry;
3106 DWORD dwHash = pCache->dwHash;
3107
3109
3110 for (CurrentEntry = g_FontCacheListHead.Flink;
3111 CurrentEntry != &g_FontCacheListHead;
3112 CurrentEntry = CurrentEntry->Flink)
3113 {
3114 FontEntry = CONTAINING_RECORD(CurrentEntry, FONT_CACHE_ENTRY, ListEntry);
3115 if (FontEntry->dwHash == dwHash &&
3116 FontEntry->Hashed.GlyphIndex == pCache->Hashed.GlyphIndex &&
3117 FontEntry->Hashed.Face == pCache->Hashed.Face &&
3118 FontEntry->Hashed.lfHeight == pCache->Hashed.lfHeight &&
3119 FontEntry->Hashed.lfWidth == pCache->Hashed.lfWidth &&
3120 FontEntry->Hashed.AspectValue == pCache->Hashed.AspectValue &&
3121 memcmp(&FontEntry->Hashed.matTransform, &pCache->Hashed.matTransform,
3122 sizeof(FT_Matrix)) == 0)
3123 {
3124 break;
3125 }
3126 }
3127
3128 if (CurrentEntry == &g_FontCacheListHead)
3129 {
3130 return NULL;
3131 }
3132
3133 RemoveEntryList(CurrentEntry);
3134 InsertHeadList(&g_FontCacheListHead, CurrentEntry);
3135 return FontEntry->BitmapGlyph;
3136}
3137
3138/* no cache */
3139static FT_BitmapGlyph
3141 FT_Face Face,
3142 FT_GlyphSlot GlyphSlot,
3143 FT_Render_Mode RenderMode)
3144{
3145 FT_Glyph Glyph;
3146 INT error;
3147 FT_Bitmap AlignedBitmap;
3148 FT_BitmapGlyph BitmapGlyph;
3149
3151
3152 error = FT_Get_Glyph(GlyphSlot, &Glyph);
3153 if (error)
3154 {
3155 DPRINT1("Failure getting glyph.\n");
3156 return NULL;
3157 }
3158
3159 error = FT_Glyph_To_Bitmap(&Glyph, RenderMode, 0, 1);
3160 if (error)
3161 {
3162 FT_Done_Glyph(Glyph);
3163 DPRINT1("Failure rendering glyph.\n");
3164 return NULL;
3165 }
3166
3167 BitmapGlyph = (FT_BitmapGlyph)Glyph;
3168 FT_Bitmap_New(&AlignedBitmap);
3169 if (FT_Bitmap_Convert(GlyphSlot->library, &BitmapGlyph->bitmap, &AlignedBitmap, 4))
3170 {
3171 DPRINT1("Conversion failed\n");
3172 FT_Done_Glyph((FT_Glyph)BitmapGlyph);
3173 return NULL;
3174 }
3175
3176 FT_Bitmap_Done(GlyphSlot->library, &BitmapGlyph->bitmap);
3177 BitmapGlyph->bitmap = AlignedBitmap;
3178
3179 return BitmapGlyph;
3180}
3181
3182static FT_BitmapGlyph
3185 IN FT_GlyphSlot GlyphSlot)
3186{
3187 FT_Glyph GlyphCopy;
3188 INT error;
3189 PFONT_CACHE_ENTRY NewEntry;
3190 FT_Bitmap AlignedBitmap;
3191 FT_BitmapGlyph BitmapGlyph;
3192
3194
3195 error = FT_Get_Glyph(GlyphSlot, &GlyphCopy);
3196 if (error)
3197 {
3198 DPRINT1("Failure caching glyph.\n");
3199 return NULL;
3200 };
3201
3202 error = FT_Glyph_To_Bitmap(&GlyphCopy, Cache->Hashed.Aspect.RenderMode, 0, 1);
3203 if (error)
3204 {
3205 FT_Done_Glyph(GlyphCopy);
3206 DPRINT1("Failure rendering glyph.\n");
3207 return NULL;
3208 };
3209
3211 if (!NewEntry)
3212 {
3213 DPRINT1("Alloc failure caching glyph.\n");
3214 FT_Done_Glyph(GlyphCopy);
3215 return NULL;
3216 }
3217
3218 BitmapGlyph = (FT_BitmapGlyph)GlyphCopy;
3219 FT_Bitmap_New(&AlignedBitmap);
3220 if(FT_Bitmap_Convert(GlyphSlot->library, &BitmapGlyph->bitmap, &AlignedBitmap, 4))
3221 {
3222 DPRINT1("Conversion failed\n");
3223 ExFreePoolWithTag(NewEntry, TAG_FONT);
3224 FT_Bitmap_Done(GlyphSlot->library, &AlignedBitmap);
3225 FT_Done_Glyph((FT_Glyph)BitmapGlyph);
3226 return NULL;
3227 }
3228
3229 FT_Bitmap_Done(GlyphSlot->library, &BitmapGlyph->bitmap);
3230 BitmapGlyph->bitmap = AlignedBitmap;
3231
3232 NewEntry->BitmapGlyph = BitmapGlyph;
3233 NewEntry->dwHash = Cache->dwHash;
3234 NewEntry->Hashed = Cache->Hashed;
3235
3238 {
3240 RemoveCachedEntry(NewEntry);
3241 }
3242
3243 return BitmapGlyph;
3244}
3245
3246
3247static unsigned int get_native_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
3248{
3249 TTPOLYGONHEADER *pph;
3250 TTPOLYCURVE *ppc;
3251 int needed = 0, point = 0, contour, first_pt;
3252 unsigned int pph_start, cpfx;
3253 DWORD type;
3254
3255 for (contour = 0; contour < outline->n_contours; contour++)
3256 {
3257 /* Ignore contours containing one point */
3258 if (point == outline->contours[contour])
3259 {
3260 point++;
3261 continue;
3262 }
3263
3264 pph_start = needed;
3265 pph = (TTPOLYGONHEADER *)(buf + needed);
3266 first_pt = point;
3267 if (buf)
3268 {
3269 pph->dwType = TT_POLYGON_TYPE;
3270 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
3271 }
3272 needed += sizeof(*pph);
3273 point++;
3274 while (point <= outline->contours[contour])
3275 {
3276 ppc = (TTPOLYCURVE *)(buf + needed);
3277 type = (outline->tags[point] & FT_Curve_Tag_On) ?
3279 cpfx = 0;
3280 do
3281 {
3282 if (buf)
3283 FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3284 cpfx++;
3285 point++;
3286 } while (point <= outline->contours[contour] &&
3287 (outline->tags[point] & FT_Curve_Tag_On) ==
3288 (outline->tags[point-1] & FT_Curve_Tag_On));
3289 /* At the end of a contour Windows adds the start point, but
3290 only for Beziers */
3291 if (point > outline->contours[contour] &&
3292 !(outline->tags[point-1] & FT_Curve_Tag_On))
3293 {
3294 if (buf)
3295 FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]);
3296 cpfx++;
3297 }
3298 else if (point <= outline->contours[contour] &&
3299 outline->tags[point] & FT_Curve_Tag_On)
3300 {
3301 /* add closing pt for bezier */
3302 if (buf)
3303 FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3304 cpfx++;
3305 point++;
3306 }
3307 if (buf)
3308 {
3309 ppc->wType = type;
3310 ppc->cpfx = cpfx;
3311 }
3312 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
3313 }
3314 if (buf)
3315 pph->cb = needed - pph_start;
3316 }
3317 return needed;
3318}
3319
3320static unsigned int get_bezier_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
3321{
3322 /* Convert the quadratic Beziers to cubic Beziers.
3323 The parametric eqn for a cubic Bezier is, from PLRM:
3324 r(t) = at^3 + bt^2 + ct + r0
3325 with the control points:
3326 r1 = r0 + c/3
3327 r2 = r1 + (c + b)/3
3328 r3 = r0 + c + b + a
3329
3330 A quadratic Bezier has the form:
3331 p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
3332
3333 So equating powers of t leads to:
3334 r1 = 2/3 p1 + 1/3 p0
3335 r2 = 2/3 p1 + 1/3 p2
3336 and of course r0 = p0, r3 = p2
3337 */
3338 int contour, point = 0, first_pt;
3339 TTPOLYGONHEADER *pph;
3340 TTPOLYCURVE *ppc;
3341 DWORD pph_start, cpfx, type;
3342 FT_Vector cubic_control[4];
3343 unsigned int needed = 0;
3344
3345 for (contour = 0; contour < outline->n_contours; contour++)
3346 {
3347 pph_start = needed;
3348 pph = (TTPOLYGONHEADER *)(buf + needed);
3349 first_pt = point;
3350 if (buf)
3351 {
3352 pph->dwType = TT_POLYGON_TYPE;
3353 FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart);
3354 }
3355 needed += sizeof(*pph);
3356 point++;
3357 while (point <= outline->contours[contour])
3358 {
3359 ppc = (TTPOLYCURVE *)(buf + needed);
3360 type = (outline->tags[point] & FT_Curve_Tag_On) ?
3362 cpfx = 0;
3363 do
3364 {
3365 if (type == TT_PRIM_LINE)
3366 {
3367 if (buf)
3368 FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]);
3369 cpfx++;
3370 point++;
3371 }
3372 else
3373 {
3374 /* Unlike QSPLINEs, CSPLINEs always have their endpoint
3375 so cpfx = 3n */
3376
3377 /* FIXME: Possible optimization in endpoint calculation
3378 if there are two consecutive curves */
3379 cubic_control[0] = outline->points[point-1];
3380 if (!(outline->tags[point-1] & FT_Curve_Tag_On))
3381 {
3382 cubic_control[0].x += outline->points[point].x + 1;
3383 cubic_control[0].y += outline->points[point].y + 1;
3384 cubic_control[0].x >>= 1;
3385 cubic_control[0].y >>= 1;
3386 }
3387 if (point+1 > outline->contours[contour])
3388 cubic_control[3] = outline->points[first_pt];
3389 else
3390 {
3391 cubic_control[3] = outline->points[point+1];
3392 if (!(outline->tags[point+1] & FT_Curve_Tag_On))
3393 {
3394 cubic_control[3].x += outline->points[point].x + 1;
3395 cubic_control[3].y += outline->points[point].y + 1;
3396 cubic_control[3].x >>= 1;
3397 cubic_control[3].y >>= 1;
3398 }
3399 }
3400 /* r1 = 1/3 p0 + 2/3 p1
3401 r2 = 1/3 p2 + 2/3 p1 */
3402 cubic_control[1].x = (2 * outline->points[point].x + 1) / 3;
3403 cubic_control[1].y = (2 * outline->points[point].y + 1) / 3;
3404 cubic_control[2] = cubic_control[1];
3405 cubic_control[1].x += (cubic_control[0].x + 1) / 3;
3406 cubic_control[1].y += (cubic_control[0].y + 1) / 3;
3407 cubic_control[2].x += (cubic_control[3].x + 1) / 3;
3408 cubic_control[2].y += (cubic_control[3].y + 1) / 3;
3409 if (buf)
3410 {
3411 FTVectorToPOINTFX(&cubic_control[1], &ppc->apfx[cpfx]);
3412 FTVectorToPOINTFX(&cubic_control[2], &ppc->apfx[cpfx+1]);
3413 FTVectorToPOINTFX(&cubic_control[3], &ppc->apfx[cpfx+2]);
3414 }
3415 cpfx += 3;
3416 point++;
3417 }
3418 } while (point <= outline->contours[contour] &&
3419 (outline->tags[point] & FT_Curve_Tag_On) ==
3420 (outline->tags[point-1] & FT_Curve_Tag_On));
3421 /* At the end of a contour Windows adds the start point,
3422 but only for Beziers and we've already done that.
3423 */
3424 if (point <= outline->contours[contour] &&
3425 outline->tags[point] & FT_Curve_Tag_On)
3426 {
3427 /* This is the closing pt of a bezier, but we've already
3428 added it, so just inc point and carry on */
3429 point++;
3430 }
3431 if (buf)
3432 {
3433 ppc->wType = type;
3434 ppc->cpfx = cpfx;
3435 }
3436 needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX);
3437 }
3438 if (buf)
3439 pph->cb = needed - pph_start;
3440 }
3441 return needed;
3442}
3443
3444static FT_Error
3445IntRequestFontSize(PDC dc, PFONTGDI FontGDI, LONG lfWidth, LONG lfHeight)
3446{
3449 FT_Face face = FontGDI->SharedFace->Face;
3450 TT_OS2 *pOS2;
3451 TT_HoriHeader *pHori;
3452 FT_WinFNT_HeaderRec WinFNT;
3453 LONG Ascent, Descent, Sum, EmHeight, Width64;
3454
3455 lfWidth = abs(lfWidth);
3456 if (lfHeight == 0)
3457 {
3458 if (lfWidth == 0)
3459 {
3460 DPRINT("lfHeight and lfWidth are zero.\n");
3461 lfHeight = -16;
3462 }
3463 else
3464 {
3465 lfHeight = lfWidth;
3466 }
3467 }
3468
3469 if (lfHeight == -1)
3470 lfHeight = -2;
3471
3472 if (FontGDI->Magic == FONTGDI_MAGIC &&
3473 FontGDI->lfHeight == lfHeight &&
3474 FontGDI->lfWidth == lfWidth)
3475 {
3476 return 0; /* Cached */
3477 }
3478
3482
3483 if (!pOS2 || !pHori)
3484 {
3485 error = FT_Get_WinFNT_Header(face, &WinFNT);
3486 if (error)
3487 {
3488 DPRINT1("%s: Failed to request font size.\n", face->family_name);
3489 ASSERT(FALSE);
3490 return error;
3491 }
3492
3493 FontGDI->tmHeight = WinFNT.pixel_height;
3494 FontGDI->tmAscent = WinFNT.ascent;
3495 FontGDI->tmDescent = FontGDI->tmHeight - FontGDI->tmAscent;
3496 FontGDI->tmInternalLeading = WinFNT.internal_leading;
3497 FontGDI->Magic = FONTGDI_MAGIC;
3498 FontGDI->lfHeight = lfHeight;
3499 FontGDI->lfWidth = lfWidth;
3500 return 0;
3501 }
3502
3503 /*
3504 * NOTE: We cast TT_OS2.usWinAscent and TT_OS2.usWinDescent to signed FT_Short.
3505 * Why? See: https://docs.microsoft.com/en-us/typography/opentype/spec/os2#uswindescent
3506 *
3507 * > usWinDescent is "usually" a positive value ...
3508 *
3509 * We can read it as "not always". See CORE-14994.
3510 * See also: https://docs.microsoft.com/en-us/typography/opentype/spec/os2#fsselection
3511 */
3512#define FM_SEL_USE_TYPO_METRICS 0x80
3513 if (lfHeight > 0)
3514 {
3515 /* case (A): lfHeight is positive */
3516 Sum = (FT_Short)pOS2->usWinAscent + (FT_Short)pOS2->usWinDescent;
3517 if (Sum == 0 || (pOS2->fsSelection & FM_SEL_USE_TYPO_METRICS))
3518 {
3519 Ascent = pHori->Ascender;
3520 Descent = -pHori->Descender;
3521 Sum = Ascent + Descent;
3522 }
3523 else
3524 {
3525 Ascent = (FT_Short)pOS2->usWinAscent;
3526 Descent = (FT_Short)pOS2->usWinDescent;
3527 }
3528
3529 FontGDI->tmAscent = FT_MulDiv(lfHeight, Ascent, Sum);
3530 FontGDI->tmDescent = FT_MulDiv(lfHeight, Descent, Sum);
3531 FontGDI->tmHeight = FontGDI->tmAscent + FontGDI->tmDescent;
3532 FontGDI->tmInternalLeading = FontGDI->tmHeight - FT_MulDiv(lfHeight, face->units_per_EM, Sum);
3533 }
3534 else if (lfHeight < 0)
3535 {
3536 /* case (B): lfHeight is negative */
3538 {
3539 FontGDI->tmAscent = FT_MulDiv(-lfHeight, pHori->Ascender, face->units_per_EM);
3540 FontGDI->tmDescent = FT_MulDiv(-lfHeight, -pHori->Descender, face->units_per_EM);
3541 }
3542 else
3543 {
3544 FontGDI->tmAscent = FT_MulDiv(-lfHeight, (FT_Short)pOS2->usWinAscent, face->units_per_EM);
3545 FontGDI->tmDescent = FT_MulDiv(-lfHeight, (FT_Short)pOS2->usWinDescent, face->units_per_EM);
3546 }
3547 FontGDI->tmHeight = FontGDI->tmAscent + FontGDI->tmDescent;
3548 FontGDI->tmInternalLeading = FontGDI->tmHeight + lfHeight;
3549 }
3550#undef FM_SEL_USE_TYPO_METRICS
3551
3552 FontGDI->Magic = FONTGDI_MAGIC;
3553 FontGDI->lfHeight = lfHeight;
3554 FontGDI->lfWidth = lfWidth;
3555
3556 EmHeight = FontGDI->tmHeight - FontGDI->tmInternalLeading;
3557 EmHeight = max(EmHeight, 1);
3558 EmHeight = min(EmHeight, USHORT_MAX);
3559
3560#if 1
3561 /* I think this is wrong implementation but its test result is better. */
3562 if (lfWidth != 0)
3563 Width64 = FT_MulDiv(lfWidth, face->units_per_EM, pOS2->xAvgCharWidth) << 6;
3564 else
3565 Width64 = 0;
3566#else
3567 /* I think this is correct implementation but it is mismatching to the
3568 other metric functions. The test result is bad. */
3569 if (lfWidth != 0)
3570 Width64 = (FT_MulDiv(lfWidth, 96 * 5, 72 * 3) << 6); /* ??? FIXME */
3571 else
3572 Width64 = 0;
3573#endif
3574
3576 req.width = Width64;
3577 req.height = (EmHeight << 6);
3578 req.horiResolution = 0;
3579 req.vertResolution = 0;
3580 return FT_Request_Size(face, &req);
3581}
3582
3583BOOL
3586 PTEXTOBJ TextObj,
3587 PFONTGDI FontGDI,
3588 BOOL bDoLock)
3589{
3590 FT_Face face;
3591 INT error, n;
3592 FT_CharMap charmap, found;
3593 LOGFONTW *plf;
3594
3595 if (bDoLock)
3597
3598 face = FontGDI->SharedFace->Face;
3599 if (face->charmap == NULL)
3600 {
3601 DPRINT("WARNING: No charmap selected!\n");
3602 DPRINT("This font face has %d charmaps\n", face->num_charmaps);
3603
3604 found = NULL;
3605 for (n = 0; n < face->num_charmaps; n++)
3606 {
3607 charmap = face->charmaps[n];
3608 if (charmap->encoding == FT_ENCODING_UNICODE)
3609 {
3610 found = charmap;
3611 break;
3612 }
3613 }
3614 if (!found)
3615 {
3616 for (n = 0; n < face->num_charmaps; n++)
3617 {
3618 charmap = face->charmaps[n];
3619 if (charmap->platform_id == TT_PLATFORM_APPLE_UNICODE)
3620 {
3621 found = charmap;
3622 break;
3623 }
3624 }
3625 }
3626 if (!found)
3627 {
3628 for (n = 0; n < face->num_charmaps; n++)
3629 {
3630 charmap = face->charmaps[n];
3631 if (charmap->encoding == FT_ENCODING_MS_SYMBOL)
3632 {
3633 found = charmap;
3634 break;
3635 }
3636 }
3637 }
3638 if (!found && face->num_charmaps > 0)
3639 {
3640 found = face->charmaps[0];
3641 }
3642 if (!found)
3643 {
3644 DPRINT1("WARNING: Could not find desired charmap!\n");
3645 }
3646 else
3647 {
3648 DPRINT("Found charmap encoding: %i\n", found->encoding);
3649 error = FT_Set_Charmap(face, found);
3650 if (error)
3651 {
3652 DPRINT1("WARNING: Could not set the charmap!\n");
3653 }
3654 }
3655 }
3656
3657 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
3658
3659 error = IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
3660
3661 if (bDoLock)
3663
3664 if (error)
3665 {
3666 DPRINT1("Error in setting pixel sizes: %d\n", error);
3667 return FALSE;
3668 }
3669
3670 return TRUE;
3671}
3672
3673static inline FT_UInt FASTCALL
3675{
3676 FT_UInt ret;
3677
3678 if (glyph < 0x100) glyph += 0xf000;
3679 /* there are a number of old pre-Unicode "broken" TTFs, which
3680 do have symbols at U+00XX instead of U+f0XX */
3681 if (!(ret = FT_Get_Char_Index(ft_face, glyph)))
3682 ret = FT_Get_Char_Index(ft_face, glyph - 0xf000);
3683
3684 return ret;
3685}
3686
3687static inline FT_UInt FASTCALL
3689{
3690 FT_UInt ret;
3691
3692 if (face_has_symbol_charmap(ft_face))
3693 {
3694 ret = get_glyph_index_symbol(ft_face, glyph);
3695 if (ret != 0)
3696 return ret;
3697 }
3698
3699 return FT_Get_Char_Index(ft_face, glyph);
3700}
3701
3702static inline FT_UInt FASTCALL
3704{
3705 FT_UInt glyph_index;
3706 if (flags & indexed_flag)
3707 {
3708 glyph_index = code;
3709 }
3710 else
3711 {
3712 glyph_index = get_glyph_index(face, code);
3713 }
3714 return glyph_index;
3715}
3716
3717/*
3718 * Based on WineEngGetGlyphOutline
3719 *
3720 */
3721ULONG
3724 PDC dc,
3725 WCHAR wch,
3726 UINT iFormat,
3727 LPGLYPHMETRICS pgm,
3728 ULONG cjBuf,
3729 PVOID pvBuf,
3730 LPMAT2 pmat2,
3731 BOOL bIgnoreRotation)
3732{
3733 PDC_ATTR pdcattr;
3734 PTEXTOBJ TextObj;
3735 PFONTGDI FontGDI;
3736 HFONT hFont = 0;
3737 GLYPHMETRICS gm;
3738 ULONG Size;
3739 FT_Face ft_face;
3740 FT_UInt glyph_index;
3741 DWORD width, height, pitch, needed = 0;
3742 FT_Bitmap ft_bitmap;
3744 INT left, right, top = 0, bottom = 0;
3746 FLOATOBJ eM11, widthRatio, eTemp;
3747 FT_Matrix mat, transMat = identityMat;
3748 BOOL needsTransform = FALSE;
3749 INT orientation;
3750 LONG aveWidth;
3751 INT adv, lsb, bbx; /* These three hold to widths of the unrotated chars */
3752 OUTLINETEXTMETRICW *potm;
3753 XFORMOBJ xo;
3754 XFORML xform;
3755 LOGFONTW *plf;
3756
3757 DPRINT("%u, %08x, %p, %08lx, %p, %p\n", wch, iFormat, pgm,
3758 cjBuf, pvBuf, pmat2);
3759
3760 pdcattr = dc->pdcattr;
3761
3762 XFORMOBJ_vInit(&xo, &dc->pdcattr->mxWorldToDevice);
3763 XFORMOBJ_iGetXform(&xo, &xform);
3764 FLOATOBJ_SetFloat(&eM11, xform.eM11);
3765
3766 hFont = pdcattr->hlfntNew;
3767 TextObj = RealizeFontInit(hFont);
3768
3769 if (!TextObj)
3770 {
3772 return GDI_ERROR;
3773 }
3774 FontGDI = ObjToGDI(TextObj->Font, FONT);
3775 ft_face = FontGDI->SharedFace->Face;
3776
3777 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
3778 aveWidth = FT_IS_SCALABLE(ft_face) ? abs(plf->lfWidth) : 0;
3779 orientation = FT_IS_SCALABLE(ft_face) ? plf->lfOrientation : 0;
3780
3781 Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
3783 if (!potm)
3784 {
3786 TEXTOBJ_UnlockText(TextObj);
3787 return GDI_ERROR;
3788 }
3789 Size = IntGetOutlineTextMetrics(FontGDI, Size, potm);
3790 if (!Size)
3791 {
3792 /* FIXME: last error? */
3794 TEXTOBJ_UnlockText(TextObj);
3795 return GDI_ERROR;
3796 }
3797
3799 TextIntUpdateSize(dc, TextObj, FontGDI, FALSE);
3801 FT_Set_Transform(ft_face, &mat, NULL);
3802
3803 TEXTOBJ_UnlockText(TextObj);
3804
3805 glyph_index = get_glyph_index_flagged(ft_face, wch, GGO_GLYPH_INDEX, iFormat);
3806 iFormat &= ~GGO_GLYPH_INDEX;
3807
3808 if (orientation || (iFormat != GGO_METRICS && iFormat != GGO_BITMAP) || aveWidth || pmat2)
3809 load_flags |= FT_LOAD_NO_BITMAP;
3810
3811 if (iFormat & GGO_UNHINTED)
3812 {
3813 load_flags |= FT_LOAD_NO_HINTING;
3814 iFormat &= ~GGO_UNHINTED;
3815 }
3816
3817 error = FT_Load_Glyph(ft_face, glyph_index, load_flags);
3818 if (error)
3819 {
3820 DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
3822 if (potm) ExFreePoolWithTag(potm, GDITAG_TEXT);
3823 return GDI_ERROR;
3824 }
3826
3827 FLOATOBJ_Set1(&widthRatio);
3828 if (aveWidth && potm)
3829 {
3830 // widthRatio = aveWidth * eM11 / potm->otmTextMetrics.tmAveCharWidth
3831 FLOATOBJ_SetLong(&widthRatio, aveWidth);
3832 FLOATOBJ_Mul(&widthRatio, &eM11);
3834 }
3835
3836 //left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64;
3837 FLOATOBJ_SetLong(&eTemp, ft_face->glyph->metrics.horiBearingX);
3838 FLOATOBJ_Mul(&eTemp, &widthRatio);
3839 left = FLOATOBJ_GetLong(&eTemp) & -64;
3840
3841 //right = (INT)((ft_face->glyph->metrics.horiBearingX +
3842 // ft_face->glyph->metrics.width) * widthRatio + 63) & -64;
3843 FLOATOBJ_SetLong(&eTemp, ft_face->glyph->metrics.horiBearingX * ft_face->glyph->metrics.width);
3844 FLOATOBJ_Mul(&eTemp, &widthRatio);
3845 FLOATOBJ_AddLong(&eTemp, 63);
3846 right = FLOATOBJ_GetLong(&eTemp) & -64;
3847
3848 //adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6;
3849 FLOATOBJ_SetLong(&eTemp, ft_face->glyph->metrics.horiAdvance);
3850 FLOATOBJ_Mul(&eTemp, &widthRatio);
3851 FLOATOBJ_AddLong(&eTemp, 63);
3852 adv = FLOATOBJ_GetLong(&eTemp) >> 6;
3853
3854 lsb = left >> 6;
3855 bbx = (right - left) >> 6;
3856
3857 DPRINT("Advance = %d, lsb = %d, bbx = %d\n",adv, lsb, bbx);
3858
3860
3861 /* Width scaling transform */
3862 if (!FLOATOBJ_Equal1(&widthRatio))
3863 {
3864 FT_Matrix scaleMat;
3865
3866 eTemp = widthRatio;
3867 FLOATOBJ_MulLong(&eTemp, 1 << 16);
3868
3869 scaleMat.xx = FLOATOBJ_GetLong(&eTemp);
3870 scaleMat.xy = 0;
3871 scaleMat.yx = 0;
3872 scaleMat.yy = INT_TO_FIXED(1);
3873 FT_Matrix_Multiply(&scaleMat, &transMat);
3874 needsTransform = TRUE;
3875 }
3876
3877 /* World transform */
3878 {
3879 FT_Matrix ftmatrix;
3881
3882 /* Create a freetype matrix, by converting to 16.16 fixpoint format */
3883 IntMatrixFromMx(&ftmatrix, pmx);
3884
3885 if (memcmp(&ftmatrix, &identityMat, sizeof(identityMat)) != 0)
3886 {
3887 FT_Matrix_Multiply(&ftmatrix, &transMat);
3888 needsTransform = TRUE;
3889 }
3890 }
3891
3892 /* Rotation transform */
3893 if (orientation)
3894 {
3895 FT_Matrix rotationMat;
3896 DPRINT("Rotation Trans!\n");
3897 IntEscapeMatrix(&rotationMat, orientation);
3898 FT_Matrix_Multiply(&rotationMat, &transMat);
3899 needsTransform = TRUE;
3900 }
3901
3902 /* Extra transformation specified by caller */
3903 if (pmat2)
3904 {
3905 FT_Matrix extraMat;
3906 DPRINT("MAT2 Matrix Trans!\n");
3907 extraMat.xx = FT_FixedFromFIXED(pmat2->eM11);
3908 extraMat.xy = FT_FixedFromFIXED(pmat2->eM21);
3909 extraMat.yx = FT_FixedFromFIXED(pmat2->eM12);
3910 extraMat.yy = FT_FixedFromFIXED(pmat2->eM22);
3911 FT_Matrix_Multiply(&extraMat, &transMat);
3912 needsTransform = TRUE;
3913 }
3914
3915 if (potm) ExFreePoolWithTag(potm, GDITAG_TEXT); /* It looks like we are finished with potm ATM. */
3916
3917 if (!needsTransform)
3918 {
3919 DPRINT("No Need to be Transformed!\n");
3920 top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;
3921 bottom = (ft_face->glyph->metrics.horiBearingY -
3922 ft_face->glyph->metrics.height) & -64;
3923 gm.gmCellIncX = adv;
3924 gm.gmCellIncY = 0;
3925 }
3926 else
3927 {
3928 INT xc, yc;
3929 FT_Vector vec;
3930 for (xc = 0; xc < 2; xc++)
3931 {
3932 for (yc = 0; yc < 2; yc++)
3933 {
3934 vec.x = (ft_face->glyph->metrics.horiBearingX +
3935 xc * ft_face->glyph->metrics.width);
3936 vec.y = ft_face->glyph->metrics.horiBearingY -
3937 yc * ft_face->glyph->metrics.height;
3938 DPRINT("Vec %ld,%ld\n", vec.x, vec.y);
3939 FT_Vector_Transform(&vec, &transMat);
3940 if (xc == 0 && yc == 0)
3941 {
3942 left = right = vec.x;
3943 top = bottom = vec.y;
3944 }
3945 else
3946 {
3947 if (vec.x < left) left = vec.x;
3948 else if (vec.x > right) right = vec.x;
3949 if (vec.y < bottom) bottom = vec.y;
3950 else if (vec.y > top) top = vec.y;
3951 }
3952 }
3953 }
3954 left = left & -64;
3955 right = (right + 63) & -64;
3956 bottom = bottom & -64;
3957 top = (top + 63) & -64;
3958
3959 DPRINT("Transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
3960 vec.x = ft_face->glyph->metrics.horiAdvance;
3961 vec.y = 0;
3962 FT_Vector_Transform(&vec, &transMat);
3963 gm.gmCellIncX = (vec.x+63) >> 6;
3964 gm.gmCellIncY = -((vec.y+63) >> 6);
3965 }
3966 gm.gmBlackBoxX = (right - left) >> 6;
3967 gm.gmBlackBoxY = (top - bottom) >> 6;
3968 gm.gmptGlyphOrigin.x = left >> 6;
3969 gm.gmptGlyphOrigin.y = top >> 6;
3970
3971 DPRINT("CX %d CY %d BBX %u BBY %u GOX %d GOY %d\n",
3972 gm.gmCellIncX, gm.gmCellIncY,
3973 gm.gmBlackBoxX, gm.gmBlackBoxY,
3975
3977
3978
3979 if (iFormat == GGO_METRICS)
3980 {
3981 DPRINT("GGO_METRICS Exit!\n");
3982 *pgm = gm;
3983 return 1; /* FIXME */
3984 }
3985
3986 if (ft_face->glyph->format != ft_glyph_format_outline && iFormat != GGO_BITMAP)
3987 {
3988 DPRINT1("Loaded a bitmap\n");
3989 return GDI_ERROR;
3990 }
3991
3992 switch (iFormat)
3993 {
3994 case GGO_BITMAP:
3995 {
3996 width = gm.gmBlackBoxX;
3997 height = gm.gmBlackBoxY;
3998 pitch = ((width + 31) >> 5) << 2;
3999 needed = pitch * height;
4000
4001 if (!pvBuf || !cjBuf) break;
4002 if (!needed) return GDI_ERROR; /* empty glyph */
4003 if (needed > cjBuf)
4004 return GDI_ERROR;
4005
4006 switch (ft_face->glyph->format)
4007 {
4009 {
4010 BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
4011 INT w = min( pitch, (ft_face->glyph->bitmap.width + 7) >> 3 );
4012 INT h = min( height, ft_face->glyph->bitmap.rows );
4013 while (h--)
4014 {
4016 src += ft_face->glyph->bitmap.pitch;
4017 dst += pitch;
4018 }
4019 break;
4020 }
4021
4023 {
4024 ft_bitmap.width = width;
4025 ft_bitmap.rows = height;
4026 ft_bitmap.pitch = pitch;
4027 ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
4028 ft_bitmap.buffer = pvBuf;
4029
4031 if (needsTransform)
4032 {
4033 FT_Outline_Transform(&ft_face->glyph->outline, &transMat);
4034 }
4035 FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
4036 /* Note: FreeType will only set 'black' bits for us. */
4037 RtlZeroMemory(pvBuf, needed);
4038 FT_Outline_Get_Bitmap(g_FreeTypeLibrary, &ft_face->glyph->outline, &ft_bitmap);
4040 break;
4041 }
4042
4043 default:
4044 DPRINT1("Loaded glyph format %x\n", ft_face->glyph->format);
4045 return GDI_ERROR;
4046 }
4047
4048 break;
4049 }
4050
4051 case GGO_GRAY2_BITMAP:
4052 case GGO_GRAY4_BITMAP:
4053 case GGO_GRAY8_BITMAP:
4054 {
4055 unsigned int mult, row, col;
4056 BYTE *start, *ptr;
4057
4058 width = gm.gmBlackBoxX;
4059 height = gm.gmBlackBoxY;
4060 pitch = (width + 3) / 4 * 4;
4061 needed = pitch * height;
4062
4063 if (!pvBuf || !cjBuf) break;
4064 if (!needed) return GDI_ERROR; /* empty glyph */
4065 if (needed > cjBuf)
4066 return GDI_ERROR;
4067
4068 switch (ft_face->glyph->format)
4069 {
4071 {
4072 BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf;
4073 INT h = min( height, ft_face->glyph->bitmap.rows );
4074 INT x;
4075 while (h--)
4076 {
4077 for (x = 0; (UINT)x < pitch; x++)
4078 {
4079 if (x < ft_face->glyph->bitmap.width)
4080 dst[x] = (src[x / 8] & (1 << ( (7 - (x % 8))))) ? 0xff : 0;
4081 else
4082 dst[x] = 0;
4083 }
4084 src += ft_face->glyph->bitmap.pitch;
4085 dst += pitch;
4086 }
4087 break;
4088 }
4090 {
4091 ft_bitmap.width = width;
4092 ft_bitmap.rows = height;
4093 ft_bitmap.pitch = pitch;
4094 ft_bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
4095 ft_bitmap.buffer = pvBuf;
4096
4098 if (needsTransform)
4099 {
4100 FT_Outline_Transform(&ft_face->glyph->outline, &transMat);
4101 }
4102 FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
4103 RtlZeroMemory(ft_bitmap.buffer, cjBuf);
4104 FT_Outline_Get_Bitmap(g_FreeTypeLibrary, &ft_face->glyph->outline, &ft_bitmap);
4106
4108 mult = 4;
4109 else if (iFormat == GGO_GRAY4_BITMAP)
4110 mult = 16;
4111 else if (iFormat == GGO_GRAY8_BITMAP)
4112 mult = 64;
4113 else
4114 {
4115 return GDI_ERROR;
4116 }
4117
4118 start = pvBuf;
4119 for (row = 0; row < height; row++)
4120 {
4121 ptr = start;
4122 for (col = 0; col < width; col++, ptr++)
4123 {
4124 *ptr = (((int)*ptr) * mult + 128) / 256;
4125 }
4126 start += pitch;
4127 }
4128
4129 break;
4130 }
4131 default:
4132 DPRINT1("Loaded glyph format %x\n", ft_face->glyph->format);
4133 return GDI_ERROR;
4134 }
4135
4136 break;
4137 }
4138
4139 case GGO_NATIVE:
4140 {
4141 FT_Outline *outline = &ft_face->glyph->outline;
4142
4143 if (cjBuf == 0) pvBuf = NULL; /* This is okay, need cjBuf to allocate. */
4144
4146 if (needsTransform && pvBuf) FT_Outline_Transform(outline, &transMat);
4147
4149
4150 if (!pvBuf || !cjBuf)
4151 {
4153 break;
4154 }
4155 if (needed > cjBuf)
4156 {
4158 return GDI_ERROR;
4159 }
4162 break;
4163 }
4164
4165 case GGO_BEZIER:
4166 {
4167 FT_Outline *outline = &ft_face->glyph->outline;
4168 if (cjBuf == 0) pvBuf = NULL;
4169
4170 if (needsTransform && pvBuf)
4171 {
4173 FT_Outline_Transform(outline, &transMat);
4175 }
4177
4178 if (!pvBuf || !cjBuf)
4179 break;
4180 if (needed > cjBuf)
4181 return GDI_ERROR;
4182
4184 break;
4185 }
4186
4187 default:
4188 DPRINT1("Unsupported format %u\n", iFormat);
4189 return GDI_ERROR;
4190 }
4191
4192 DPRINT("ftGdiGetGlyphOutline END and needed %lu\n", needed);
4193
4194 if (gm.gmBlackBoxX == 0)
4195 gm.gmBlackBoxX = 1;
4196 if (gm.gmBlackBoxY == 0)
4197 gm.gmBlackBoxY = 1;
4198
4199 *pgm = gm;
4200 return needed;
4201}
4202
4203static FT_BitmapGlyph
4206{
4207 INT error;
4208 FT_GlyphSlot glyph;
4209 FT_BitmapGlyph realglyph;
4210
4212
4213 if (Cache->Hashed.Aspect.EmuBoldItalic)
4214 {
4215 error = FT_Load_Glyph(Cache->Hashed.Face, Cache->Hashed.GlyphIndex, FT_LOAD_NO_BITMAP);
4216 if (error)
4217 {
4218 DPRINT1("WARNING: Failed to load and render glyph! [index: %d]\n",
4219 Cache->Hashed.GlyphIndex);
4220 return NULL;
4221 }
4222
4223 glyph = Cache->Hashed.Face->glyph;
4224
4225 if (Cache->Hashed.Aspect.Emu.Bold)
4226 FT_GlyphSlot_Embolden(glyph);
4227 if (Cache->Hashed.Aspect.Emu.Italic)
4228 FT_GlyphSlot_Oblique(glyph);
4229 realglyph = IntGetBitmapGlyphNoCache(Cache->Hashed.Face, glyph, Cache->Hashed.Aspect.RenderMode);
4230 }
4231 else
4232 {
4233 Cache->dwHash = IntGetHash(&Cache->Hashed, sizeof(Cache->Hashed) / sizeof(DWORD));
4234
4235 realglyph = IntFindGlyphCache(Cache);
4236 if (realglyph)
4237 return realglyph;
4238
4239 error = FT_Load_Glyph(Cache->Hashed.Face, Cache->Hashed.GlyphIndex, FT_LOAD_DEFAULT);
4240 if (error)
4241 {
4242 DPRINT1("WARNING: Failed to load and render glyph! [index: %d]\n", Cache->Hashed.GlyphIndex);
4243 return NULL;
4244 }
4245
4246 glyph = Cache->Hashed.Face->glyph;
4247 realglyph = IntGetBitmapGlyphWithCache(Cache, glyph);
4248 }
4249
4250 if (!realglyph)
4251 DPRINT1("Failed to render glyph! [index: %d]\n", Cache->Hashed.GlyphIndex);
4252
4253 return realglyph;
4254}
4255
4256BOOL
4259 PTEXTOBJ TextObj,
4261 INT Count,
4262 ULONG MaxExtent,
4263 LPINT Fit,
4264 LPINT Dx,
4265 LPSIZE Size,
4266 FLONG fl)
4267{
4268 PFONTGDI FontGDI;
4269 FT_BitmapGlyph realglyph;
4270 INT glyph_index, i, previous, nTenthsOfDegrees;
4271 ULONGLONG TotalWidth64 = 0;
4272 LOGFONTW *plf;
4273 BOOL use_kerning, bVerticalWriting;
4274 LONG ascender, descender;
4276
4277 FontGDI = ObjToGDI(TextObj->Font, FONT);
4278
4279 Cache.Hashed.Face = FontGDI->SharedFace->Face;
4280 if (NULL != Fit)
4281 {
4282 *Fit = 0;
4283 }
4284
4285 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
4286 Cache.Hashed.lfHeight = plf->lfHeight;
4287 Cache.Hashed.lfWidth = plf->lfWidth;
4288 Cache.Hashed.Aspect.Emu.Bold = EMUBOLD_NEEDED(FontGDI->OriginalWeight, plf->lfWeight);
4289 Cache.Hashed.Aspect.Emu.Italic = (plf->lfItalic && !FontGDI->OriginalItalic);
4290
4291 // Check vertical writing (tategaki)
4292 nTenthsOfDegrees = IntNormalizeAngle(plf->lfEscapement - plf->lfOrientation);
4293 bVerticalWriting = ((nTenthsOfDegrees == 90 * 10) || (nTenthsOfDegrees == 270 * 10));
4294
4296 Cache.Hashed.Aspect.RenderMode = (BYTE)IntGetFontRenderMode(plf);
4297 else
4298 Cache.Hashed.Aspect.RenderMode = (BYTE)FT_RENDER_MODE_MONO;
4299
4300 // NOTE: GetTextExtentPoint32 simply ignores lfEscapement and XFORM.
4302 TextIntUpdateSize(dc, TextObj, FontGDI, FALSE);
4303 Cache.Hashed.matTransform = identityMat;
4304 FT_Set_Transform(Cache.Hashed.Face, NULL, NULL);
4305
4306 use_kerning = FT_HAS_KERNING(Cache.Hashed.Face);
4307 previous = 0;
4308
4309 for (i = 0; i < Count; i++)
4310 {
4311 glyph_index = get_glyph_index_flagged(Cache.Hashed.Face, *String, GTEF_INDICES, fl);
4312 Cache.Hashed.GlyphIndex = glyph_index;
4313
4314 realglyph = IntGetRealGlyph(&Cache);
4315 if (!realglyph)
4316 break;
4317
4318 /* Retrieve kerning distance */
4319 if (use_kerning && previous && glyph_index)
4320 {
4321 FT_Vector delta;
4322 FT_Get_Kerning(Cache.Hashed.Face, previous, glyph_index, 0, &delta);
4323 TotalWidth64 += delta.x;
4324 }
4325
4326 TotalWidth64 += realglyph->root.advance.x >> 10;
4327
4328 if (((TotalWidth64 + 32) >> 6) <= MaxExtent && NULL != Fit)
4329 {
4330 *Fit = i + 1;
4331 }
4332 if (NULL != Dx)
4333 {
4334 Dx[i] = (TotalWidth64 + 32) >> 6;
4335 }
4336
4337 /* Bold and italic do not use the cache */
4338 if (Cache.Hashed.Aspect.EmuBoldItalic)
4339 {
4340 FT_Done_Glyph((FT_Glyph)realglyph);
4341 }
4342
4343 previous = glyph_index;
4344 String++;
4345 }
4346 ASSERT(FontGDI->Magic == FONTGDI_MAGIC);
4347 ascender = FontGDI->tmAscent; /* Units above baseline */
4348 descender = FontGDI->tmDescent; /* Units below baseline */
4350
4351 if (bVerticalWriting)
4352 {
4353 Size->cx = ascender + descender;
4354 Size->cy = (TotalWidth64 + 32) >> 6;
4355 }
4356 else
4357 {
4358 Size->cx = (TotalWidth64 + 32) >> 6;
4359 Size->cy = ascender + descender;
4360 }
4361
4362 return TRUE;
4363}
4364
4365
4366INT
4369 PDC Dc,
4370 LPFONTSIGNATURE lpSig,
4371 DWORD dwFlags)
4372{
4373 PDC_ATTR pdcattr;
4374 UINT Ret = DEFAULT_CHARSET;
4375 INT i;
4376 HFONT hFont;
4377 PTEXTOBJ TextObj;
4378 PFONTGDI FontGdi;
4380 TT_OS2 *pOS2;
4381 FT_Face Face;
4382 CHARSETINFO csi;
4383 DWORD cp, fs0;
4384 USHORT usACP, usOEM;
4385
4386 pdcattr = Dc->pdcattr;
4387 hFont = pdcattr->hlfntNew;
4388 TextObj = RealizeFontInit(hFont);
4389
4390 if (!TextObj)
4391 {
4393 return Ret;
4394 }
4395 FontGdi = ObjToGDI(TextObj->Font, FONT);
4396 Face = FontGdi->SharedFace->Face;
4397 TEXTOBJ_UnlockText(TextObj);
4398
4399 memset(&fs, 0, sizeof(FONTSIGNATURE));
4401 pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
4402 if (NULL != pOS2)
4403 {
4404 fs.fsCsb[0] = pOS2->ulCodePageRange1;
4405 fs.fsCsb[1] = pOS2->ulCodePageRange2;
4406 fs.fsUsb[0] = pOS2->ulUnicodeRange1;
4407 fs.fsUsb[1] = pOS2->ulUnicodeRange2;
4408 fs.fsUsb[2] = pOS2->ulUnicodeRange3;
4409 fs.fsUsb[3] = pOS2->ulUnicodeRange4;
4410 if (pOS2->version == 0)
4411 {
4412 FT_UInt dummy;
4413
4414 if (FT_Get_First_Char( Face, &dummy ) < 0x100)
4415 fs.fsCsb[0] |= FS_LATIN1;
4416 else
4417 fs.fsCsb[0] |= FS_SYMBOL;
4418 }
4419 }
4420 pOS2 = NULL;
4422 DPRINT("Csb 1=%x 0=%x\n", fs.fsCsb[1],fs.fsCsb[0]);
4423 if (fs.fsCsb[0] == 0)
4424 { /* Let's see if we can find any interesting cmaps */
4425 for (i = 0; i < Face->num_charmaps; i++)
4426 {
4427 switch (Face->charmaps[i]->encoding)
4428 {
4429 case FT_ENCODING_UNICODE:
4430 case FT_ENCODING_APPLE_ROMAN:
4431 fs.fsCsb[0] |= FS_LATIN1;
4432 break;
4433 case FT_ENCODING_MS_SYMBOL:
4434 fs.fsCsb[0] |= FS_SYMBOL;
4435 break;
4436 default:
4437 break;
4438 }
4439 }
4440 }
4441 if (lpSig)
4442 {
4443 RtlCopyMemory(lpSig, &fs, sizeof(FONTSIGNATURE));
4444 }
4445
4446 RtlGetDefaultCodePage(&usACP, &usOEM);
4447 cp = usACP;
4448
4450 if (csi.fs.fsCsb[0] & fs.fsCsb[0])
4451 {
4452 DPRINT("Hit 1\n");
4453 Ret = csi.ciCharset;
4454 goto Exit;
4455 }
4456
4457 for (i = 0; i < MAXTCIINDEX; i++)
4458 {
4459 fs0 = 1L << i;
4460 if (fs.fsCsb[0] & fs0)
4461 {
4462 if (IntTranslateCharsetInfo(&fs0, &csi, TCI_SRCFONTSIG))
4463 {
4464 // *cp = csi.ciACP;
4465 DPRINT("Hit 2\n");
4466 Ret = csi.ciCharset;
4467 goto Exit;
4468 }
4469 else
4470 DPRINT1("TCI failing on %x\n", fs0);
4471 }
4472 }
4473Exit:
4474 DPRINT("CharSet %u CodePage %u\n", csi.ciCharset, csi.ciACP);
4475 return (MAKELONG(csi.ciACP, csi.ciCharset));
4476}
4477
4478
4479DWORD
4482{
4483 DWORD size = 0;
4484 DWORD num_ranges = 0;
4485 FT_Face face = Font->SharedFace->Face;
4486
4487 if (face->charmap == NULL)
4488 {
4489 DPRINT1("FIXME: No charmap selected! This is a BUG!\n");
4490 return 0;
4491 }
4492
4493 if (face->charmap->encoding == FT_ENCODING_UNICODE)
4494 {
4495 FT_UInt glyph_code = 0;
4496 FT_ULong char_code, char_code_prev;
4497
4498 char_code_prev = char_code = FT_Get_First_Char(face, &glyph_code);
4499
4500 DPRINT("Face encoding FT_ENCODING_UNICODE, number of glyphs %ld, first glyph %u, first char %04lx\n",
4501 face->num_glyphs, glyph_code, char_code);
4502
4503 if (!glyph_code) return 0;
4504
4505 if (glyphset)
4506 {
4507 glyphset->ranges[0].wcLow = (USHORT)char_code;
4508 glyphset->ranges[0].cGlyphs = 0;
4509 glyphset->cGlyphsSupported = 0;
4510 }
4511
4512 num_ranges = 1;
4513 while (glyph_code)
4514 {
4515 if (char_code < char_code_prev)
4516 {
4517 DPRINT1("Expected increasing char code from FT_Get_Next_Char\n");
4518 return 0;
4519 }
4520 if (char_code - char_code_prev > 1)
4521 {
4522 num_ranges++;
4523 if (glyphset)
4524 {
4525 glyphset->ranges[num_ranges - 1].wcLow = (USHORT)char_code;
4526 glyphset->ranges[num_ranges - 1].cGlyphs = 1;
4527 glyphset->cGlyphsSupported++;
4528 }
4529 }
4530 else if (glyphset)
4531 {
4532 glyphset->ranges[num_ranges - 1].cGlyphs++;
4533 glyphset->cGlyphsSupported++;
4534 }
4535 char_code_prev = char_code;
4536 char_code = FT_Get_Next_Char(face, char_code, &glyph_code);
4537 }
4538 }
4539 else
4540 DPRINT1("Encoding %i not supported\n", face->charmap->encoding);
4541
4542 size = sizeof(GLYPHSET) + sizeof(WCRANGE) * (num_ranges - 1);
4543 if (glyphset)
4544 {
4545 glyphset->cbThis = size;
4546 glyphset->cRanges = num_ranges;
4547 glyphset->flAccel = 0;
4548 }
4549 return size;
4550}
4551
4552
4553BOOL
4556 HDC hDC,
4557 PTMW_INTERNAL ptmwi)
4558{
4559 PDC dc;
4560 PDC_ATTR pdcattr;
4561 PTEXTOBJ TextObj;
4562 PFONTGDI FontGDI;
4563 FT_Face Face;
4564 TT_OS2 *pOS2;
4565 TT_HoriHeader *pHori;
4567 ULONG Error;
4569 LOGFONTW *plf;
4570
4571 if (!ptmwi)
4572 {
4574 return FALSE;
4575 }
4576 RtlZeroMemory(ptmwi, sizeof(TMW_INTERNAL));
4577
4578 if (!(dc = DC_LockDc(hDC)))
4579 {
4581 return FALSE;
4582 }
4583 pdcattr = dc->pdcattr;
4584 TextObj = RealizeFontInit(pdcattr->hlfntNew);
4585 if (NULL != TextObj)
4586 {
4587 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
4588 FontGDI = ObjToGDI(TextObj->Font, FONT);
4589
4590 Face = FontGDI->SharedFace->Face;
4591
4592 // NOTE: GetTextMetrics simply ignores lfEscapement and XFORM.
4594 Error = IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
4595 FT_Set_Transform(Face, NULL, NULL);
4596
4598
4599 if (0 != Error)
4600 {
4601 DPRINT1("Error in setting pixel sizes: %u\n", Error);
4603 }
4604 else
4605 {
4607
4609 pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
4610 if (NULL == pOS2)
4611 {
4612 DPRINT1("Can't find OS/2 table - not TT font?\n");
4614 }
4615
4616 pHori = FT_Get_Sfnt_Table(Face, ft_sfnt_hhea);
4617 if (NULL == pHori)
4618 {
4619 DPRINT1("Can't find HHEA table - not TT font?\n");
4621 }
4622
4623 Error = FT_Get_WinFNT_Header(Face, &Win);
4624
4625 if (NT_SUCCESS(Status) || !Error)
4626 {
4627 FillTM(&ptmwi->TextMetric, FontGDI, pOS2, pHori, !Error ? &Win : 0);
4628
4629 /* FIXME: Fill Diff member */
4630 }
4631
4633 }
4634 TEXTOBJ_UnlockText(TextObj);
4635 }
4636 else
4637 {
4639 }
4640 DC_UnlockDc(dc);
4641
4642 if (!NT_SUCCESS(Status))
4643 {
4645 return FALSE;
4646 }
4647 return TRUE;
4648}
4649
4650DWORD
4653 PFONTGDI FontGdi,
4654 DWORD Table,
4655 DWORD Offset,
4656 PVOID Buffer,
4657 DWORD Size)
4658{
4660 FT_Face Face = FontGdi->SharedFace->Face;
4661
4663
4664 if (FT_IS_SFNT(Face))
4665 {
4666 if (Table)
4667 Table = Table >> 24 | Table << 24 | (Table >> 8 & 0xFF00) |
4668 (Table << 8 & 0xFF0000);
4669
4670 if (!Buffer) Size = 0;
4671
4672 if (Buffer && Size)
4673 {
4675 FT_ULong Needed = 0;
4676
4677 Error = FT_Load_Sfnt_Table(Face, Table, Offset, NULL, &Needed);
4678
4679 if ( !Error && Needed < Size) Size = Needed;
4680 }
4681 if (!FT_Load_Sfnt_Table(Face, Table, Offset, Buffer, &Size))
4682 Result = Size;
4683 }
4684
4686
4687 return Result;
4688}
4689
4690#define GOT_PENALTY(name, value) Penalty += (value)
4691
4692// NOTE: See Table 1. of https://msdn.microsoft.com/en-us/library/ms969909.aspx
4693static UINT
4694GetFontPenalty(const LOGFONTW * LogFont,
4695 const OUTLINETEXTMETRICW * Otm,
4696 const char * style_name)
4697{
4698 ULONG Penalty = 0;
4699 BYTE Byte;
4700 LONG Long;
4701 BOOL fNeedScaling = FALSE;
4702 const BYTE UserCharSet = CharSetFromLangID(gusLanguageID);
4703 const TEXTMETRICW * TM = &Otm->otmTextMetrics;
4704 WCHAR* ActualNameW;
4705
4706 ASSERT(Otm);
4707 ASSERT(LogFont);
4708
4709 /* FIXME: IntSizeSynth Penalty 20 */
4710 /* FIXME: SmallPenalty Penalty 1 */
4711 /* FIXME: FaceNameSubst Penalty 500 */
4712
4713 Byte = LogFont->lfCharSet;
4714
4715 if (Byte != TM->tmCharSet)
4716 {
4718 {
4719 /* CharSet Penalty 65000 */
4720 /* Requested charset does not match the candidate's. */
4721 GOT_PENALTY("CharSet", 65000);
4722 }
4723 else
4724 {
4725 if (UserCharSet != TM->tmCharSet)
4726 {
4727 /* UNDOCUMENTED: Not user language */
4728 GOT_PENALTY("UNDOCUMENTED:NotUserLanguage", 100);
4729
4730 if (ANSI_CHARSET != TM->tmCharSet)
4731 {
4732 /* UNDOCUMENTED: Not ANSI charset */
4733 GOT_PENALTY("UNDOCUMENTED:NotAnsiCharSet", 100);
4734 }
4735 }
4736 }
4737 }
4738
4739 Byte = LogFont->lfOutPrecision;
4740 switch (Byte)
4741 {
4742 case OUT_DEFAULT_PRECIS:
4743 /* nothing to do */
4744 break;
4745 case OUT_DEVICE_PRECIS:
4746 if (!(TM->tmPitchAndFamily & TMPF_DEVICE) ||
4748 {
4749 /* OutputPrecision Penalty 19000 */
4750 /* Requested OUT_STROKE_PRECIS, but the device can't do it
4751 or the candidate is not a vector font. */
4752 GOT_PENALTY("OutputPrecision", 19000);
4753 }
4754 break;
4755 default:
4757 {
4758 /* OutputPrecision Penalty 19000 */
4759 /* Or OUT_STROKE_PRECIS not requested, and the candidate
4760 is a vector font that requires GDI support. */
4761 GOT_PENALTY("OutputPrecision", 19000);
4762 }
4763 break;
4764 }
4765
4766 Byte = (LogFont->lfPitchAndFamily & 0x0F);
4767 if (Byte == DEFAULT_PITCH)
4769 if (Byte == FIXED_PITCH)
4770 {
4772 {
4773 /* FixedPitch Penalty 15000 */
4774 /* Requested a fixed pitch font, but the candidate is a
4775 variable pitch font. */
4776 GOT_PENALTY("FixedPitch", 15000);
4777 }
4778 }
4779 if (Byte == VARIABLE_PITCH)
4780 {
4782 {
4783 /* PitchVariable Penalty 350 */
4784 /* Requested a variable pitch font, but the candidate is not a
4785 variable pitch font. */
4786 GOT_PENALTY("PitchVariable", 350);
4787 }
4788 }
4789
4790 Byte = (LogFont->lfPitchAndFamily & 0x0F);
4791 if (Byte == DEFAULT_PITCH)
4792 {
4794 {
4795 /* DefaultPitchFixed Penalty 1 */
4796 /* Requested DEFAULT_PITCH, but the candidate is fixed pitch. */
4797 GOT_PENALTY("DefaultPitchFixed", 1);
4798 }
4799 }
4800
4801 ActualNameW = (WCHAR*)((ULONG_PTR)Otm + (ULONG_PTR)Otm->otmpFamilyName);
4802
4803 if (LogFont->lfFaceName[0] != UNICODE_NULL)
4804 {
4805 BOOL Found = FALSE;
4806
4807 /* localized family name */
4808 if (!Found)
4809 {
4810 Found = (_wcsicmp(LogFont->lfFaceName, ActualNameW) == 0);
4811 }
4812 /* localized full name */
4813 if (!Found)
4814 {
4815 ActualNameW = (WCHAR*)((ULONG_PTR)Otm + (ULONG_PTR)Otm->otmpFaceName);
4816 Found = (_wcsicmp(LogFont->lfFaceName, ActualNameW) == 0);
4817 }
4818 if (!Found)
4819 {
4820 /* FaceName Penalty 10000 */
4821 /* Requested a face name, but the candidate's face name
4822 does not match. */
4823 GOT_PENALTY("FaceName", 10000);
4824 }
4825 }
4826
4827 Byte = (LogFont->lfPitchAndFamily & 0xF0);
4828 if (Byte != FF_DONTCARE)
4829 {
4830 if (Byte != (TM->tmPitchAndFamily & 0xF0))
4831 {
4832 /* Family Penalty 9000 */
4833 /* Requested a family, but the candidate's family is different. */
4834 GOT_PENALTY("Family", 9000);
4835 }
4836 }
4837
4838 if ((TM->tmPitchAndFamily & 0xF0) == FF_DONTCARE)
4839 {
4840 /* FamilyUnknown Penalty 8000 */
4841 /* Requested a family, but the candidate has no family. */
4842 GOT_PENALTY("FamilyUnknown", 8000);
4843 }
4844
4845 /* Is the candidate a non-vector font? */
4847 {
4848 /* Is lfHeight specified? */
4849 if (LogFont->lfHeight != 0)
4850 {
4851 if (labs(LogFont->lfHeight) < TM->tmHeight)
4852 {
4853 /* HeightBigger Penalty 600 */
4854 /* The candidate is a nonvector font and is bigger than the
4855 requested height. */
4856 GOT_PENALTY("HeightBigger", 600);
4857 /* HeightBiggerDifference Penalty 150 */
4858 /* The candidate is a raster font and is larger than the
4859 requested height. Penalty * height difference */
4860 GOT_PENALTY("HeightBiggerDifference", 150 * labs(TM->tmHeight - labs(LogFont->lfHeight)));
4861
4862 fNeedScaling = TRUE;
4863 }
4864 if (TM->tmHeight < labs(LogFont->lfHeight))
4865 {
4866 /* HeightSmaller Penalty 150 */
4867 /* The candidate is a raster font and is smaller than the
4868 requested height. Penalty * height difference */
4869 GOT_PENALTY("HeightSmaller", 150 * labs(TM->tmHeight - labs(LogFont->lfHeight)));
4870
4871 fNeedScaling = TRUE;
4872 }
4873 }
4874 }
4875
4876 switch (LogFont->lfPitchAndFamily & 0xF0)
4877 {
4878 case FF_ROMAN: case FF_MODERN: case FF_SWISS:
4879 switch (TM->tmPitchAndFamily & 0xF0)
4880 {
4881 case FF_DECORATIVE: case FF_SCRIPT:
4882 /* FamilyUnlikely Penalty 50 */
4883 /* Requested a roman/modern/swiss family, but the
4884 candidate is decorative/script. */
4885 GOT_PENALTY("FamilyUnlikely", 50);
4886 break;
4887 default:
4888 break;
4889 }
4890 break;
4891 case FF_DECORATIVE: case FF_SCRIPT:
4892 switch (TM->tmPitchAndFamily & 0xF0)
4893 {
4894 case FF_ROMAN: case FF_MODERN: case FF_SWISS:
4895 /* FamilyUnlikely Penalty 50 */
4896 /* Or requested decorative/script, and the candidate is
4897 roman/modern/swiss. */
4898 GOT_PENALTY("FamilyUnlikely", 50);
4899 break;
4900 default:
4901 break;
4902 }
4903 default:
4904 break;
4905 }
4906
4907 if (LogFont->lfWidth != 0)
4908 {
4909 if (LogFont->lfWidth != TM->tmAveCharWidth)
4910 {
4911 /* Width Penalty 50 */
4912 /* Requested a nonzero width, but the candidate's width
4913 doesn't match. Penalty * width difference */
4914 GOT_PENALTY("Width", 50 * labs(LogFont->lfWidth - TM->tmAveCharWidth));
4915
4917 fNeedScaling = TRUE;
4918 }
4919 }
4920
4921 if (fNeedScaling)
4922 {
4923 /* SizeSynth Penalty 50 */
4924 /* The candidate is a raster font that needs scaling by GDI. */
4925 GOT_PENALTY("SizeSynth", 50);
4926 }
4927
4928 if (!LogFont->lfItalic && TM->tmItalic)
4929 {
4930 /* Italic Penalty 4 */
4931 /* Requested font and candidate font do not agree on italic status,
4932 and the desired result cannot be simulated. */
4933 /* Adjusted to 40 to satisfy (Oblique Penalty > Book Penalty). */
4934 GOT_PENALTY("Italic", 40);
4935 }
4936 else if (LogFont->lfItalic && !TM->tmItalic)
4937 {
4938 /* ItalicSim Penalty 1 */
4939 /* Requested italic font but the candidate is not italic,
4940 although italics can be simulated. */
4941 GOT_PENALTY("ItalicSim", 1);
4942 }
4943
4944 if (LogFont->lfOutPrecision == OUT_TT_PRECIS)
4945 {
4946 if (!(TM->tmPitchAndFamily & TMPF_TRUETYPE))
4947 {
4948 /* NotTrueType Penalty 4 */
4949 /* Requested OUT_TT_PRECIS, but the candidate is not a
4950 TrueType font. */
4951 GOT_PENALTY("NotTrueType", 4);
4952 }
4953 }
4954
4955 Long = LogFont->lfWeight;
4956 if (LogFont->lfWeight == FW_DONTCARE)
4957 Long = FW_NORMAL;
4958 if (Long != TM->tmWeight)
4959 {
4960 /* Weight Penalty 3 */
4961 /* The candidate's weight does not match the requested weight.
4962 Penalty * (weight difference/10) */
4963 GOT_PENALTY("Weight", 3 * (labs(Long - TM->tmWeight) / 10));
4964 }
4965
4966 if (!LogFont->lfUnderline && TM->tmUnderlined)
4967 {
4968 /* Underline Penalty 3 */
4969 /* Requested font has no underline, but the candidate is
4970 underlined. */
4971 GOT_PENALTY("Underline", 3);
4972 }
4973
4974 if (!LogFont->lfStrikeOut && TM->tmStruckOut)
4975 {
4976 /* StrikeOut Penalty 3 */
4977 /* Requested font has no strike-out, but the candidate is
4978 struck out. */
4979 GOT_PENALTY("StrikeOut", 3);
4980 }
4981
4982 /* Is the candidate a non-vector font? */
4984 {
4985 if (LogFont->lfHeight != 0 && TM->tmHeight < LogFont->lfHeight)
4986 {
4987 /* VectorHeightSmaller Penalty 2 */
4988 /* Candidate is a vector font that is smaller than the
4989 requested height. Penalty * height difference */
4990 GOT_PENALTY("VectorHeightSmaller", 2 * labs(TM->tmHeight - LogFont->lfHeight));
4991 }
4992 if (LogFont->lfHeight != 0 && TM->tmHeight > LogFont->lfHeight)
4993 {
4994 /* VectorHeightBigger Penalty 1 */
4995 /* Candidate is a vector font that is bigger than the
4996 requested height. Penalty * height difference */
4997 GOT_PENALTY("VectorHeightBigger", 1 * labs(TM->tmHeight - LogFont->lfHeight));
4998 }
4999 }
5000
5001 if (!(TM->tmPitchAndFamily & TMPF_DEVICE))
5002 {
5003 /* DeviceFavor Penalty 2 */
5004 /* Extra penalty for all nondevice fonts. */
5005 GOT_PENALTY("DeviceFavor", 2);
5006 }
5007
5008 if (TM->tmAveCharWidth >= 5 && TM->tmHeight >= 5)
5009 {
5010 if (TM->tmAveCharWidth / TM->tmHeight >= 3)
5011 {
5012 /* Aspect Penalty 30 */
5013 /* The aspect rate is >= 3. It seems like a bad font. */
5014 GOT_PENALTY("Aspect", ((TM->tmAveCharWidth / TM->tmHeight) - 2) * 30);
5015 }
5016 else if (TM->tmHeight / TM->tmAveCharWidth >= 3)
5017 {
5018 /* Aspect Penalty 30 */
5019 /* The aspect rate is >= 3. It seems like a bad font. */
5020 GOT_PENALTY("Aspect", ((TM->tmHeight / TM->tmAveCharWidth) - 2) * 30);
5021 }
5022 }
5023
5024 if (Penalty < 200)
5025 {
5026 DPRINT("WARNING: Penalty:%ld < 200: RequestedNameW:%ls, "
5027 "ActualNameW:%ls, lfCharSet:%d, lfWeight:%ld, "
5028 "tmCharSet:%d, tmWeight:%ld\n",
5029 Penalty, LogFont->lfFaceName, ActualNameW,
5030 LogFont->lfCharSet, LogFont->lfWeight,
5031 TM->tmCharSet, TM->tmWeight);
5032 }
5033
5034 return Penalty; /* success */
5035}
5036
5037#undef GOT_PENALTY
5038
5039static __inline VOID
5040FindBestFontFromList(FONTOBJ **FontObj, ULONG *MatchPenalty,
5041 const LOGFONTW *LogFont,
5042 const PLIST_ENTRY Head)
5043{
5044 ULONG Penalty;
5046 PFONT_ENTRY CurrentEntry;
5047 FONTGDI *FontGDI;
5048 OUTLINETEXTMETRICW *Otm = NULL;
5049 UINT OtmSize, OldOtmSize = 0;
5050 FT_Face Face;
5051
5052 ASSERT(FontObj);
5053 ASSERT(MatchPenalty);
5054 ASSERT(LogFont);
5055 ASSERT(Head);
5056
5057 /* Start with a pretty big buffer */
5058 OldOtmSize = 0x200;
5059 Otm = ExAllocatePoolWithTag(PagedPool, OldOtmSize, GDITAG_TEXT);
5060
5061 /* get the FontObj of lowest penalty */
5062 for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
5063 {
5064 CurrentEntry = CONTAINING_RECORD(Entry, FONT_ENTRY, ListEntry);
5065
5066 FontGDI = CurrentEntry->Font;
5067 ASSERT(FontGDI);
5068 Face = FontGDI->SharedFace->Face;
5069
5070 /* get text metrics */
5071 OtmSize = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
5072 if (OtmSize > OldOtmSize)
5073 {
5074 if (Otm)
5077 }
5078
5079 /* update FontObj if lowest penalty */
5080 if (Otm)
5081 {
5083 IntRequestFontSize(NULL, FontGDI, LogFont->lfWidth, LogFont->lfHeight);
5085
5086 OtmSize = IntGetOutlineTextMetrics(FontGDI, OtmSize, Otm);
5087 if (!OtmSize)
5088 continue;
5089
5090 OldOtmSize = OtmSize;
5091
5092 Penalty = GetFontPenalty(LogFont, Otm, Face->style_name);
5093 if (*MatchPenalty == 0xFFFFFFFF || Penalty < *MatchPenalty)
5094 {
5095 *FontObj = GDIToObj(FontGDI, FONT);
5096 *MatchPenalty = Penalty;
5097 }
5098 }
5099 }
5100
5101 if (Otm)
5103}
5104
5105static
5106VOID
5109{
5110 PS_FontInfoRec psfInfo;
5111 FT_ULong tmp_size = 0;
5112 FT_Face Face = Font->SharedFace->Face;
5113
5116
5117 if (FT_HAS_MULTIPLE_MASTERS(Face))
5118 Font->FontObj.flFontType |= FO_MULTIPLEMASTER;
5119 if (FT_HAS_VERTICAL(Face))
5120 Font->FontObj.flFontType |= FO_VERT_FACE;
5121 if (!FT_IS_SCALABLE(Face))
5122 Font->FontObj.flFontType |= FO_TYPE_RASTER;
5123 if (FT_IS_SFNT(Face))
5124 {
5125 Font->FontObj.flFontType |= FO_TYPE_TRUETYPE;
5127 Font->FontObj.flFontType |= FO_POSTSCRIPT;
5128 }
5129 if (!FT_Get_PS_Font_Info(Face, &psfInfo ))
5130 {
5131 Font->FontObj.flFontType |= FO_POSTSCRIPT;
5132 }
5133 /* Check for the presence of the 'CFF ' table to check if the font is Type1 */
5134 if (!FT_Load_Sfnt_Table(Face, TTAG_CFF, 0, NULL, &tmp_size))
5135 {
5136 Font->FontObj.flFontType |= (FO_CFF|FO_POSTSCRIPT);
5137 }
5138
5140}
5141
5142static BOOL
5144{
5147
5149 Status = IntGetFontLocalizedName(&Name2, SharedFace, NameID, LangID);
5150
5151 if (NT_SUCCESS(Status))
5152 {
5153 if (RtlCompareUnicodeString(Name1, &Name2, TRUE) == 0)
5154 {
5156 return TRUE;
5157 }
5158
5160 }
5161
5162 return FALSE;
5163}
5164
5165static BOOL
5166MatchFontNames(PSHARED_FACE SharedFace, LPCWSTR lfFaceName)
5167{
5168 UNICODE_STRING Name1;
5169
5170 if (lfFaceName[0] == UNICODE_NULL)
5171 return FALSE;
5172
5173 RtlInitUnicodeString(&Name1, lfFaceName);
5174
5175 if (MatchFontName(SharedFace, &Name1, TT_NAME_ID_FONT_FAMILY, LANG_ENGLISH) ||
5176 MatchFontName(SharedFace, &Name1, TT_NAME_ID_FULL_NAME, LANG_ENGLISH))
5177 {
5178 return TRUE;
5179 }
5181 {
5182 if (MatchFontName(SharedFace, &Name1, TT_NAME_ID_FONT_FAMILY, gusLanguageID) ||
5183 MatchFontName(SharedFace, &Name1, TT_NAME_ID_FULL_NAME, gusLanguageID))
5184 {
5185 return TRUE;
5186 }
5187 }
5188 return FALSE;
5189}
5190
5193TextIntRealizeFont(HFONT FontHandle, PTEXTOBJ pTextObj)
5194{
5196 PTEXTOBJ TextObj;
5197 PPROCESSINFO Win32Process;
5198 ULONG MatchPenalty;
5199 LOGFONTW *pLogFont;
5200 LOGFONTW SubstitutedLogFont;
5201
5202 if (!pTextObj)
5203 {
5204 TextObj = TEXTOBJ_LockText(FontHandle);
5205 if (NULL == TextObj)
5206 {
5207 return STATUS_INVALID_HANDLE;
5208 }
5209
5210 if (TextObj->fl & TEXTOBJECT_INIT)
5211 {
5212 TEXTOBJ_UnlockText(TextObj);
5213 return STATUS_SUCCESS;
5214 }
5215 }
5216 else
5217 {
5218 TextObj = pTextObj;
5219 }
5220
5221 pLogFont = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
5222
5223 /* substitute */
5224 SubstitutedLogFont = *pLogFont;
5225 DPRINT("Font '%S,%u' is substituted by: ", pLogFont->lfFaceName, pLogFont->lfCharSet);
5226 SubstituteFontRecurse(&SubstitutedLogFont);
5227 DPRINT("'%S,%u'.\n", SubstitutedLogFont.lfFaceName, SubstitutedLogFont.lfCharSet);
5228
5229 MatchPenalty = 0xFFFFFFFF;
5230 TextObj->Font = NULL;
5231
5232 Win32Process = PsGetCurrentProcessWin32Process();
5233
5234 /* Search private fonts */
5235 IntLockProcessPrivateFonts(Win32Process);
5236 FindBestFontFromList(&TextObj->Font, &MatchPenalty, &SubstitutedLogFont,
5237 &Win32Process->PrivateFontListHead);
5238 IntUnLockProcessPrivateFonts(Win32Process);
5239
5240 /* Search system fonts */
5242 FindBestFontFromList(&TextObj->Font, &MatchPenalty, &SubstitutedLogFont,
5245
5246 if (NULL == TextObj->Font)
5247 {
5248 DPRINT1("Request font %S not found, no fonts loaded at all\n",
5249 pLogFont->lfFaceName);
5251 }
5252 else
5253 {
5255 PFONTGDI FontGdi = ObjToGDI(TextObj->Font, FONT);
5256 PSHARED_FACE SharedFace = FontGdi->SharedFace;
5257
5258 TextObj->TextFace[0] = UNICODE_NULL;
5259 if (MatchFontNames(SharedFace, SubstitutedLogFont.lfFaceName))
5260 {
5261 RtlStringCchCopyW(TextObj->TextFace, _countof(TextObj->TextFace), pLogFont->lfFaceName);
5262 }
5263 else
5264 {
5267 if (NT_SUCCESS(Status))
5268 {
5269 /* truncated copy */
5270 IntUnicodeStringToBuffer(TextObj->TextFace, sizeof(TextObj->TextFace), &Name);
5272 }
5273 }
5274
5275 // Need hdev, when freetype is loaded need to create DEVOBJ for
5276 // Consumer and Producer.
5277 TextObj->Font->iUniq = 1; // Now it can be cached.
5278 IntFontType(FontGdi);
5279 FontGdi->flType = TextObj->Font->flFontType;
5280 FontGdi->RequestUnderline = pLogFont->lfUnderline ? 0xFF : 0;
5281 FontGdi->RequestStrikeOut = pLogFont->lfStrikeOut ? 0xFF : 0;
5282 FontGdi->RequestItalic = pLogFont->lfItalic ? 0xFF : 0;
5283 if (pLogFont->lfWeight != FW_DONTCARE)
5284 FontGdi->RequestWeight = pLogFont->lfWeight;
5285 else
5286 FontGdi->RequestWeight = FW_NORMAL;
5287
5288 TextObj->fl |= TEXTOBJECT_INIT;
5290 }
5291
5292 if (!pTextObj) TEXTOBJ_UnlockText(TextObj);
5293
5294 ASSERT((NT_SUCCESS(Status) ^ (NULL == TextObj->Font)) != 0);
5295
5296 return Status;
5297}
5298
5299
5300static
5301BOOL
5304 POBJECT_NAME_INFORMATION NameInfo,
5305 ULONG Size,
5307{
5310 HANDLE hFile;
5312 ULONG Desired;
5313
5315 FileName,
5317 NULL,
5318 NULL);
5319
5321 &hFile,
5322 0, // FILE_READ_ATTRIBUTES,
5326 0);
5327
5328 if (!NT_SUCCESS(Status))
5329 {
5330 DPRINT("ZwOpenFile() failed (Status = 0x%lx)\n", Status);
5331 return FALSE;
5332 }
5333
5334 Status = ZwQueryObject(hFile, ObjectNameInformation, NameInfo, Size, &Desired);
5335 ZwClose(hFile);
5336 if (!NT_SUCCESS(Status))
5337 {
5338 DPRINT("ZwQueryObject() failed (Status = %lx)\n", Status);
5339 return FALSE;
5340 }
5341
5342 return TRUE;
5343}
5344
5345static BOOL
5346EqualFamilyInfo(const FONTFAMILYINFO *pInfo1, const FONTFAMILYINFO *pInfo2)
5347{
5348 const ENUMLOGFONTEXW *pLog1 = &pInfo1->EnumLogFontEx;
5349 const ENUMLOGFONTEXW *pLog2 = &pInfo2->EnumLogFontEx;
5350 const LOGFONTW *plf1 = &pLog1->elfLogFont;
5351 const LOGFONTW *plf2 = &pLog2->elfLogFont;
5352
5353 if (_wcsicmp(plf1->lfFaceName, plf2->lfFaceName) != 0)
5354 {
5355 return FALSE;
5356 }
5357
5358 if (_wcsicmp(pLog1->elfStyle, pLog2->elfStyle) != 0)
5359 {
5360 return FALSE;
5361 }
5362
5363 return TRUE;
5364}
5365
5366static VOID
5368{
5370 if (FamInfo->EnumLogFontEx.elfStyle[0] &&
5371 _wcsicmp(FamInfo->EnumLogFontEx.elfStyle, L"Regular") != 0)
5372 {
5373 wcscat(psz, L" ");
5374 wcscat(psz, FamInfo->EnumLogFontEx.elfStyle);
5375 }
5376}
5377
5378BOOL
5382 PVOID pBuffer,
5383 DWORD *pdwBytes,
5384 DWORD dwType)
5385{
5386 UNICODE_STRING EntryFileName;
5387 POBJECT_NAME_INFORMATION NameInfo1 = NULL, NameInfo2 = NULL;
5388 PLIST_ENTRY ListEntry;
5389 PFONT_ENTRY FontEntry;
5390 ULONG Size, i, Count;
5391 LPBYTE pbBuffer;
5392 BOOL IsEqual;
5393 FONTFAMILYINFO *FamInfo;
5394 const ULONG MaxFamInfo = 64;
5395 const ULONG MAX_FAM_INFO_BYTES = sizeof(FONTFAMILYINFO) * MaxFamInfo;
5396 BOOL bSuccess;
5397 const ULONG NAMEINFO_SIZE = sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR);
5398
5399 DPRINT("IntGdiGetFontResourceInfo: dwType == %lu\n", dwType);
5400
5401 do
5402 {
5403 /* Create buffer for full path name */
5404 NameInfo1 = ExAllocatePoolWithTag(PagedPool, NAMEINFO_SIZE, TAG_FINF);
5405 if (!NameInfo1)
5406 break;
5407
5408 /* Get the full path name */
5409 if (!IntGetFullFileName(NameInfo1, NAMEINFO_SIZE, FileName))
5410 break;
5411
5412 /* Create a buffer for the entries' names */
5413 NameInfo2 = ExAllocatePoolWithTag(PagedPool, NAMEINFO_SIZE, TAG_FINF);
5414 if (!NameInfo2)
5415 break;
5416
5417 FamInfo = ExAllocatePoolWithTag(PagedPool, MAX_FAM_INFO_BYTES, TAG_FINF);
5418 } while (0);
5419
5420 if (!NameInfo1 || !NameInfo2 || !FamInfo)
5421 {
5422 if (NameInfo2)
5423 ExFreePoolWithTag(NameInfo2, TAG_FINF);
5424
5425 if (NameInfo1)
5426 ExFreePoolWithTag(NameInfo1, TAG_FINF);
5427
5429 return FALSE;
5430 }
5431
5432 Count = 0;
5433
5434 /* Try to find the pathname in the global font list */
5436 for (ListEntry = g_FontListHead.Flink; ListEntry != &g_FontListHead;
5437 ListEntry = ListEntry->Flink)
5438 {
5439 FontEntry = CONTAINING_RECORD(ListEntry, FONT_ENTRY, ListEntry);
5440 if (FontEntry->Font->Filename == NULL)
5441 continue;
5442
5443 RtlInitUnicodeString(&EntryFileName , FontEntry->Font->Filename);
5444 if (!IntGetFullFileName(NameInfo2, NAMEINFO_SIZE, &EntryFileName))
5445 continue;
5446
5447 if (!RtlEqualUnicodeString(&NameInfo1->Name, &NameInfo2->Name, FALSE))
5448 continue;
5449
5450 IsEqual = FALSE;
5451 FontFamilyFillInfo(&FamInfo[Count], FontEntry->FaceName.Buffer,
5452 NULL, FontEntry->Font);
5453 for (i = 0; i < Count; ++i)
5454 {
5455 if (EqualFamilyInfo(&FamInfo[i], &FamInfo[Count]))
5456 {
5457 IsEqual = TRUE;
5458 break;
5459 }
5460 }
5461 if (!IsEqual)
5462 {
5463 /* Found */
5464 ++Count;
5465 if (Count >= MaxFamInfo)
5466 break;
5467 }
5468 }
5470
5471 /* Free the buffers */
5472 ExFreePoolWithTag(NameInfo1, TAG_FINF);
5473 ExFreePoolWithTag(NameInfo2, TAG_FINF);
5474
5475 if (Count == 0 && dwType != 5)
5476 {
5477 /* Font could not be found in system table
5478 dwType == 5 will still handle this */
5479 ExFreePoolWithTag(FamInfo, TAG_FINF);
5480 return FALSE;
5481 }
5482
5483 bSuccess = FALSE;
5484 switch (dwType)
5485 {
5486 case 0: /* FIXME: Returns 1 or 2, don't know what this is atm */
5487 Size = sizeof(DWORD);
5488 if (*pdwBytes == 0)
5489 {
5490 *pdwBytes = Size;
5491 bSuccess = TRUE;
5492 }
5493 else if (pBuffer)
5494 {
5495 if (*pdwBytes >= Size)
5496 {
5497 *(DWORD*)pBuffer = Count;
5498 }
5499 *pdwBytes = Size;
5500 bSuccess = TRUE;
5501 }
5502 break;
5503
5504 case 1: /* copy the font title */
5505 /* calculate the required size */
5506 Size = 0;
5507 for (i = 0; i < Count; ++i)
5508 {
5509 if (i > 0)
5510 Size += 3; /* " & " */
5511 Size += wcslen(FamInfo[i].EnumLogFontEx.elfLogFont.lfFaceName);
5512 if (FamInfo[i].EnumLogFontEx.elfStyle[0] &&
5513 _wcsicmp(FamInfo[i].EnumLogFontEx.elfStyle, L"Regular") != 0)
5514 {
5515 Size += 1 + wcslen(FamInfo[i].EnumLogFontEx.elfStyle);
5516 }
5517 }
5518 Size += 2; /* "\0\0" */
5519 Size *= sizeof(WCHAR);
5520
5521 if (*pdwBytes == 0)
5522 {
5523 *pdwBytes = Size;
5524 bSuccess = TRUE;
5525 }
5526 else if (pBuffer)
5527 {
5528 if (*pdwBytes >= Size)
5529 {
5530 /* store font title to buffer */
5531 WCHAR *psz = pBuffer;
5532 *psz = 0;
5533 for (i = 0; i < Count; ++i)
5534 {
5535 if (i > 0)
5536 wcscat(psz, L" & ");
5537 IntAddNameFromFamInfo(psz, &FamInfo[i]);
5538 }
5539 psz[wcslen(psz) + 1] = UNICODE_NULL;
5540 *pdwBytes = Size;
5541 bSuccess = TRUE;
5542 }
5543 else
5544 {
5545 *pdwBytes = 1024; /* this is confirmed value */
5546 }
5547 }
5548 break;
5549
5550 case 2: /* Copy an array of LOGFONTW */
5551 Size = Count * sizeof(LOGFONTW);
5552 if (*pdwBytes == 0)
5553 {
5554 *pdwBytes = Size;
5555 bSuccess = TRUE;
5556 }
5557 else if (pBuffer)
5558 {
5559 if (*pdwBytes >= Size)
5560 {
5561 pbBuffer = (LPBYTE)pBuffer;
5562 for (i = 0; i < Count; ++i)
5563 {
5564 FamInfo[i].EnumLogFontEx.elfLogFont.lfWidth = 0;
5565 RtlCopyMemory(pbBuffer, &FamInfo[i].EnumLogFontEx.elfLogFont, sizeof(LOGFONTW));
5566 pbBuffer += sizeof(LOGFONTW);
5567 }
5568 }
5569 *pdwBytes = Size;
5570 bSuccess = TRUE;
5571 }
5572 else
5573 {
5574 *pdwBytes = 1024; /* this is confirmed value */
5575 }
5576 break;
5577
5578 case 3:
5579 Size = sizeof(DWORD);
5580 if (*pdwBytes == 0)
5581 {
5582 *pdwBytes = Size;
5583 bSuccess = TRUE;
5584 }
5585 else if (pBuffer)
5586 {
5587 if (*pdwBytes >= Size)
5588 {
5589 /* FIXME: What exactly is copied here? */
5590 *(DWORD*)pBuffer = 1;
5591 }
5592 *pdwBytes = Size;
5593 bSuccess = TRUE;
5594 }
5595 break;
5596
5597 case 4: /* full file path */
5598 if (FileName->Length >= 4 * sizeof(WCHAR))
5599 {
5600 /* The beginning of FileName is \??\ */
5601 LPWSTR pch = FileName->Buffer + 4;
5602 DWORD Length = FileName->Length - 4 * sizeof(WCHAR);
5603
5604 Size = Length + sizeof(WCHAR);
5605 if (*pdwBytes == 0)
5606 {
5607 *pdwBytes = Size;
5608 bSuccess = TRUE;
5609 }
5610 else if (pBuffer)
5611 {
5612 if (*pdwBytes >= Size)
5613 {
5615 }
5616 *pdwBytes = Size;
5617 bSuccess = TRUE;
5618 }
5619 }
5620 break;
5621
5622 case 5: /* Looks like a BOOL that is copied, TRUE, if the font was not found */
5623 Size = sizeof(BOOL);
5624 if (*pdwBytes == 0)
5625 {
5626 *pdwBytes = Size;
5627 bSuccess = TRUE;
5628 }
5629 else if (pBuffer)
5630 {
5631 if (*pdwBytes >= Size)
5632 {
5633 *(BOOL*)pBuffer = Count == 0;
5634 }
5635 *pdwBytes = Size;
5636 bSuccess = TRUE;
5637 }
5638 break;
5639 }
5640 ExFreePoolWithTag(FamInfo, TAG_FINF);
5641
5642 return bSuccess;
5643}
5644
5645
5646BOOL
5649{
5650 if (FT_HAS_FIXED_SIZES(Font->SharedFace->Face))
5651 Info->iTechnology = RI_TECH_BITMAP;
5652 else
5653 {
5654 if (FT_IS_SCALABLE(Font->SharedFace->Face))
5655 Info->iTechnology = RI_TECH_SCALABLE;
5656 else
5657 Info->iTechnology = RI_TECH_FIXED;
5658 }
5659 Info->iUniq = Font->FontObj.iUniq;
5660 Info->dwUnknown = -1;
5661 return TRUE;
5662}
5663
5664
5665DWORD
5668 DWORD cPairs,
5669 LPKERNINGPAIR pKerningPair)
5670{
5671 DWORD Count = 0;
5672 INT i = 0;
5673 FT_Face face = Font->SharedFace->Face;
5674
5675 if (FT_HAS_KERNING(face) && face->charmap->encoding == FT_ENCODING_UNICODE)
5676 {
5677 FT_UInt previous_index = 0, glyph_index = 0;
5678 FT_ULong char_code, char_previous;
5679 FT_Vector delta;
5680
5681 char_previous = char_code = FT_Get_First_Char(face, &glyph_index);
5682
5684
5685 while (glyph_index)
5686 {
5687 if (previous_index && glyph_index)
5688 {
5689 FT_Get_Kerning(face, previous_index, glyph_index, FT_KERNING_DEFAULT, &delta);
5690
5691 if (pKerningPair && cPairs)
5692 {
5693 pKerningPair[i].wFirst = char_previous;
5694 pKerningPair[i].wSecond = char_code;
5695 pKerningPair[i].iKernAmount = delta.x;
5696 i++;
5697 if (i == cPairs) break;
5698 }
5699 Count++;
5700 }
5701 previous_index = glyph_index;
5702 char_previous = char_code;
5703 char_code = FT_Get_Next_Char(face, char_code, &glyph_index);
5704 }
5706 }
5707 return Count;
5708}
5709
5710
5712//
5713// Functions needing sorting.
5714//
5716
5719 const LOGFONTW *SafeLogFont,
5720 PFONTFAMILYINFO SafeInfo,
5721 LONG InfoCount)
5722{
5723 LONG AvailCount = 0;
5724 PPROCESSINFO Win32Process;
5725
5726 /* Enumerate font families in the global list */
5728 if (!GetFontFamilyInfoForList(SafeLogFont, SafeInfo, NULL, &AvailCount,
5729 InfoCount, &g_FontListHead))
5730 {
5732 return -1;
5733 }
5735
5736 /* Enumerate font families in the process local list */
5737 Win32Process = PsGetCurrentProcessWin32Process();
5738 IntLockProcessPrivateFonts(Win32Process);
5739 if (!GetFontFamilyInfoForList(SafeLogFont, SafeInfo, NULL, &AvailCount, InfoCount,
5740 &Win32Process->PrivateFontListHead))
5741 {
5742 IntUnLockProcessPrivateFonts(Win32Process);
5743 return -1;
5744 }
5745 IntUnLockProcessPrivateFonts(Win32Process);
5746
5747 /* Enumerate font families in the registry */
5748 if (!GetFontFamilyInfoForSubstitutes(SafeLogFont, SafeInfo, &AvailCount, InfoCount))
5749 {
5750 return -1;
5751 }
5752
5753 return AvailCount;
5754}
5755
5756LONG NTAPI
5758 const LOGFONTW *UnsafeLogFont,
5759 PFONTFAMILYINFO UnsafeInfo,
5760 LPLONG UnsafeInfoCount)
5761{
5763 LOGFONTW LogFont;
5765 LONG GotCount, AvailCount, SafeInfoCount;
5767
5768 if (UnsafeLogFont == NULL || UnsafeInfo == NULL || UnsafeInfoCount == NULL)
5769 {
5771 return -1;
5772 }
5773
5774 Status = MmCopyFromCaller(&SafeInfoCount, UnsafeInfoCount, sizeof(SafeInfoCount));
5775 if (!NT_SUCCESS(Status))
5776 {
5778 return -1;
5779 }
5780 GotCount = 0;
5781 Status = MmCopyToCaller(UnsafeInfoCount, &GotCount, sizeof(*UnsafeInfoCount));
5782 if (!NT_SUCCESS(Status))
5783 {
5785 return -1;
5786 }
5787 Status = MmCopyFromCaller(&LogFont, UnsafeLogFont, sizeof(LOGFONTW));
5788 if (!NT_SUCCESS(Status))
5789 {
5791 return -1;
5792 }
5793 if (SafeInfoCount <= 0)
5794 {
5796 return -1;
5797 }
5798
5799 /* Allocate space for a safe copy */
5800 Status = RtlULongMult(SafeInfoCount, sizeof(FONTFAMILYINFO), &DataSize);
5802 {
5803 DPRINT1("Overflowed.\n");
5805 return -1;
5806 }
5808 if (Info == NULL)
5809 {
5811 return -1;
5812 }
5813
5814 /* Retrieve the information */
5815 AvailCount = IntGetFontFamilyInfo(Dc, &LogFont, Info, SafeInfoCount);
5816 GotCount = min(AvailCount, SafeInfoCount);
5817 SafeInfoCount = AvailCount;
5818
5819 /* Return data to caller */
5820 if (GotCount > 0)
5821 {
5822 Status = RtlULongMult(GotCount, sizeof(FONTFAMILYINFO), &DataSize);
5824 {
5825 DPRINT1("Overflowed.\n");
5828 return -1;
5829 }
5830 Status = MmCopyToCaller(UnsafeInfo, Info, DataSize);
5831 if (!NT_SUCCESS(Status))
5832 {
5835 return -1;
5836 }
5837 Status = MmCopyToCaller(UnsafeInfoCount, &SafeInfoCount, sizeof(*UnsafeInfoCount));
5838 if (!NT_SUCCESS(Status))
5839 {
5842 return -1;
5843 }
5844 }
5845
5847
5848 return GotCount;
5849}
5850
5851static inline
5852LONG
5854{
5855 FLOATOBJ efTemp;
5856
5857 /* Check if we have scaling different from 1 */
5858 if (!FLOATOBJ_Equal(pef, (PFLOATOBJ)&gef1))
5859 {
5860 /* Need to multiply */
5861 FLOATOBJ_SetLong(&efTemp, lValue);
5862 FLOATOBJ_Mul(&efTemp, pef);
5863 lValue = FLOATOBJ_GetLong(&efTemp);
5864 }
5865
5866 return lValue;
5867}
5868
5869/*
5870 * Calculate X and Y disposition of the text.
5871 * NOTE: The disposition can be negative.
5872 */
5873static BOOL
5875 OUT LONGLONG *pX64,
5876 OUT LONGLONG *pY64,
5878 IN INT Count,
5879 IN OPTIONAL LPINT Dx,
5881 IN UINT fuOptions)
5882{
5883 LONGLONG X64 = 0, Y64 = 0;
5884 INT i, glyph_index;
5885 FT_BitmapGlyph realglyph;
5886 FT_Face face = Cache->Hashed.Face;
5887 BOOL use_kerning = FT_HAS_KERNING(face);
5888 ULONG previous = 0;
5889 FT_Vector delta;
5890
5892
5893 for (i = 0; i < Count; ++i)
5894 {
5895 glyph_index = get_glyph_index_flagged(face, *String++, ETO_GLYPH_INDEX, fuOptions);
5896 Cache->Hashed.GlyphIndex = glyph_index;
5897
5898 realglyph = IntGetRealGlyph(Cache);
5899 if (!realglyph)
5900 return FALSE;
5901
5902 /* Retrieve kerning distance */
5903 if (use_kerning && previous && glyph_index)
5904 {
5905 FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
5906 X64 += delta.x;
5907 Y64 -= delta.y;
5908 }
5909
5910 if (NULL == Dx)
5911 {
5912 X64 += realglyph->root.advance.x >> 10;
5913 Y64 -= realglyph->root.advance.y >> 10;
5914 }
5915 else if (fuOptions & ETO_PDY)
5916 {
5917 FT_Vector vec = { Dx[2 * i + 0] << 6, Dx[2 * i + 1] << 6 };
5918 FT_Vector_Transform(&vec, &Cache->Hashed.matTransform);
5919 X64 += vec.x;
5920 Y64 -= vec.y;
5921 }
5922 else
5923 {
5924 FT_Vector vec = { Dx[i] << 6, 0 };
5925 FT_Vector_Transform(&vec, &Cache->Hashed.matTransform);
5926 X64 += vec.x;
5927 Y64 -= vec.y;
5928 }
5929
5930 if (Cache->Hashed.Aspect.EmuBoldItalic)
5931 FT_Done_Glyph((FT_Glyph)realglyph);
5932
5933 previous = glyph_index;
5934 }
5935
5936 *pX64 = X64;
5937 *pY64 = Y64;
5938 return TRUE;
5939}
5940
5943 IN OUT PDC dc,
5944 IN POINTL *pPoints,
5945 IN UINT cPoints,
5946 IN BRUSHOBJ *BrushObj)
5947{
5948 SURFACE *psurf = dc->dclevel.pSurface;
5949 RECT Rect;
5950 UINT i;
5951 INT x, y;
5952
5954 ASSERT(psurf != NULL);
5955
5956 Rect.left = Rect.right = pPoints[0].x;
5957 Rect.top = Rect.bottom = pPoints[0].y;
5958 for (i = 1; i < cPoints; ++i)
5959 {
5960 x = pPoints[i].x;
5961 if (x < Rect.left)
5962 Rect.left = x;
5963 else if (Rect.right < x)
5964 Rect.right = x;
5965
5966 y = pPoints[i].y;
5967 if (y < Rect.top)
5968 Rect.top = y;
5969 else if (Rect.bottom < y)
5970 Rect.bottom = y;
5971 }
5972
5973 IntFillPolygon(dc, dc->dclevel.pSurface, BrushObj, pPoints, cPoints, Rect, &PointZero);
5974}
5975
5976VOID
5979 IN OUT PDC dc,
5980 IN INT X,
5981 IN INT Y,
5982 IN INT Width,
5983 IN INT Height,
5984 IN BRUSHOBJ *BrushObj)
5985{
5986 RECTL DestRect;
5987 SURFACE *psurf = dc->dclevel.pSurface;
5988
5990 ASSERT(psurf != NULL);
5991
5992 if (Width < 0)
5993 {
5994 X += Width;
5995 Width = -Width;
5996 }
5997
5998 if (Height < 0)
5999 {
6000 Y += Height;
6001 Height = -Height;
6002 }
6003
6004 DestRect.left = X;
6005 DestRect.right = X + Width;
6006 DestRect.top = Y;
6007 DestRect.bottom = Y + Height;
6008
6009 IntEngBitBlt(&psurf->SurfObj,
6010 NULL,
6011 NULL,
6012 (CLIPOBJ *)&dc->co,
6013 NULL,
6014 &DestRect,
6015 NULL,
6016 NULL,
6017 BrushObj,
6018 &PointZero,
6020}
6021
6022
6023BOOL
6026 IN PDC dc,
6027 IN INT XStart,
6028 IN INT YStart,
6029 IN UINT fuOptions,
6032 IN INT Count,
6033 IN OPTIONAL LPINT Dx,
6034 IN DWORD dwCodePage)
6035{
6036 /*
6037 * FIXME:
6038 * Call EngTextOut, which does the real work (calling DrvTextOut where
6039 * appropriate)
6040 */
6041
6042 PDC_ATTR pdcattr;
6043 SURFOBJ *SurfObj, *SourceGlyphSurf;
6044 SURFACE *psurf;
6045 INT glyph_index, i;
6046 FT_Face face;
6047 FT_BitmapGlyph realglyph;
6048 LONGLONG X64, Y64, RealXStart64, RealYStart64, DeltaX64, DeltaY64;
6049 ULONG previous;
6050 RECTL DestRect, MaskRect;
6051 HBITMAP HSourceGlyph;
6052 SIZEL bitSize;
6053 FONTOBJ *FontObj;
6054 PFONTGDI FontGDI;
6055 PTEXTOBJ TextObj = NULL;
6056 EXLATEOBJ exloRGB2Dst, exloDst2RGB;
6057 POINT Start;
6058 PMATRIX pmxWorldToDevice;
6059 FT_Vector delta, vecAscent64, vecDescent64;
6060 LOGFONTW *plf;
6061 BOOL use_kerning, bResult, DoBreak;
6063 FT_Matrix mat;
6064
6065 /* Check if String is valid */
6066 if (Count > 0xFFFF || (Count > 0 && String == NULL))
6067 {
6069 return FALSE;
6070 }
6071
6072 if (PATH_IsPathOpen(dc->dclevel))
6073 {
6074 return PATH_ExtTextOut(dc,
6075 XStart, YStart,
6076 fuOptions,
6077 lprc,
6078 String, Count,
6079 Dx);
6080 }
6081
6083
6084 if (!dc->dclevel.pSurface)
6085 {
6086 /* Memory DC with no surface selected */
6087 bResult = TRUE;
6088 goto Cleanup;
6089 }
6090
6091 pdcattr = dc->pdcattr;
6092 if (pdcattr->flTextAlign & TA_UPDATECP)
6093 {
6094 Start.x = pdcattr->ptlCurrent.x;
6095 Start.y = pdcattr->ptlCurrent.y;
6096 }
6097 else
6098 {
6099 Start.x = XStart;
6100 Start.y = YStart;
6101 }
6102
6103 IntLPtoDP(dc, &Start, 1);
6104 RealXStart64 = ((LONGLONG)Start.x + dc->ptlDCOrig.x) << 6;
6105 RealYStart64 = ((LONGLONG)Start.y + dc->ptlDCOrig.y) << 6;
6106
6107 MaskRect.left = 0;
6108 MaskRect.top = 0;
6109
6110 psurf = dc->dclevel.pSurface;
6111 SurfObj = &psurf->SurfObj;
6112
6113 if (pdcattr->iGraphicsMode == GM_ADVANCED)
6114 pmxWorldToDevice = DC_pmxWorldToDevice(dc);
6115 else
6116 pmxWorldToDevice = (PMATRIX)&gmxWorldToDeviceDefault;
6117
6118 if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
6120
6121 if (lprc && (fuOptions & (ETO_CLIPPED | ETO_OPAQUE)))
6122 {
6123 IntLPtoDP(dc, (POINT*)lprc, 2);
6124 lprc->left += dc->ptlDCOrig.x;
6125 lprc->top += dc->ptlDCOrig.y;
6126 lprc->right += dc->ptlDCOrig.x;
6127 lprc->bottom += dc->ptlDCOrig.y;
6128 }
6129
6130 if (lprc && (fuOptions & ETO_OPAQUE))
6131 {
6133 lprc->left, lprc->top,
6134 lprc->right - lprc->left, lprc->bottom - lprc->top,
6135 &dc->eboBackground.BrushObject);
6136 fuOptions &= ~ETO_OPAQUE;
6137 }
6138 else
6139 {
6140 if (pdcattr->jBkMode == OPAQUE)
6141 {
6142 fuOptions |= ETO_OPAQUE;
6143 }
6144 }
6145
6146 TextObj = RealizeFontInit(pdcattr->hlfntNew);
6147 if (TextObj == NULL)
6148 {
6149 bResult = FALSE;
6150 goto Cleanup;
6151 }
6152
6153 FontObj = TextObj->Font;
6154 ASSERT(FontObj);
6155 FontGDI = ObjToGDI(FontObj, FONT);
6156 ASSERT(FontGDI);
6157
6159 Cache.Hashed.Face = face = FontGDI->SharedFace->Face;
6160
6161 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
6162 Cache.Hashed.lfHeight = plf->lfHeight;
6163 Cache.Hashed.lfWidth = plf->lfWidth;
6164 Cache.Hashed.Aspect.Emu.Bold = EMUBOLD_NEEDED(FontGDI->OriginalWeight, plf->lfWeight);
6165 Cache.Hashed.Aspect.Emu.Italic = (plf->lfItalic && !FontGDI->OriginalItalic);
6166
6168 Cache.Hashed.Aspect.RenderMode = (BYTE)IntGetFontRenderMode(plf);
6169 else
6170 Cache.Hashed.Aspect.RenderMode = (BYTE)FT_RENDER_MODE_MONO;
6171
6172 if (!TextIntUpdateSize(dc, TextObj, FontGDI, FALSE))
6173 {
6175 bResult = FALSE;
6176 goto Cleanup;
6177 }
6178
6179 /* Apply lfEscapement */
6180 if (FT_IS_SCALABLE(face) && plf->lfEscapement != 0)
6181 IntEscapeMatrix(&Cache.Hashed.matTransform, plf->lfEscapement);
6182 else
6183 Cache.Hashed.matTransform = identityMat;
6184
6185 /* Apply the world transformation */
6186 IntMatrixFromMx(&mat, pmxWorldToDevice);
6187 FT_Matrix_Multiply(&mat, &Cache.Hashed.matTransform);
6188 FT_Set_Transform(face, &Cache.Hashed.matTransform, NULL);
6189
6190 /* Calculate the ascent point and the descent point */
6191 vecAscent64.x = 0;
6192 vecAscent64.y = (FontGDI->tmAscent << 6);
6193 FT_Vector_Transform(&vecAscent64, &Cache.Hashed.matTransform);
6194 vecDescent64.x = 0;
6195 vecDescent64.y = -(FontGDI->tmDescent << 6);
6196 FT_Vector_Transform(&vecDescent64, &Cache.Hashed.matTransform);
6197
6198 /* Process the vertical alignment and fix the real starting point. */
6199#define VALIGN_MASK (TA_TOP | TA_BASELINE | TA_BOTTOM)
6200 if ((pdcattr->flTextAlign & VALIGN_MASK) == TA_BASELINE)
6201 {
6202 NOTHING;
6203 }
6204 else if ((pdcattr->flTextAlign & VALIGN_MASK) == TA_BOTTOM)
6205 {
6206 RealXStart64 -= vecDescent64.x;
6207 RealYStart64 += vecDescent64.y;
6208 }
6209 else /* TA_TOP */
6210 {
6211 RealXStart64 -= vecAscent64.x;
6212 RealYStart64 += vecAscent64.y;
6213 }
6214#undef VALIGN_MASK
6215
6216 use_kerning = FT_HAS_KERNING(face);
6217
6218 /* Calculate the text width if necessary */
6219 if ((fuOptions & ETO_OPAQUE) || (pdcattr->flTextAlign & (TA_CENTER | TA_RIGHT)))
6220 {
6221 if (!IntGetTextDisposition(&DeltaX64, &DeltaY64, String, Count, Dx, &Cache, fuOptions))
6222 {
6224 bResult = FALSE;
6225 goto Cleanup;
6226 }
6227
6228 /* Adjust the horizontal position by horizontal alignment */
6229 if ((pdcattr->flTextAlign & TA_CENTER) == TA_CENTER)
6230 {
6231 RealXStart64 -= DeltaX64 / 2;
6232 RealYStart64 -= DeltaY64 / 2;
6233 }
6234 else if ((pdcattr->flTextAlign & TA_RIGHT) == TA_RIGHT)
6235 {
6236 RealXStart64 -= DeltaX64;
6237 RealYStart64 -= DeltaY64;
6238 }
6239
6240 /* Fill background */
6241 if (fuOptions & ETO_OPAQUE)
6242 {
6243 INT X0 = (RealXStart64 + vecAscent64.x + 32) >> 6;
6244 INT Y0 = (RealYStart64 - vecAscent64.y + 32) >> 6;
6245 INT DX = (DeltaX64 >> 6);
6246 if (Cache.Hashed.matTransform.xy == 0 && Cache.Hashed.matTransform.yx == 0)
6247 {
6248 INT CY = (vecAscent64.y - vecDescent64.y + 32) >> 6;
6249 IntEngFillBox(dc, X0, Y0, DX, CY, &dc->eboBackground.BrushObject);
6250 }
6251 else
6252 {
6253 INT DY = (DeltaY64 >> 6);
6254 INT X1 = ((RealXStart64 + vecDescent64.x + 32) >> 6);
6255 INT Y1 = ((RealYStart64 - vecDescent64.y + 32) >> 6);
6256 POINT Points[4] =
6257 {
6258 { X0, Y0 },
6259 { X0 + DX, Y0 + DY },
6260 { X1 + DX, Y1 + DY },
6261 { X1, Y1 },
6262 };
6263 IntEngFillPolygon(dc, Points, 4, &dc->eboBackground.BrushObject);
6264 }
6265 }
6266 }
6267
6268 EXLATEOBJ_vInitialize(&exloRGB2Dst, &gpalRGB, psurf->ppal, 0, 0, 0);
6269 EXLATEOBJ_vInitialize(&exloDst2RGB, psurf->ppal, &gpalRGB, 0, 0, 0);
6270
6271 /* Assume success */
6272 bResult = TRUE;
6273
6274 if (pdcattr->ulDirty_ & DIRTY_TEXT)
6276
6277 /*
6278 * The main rendering loop.
6279 */
6280 X64 = RealXStart64;
6281 Y64 = RealYStart64;
6282 previous = 0;
6283 DoBreak = FALSE;
6284 for (i = 0; i < Count; ++i)
6285 {
6286 glyph_index = get_glyph_index_flagged(face, *String++, ETO_GLYPH_INDEX, fuOptions);
6287 Cache.Hashed.GlyphIndex = glyph_index;
6288
6289 realglyph = IntGetRealGlyph(&Cache);
6290 if (!realglyph)
6291 {
6292 bResult = FALSE;
6293 break;
6294 }
6295
6296 /* retrieve kerning distance and move pen position */
6297 if (use_kerning && previous && glyph_index && NULL == Dx)
6298 {
6299 FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
6300 X64 += delta.x;
6301 Y64 -= delta.y;
6302 }
6303
6304 DPRINT("X64, Y64: %I64d, %I64d\n", X64, Y64);
6305 DPRINT("Advance: %d, %d\n", realglyph->root.advance.x, realglyph->root.advance.y);
6306
6307 bitSize.cx = realglyph->bitmap.width;
6308 bitSize.cy = realglyph->bitmap.rows;
6309
6310 MaskRect.right = realglyph->bitmap.width;
6311 MaskRect.bottom = realglyph->bitmap.rows;
6312
6313 DestRect.left = ((X64 + 32) >> 6) + realglyph->left;
6314 DestRect.right = DestRect.left + bitSize.cx;
6315 DestRect.top = ((Y64 + 32) >> 6) - realglyph->top;
6316 DestRect.bottom = DestRect.top + bitSize.cy;
6317
6318 /* Check if the bitmap has any pixels */
6319 if ((bitSize.cx != 0) && (bitSize.cy != 0))
6320 {
6321 /*
6322 * We should create the bitmap out of the loop at the biggest possible
6323 * glyph size. Then use memset with 0 to clear it and sourcerect to
6324 * limit the work of the transbitblt.
6325 */
6326 HSourceGlyph = EngCreateBitmap(bitSize, realglyph->bitmap.pitch,
6328 realglyph->bitmap.buffer);
6329 if (!HSourceGlyph)
6330 {
6331 DPRINT1("WARNING: EngCreateBitmap() failed!\n");
6332 bResult = FALSE;
6333 if (Cache.Hashed.Aspect.EmuBoldItalic)
6334 FT_Done_Glyph((FT_Glyph)realglyph);
6335 break;
6336 }
6337
6338 SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
6339 if (!SourceGlyphSurf)
6340 {
6341 EngDeleteSurface((HSURF)HSourceGlyph);
6342 DPRINT1("WARNING: EngLockSurface() failed!\n");
6343 bResult = FALSE;
6344 if (Cache.Hashed.Aspect.EmuBoldItalic)
6345 FT_Done_Glyph((FT_Glyph)realglyph);
6346 break;
6347 }
6348
6349 /*
6350 * Use the font data as a mask to paint onto the DCs surface using a
6351 * brush.
6352 */
6353 if (lprc && (fuOptions & ETO_CLIPPED))
6354 {
6355 // We do the check '>=' instead of '>' to possibly save an iteration
6356 // through this loop, since it's breaking after the drawing is done,
6357 // and x is always incremented.
6358 if (DestRect.right >= lprc->right)
6359 {
6360 DestRect.right = lprc->right;
6361 DoBreak = TRUE;
6362 }
6363
6364 if (DestRect.bottom >= lprc->bottom)
6365 {
6366 DestRect.bottom = lprc->bottom;
6367 }
6368 }
6369
6370 if (!IntEngMaskBlt(SurfObj,
6371 SourceGlyphSurf,
6372 (CLIPOBJ *)&dc->co,
6373 &exloRGB2Dst.xlo,
6374 &exloDst2RGB.xlo,
6375 &DestRect,
6376 (PPOINTL)&MaskRect,
6377 &dc->eboText.BrushObject,
6378 &PointZero))
6379 {
6380 DPRINT1("Failed to MaskBlt a glyph!\n");
6381 }
6382
6383 EngUnlockSurface(SourceGlyphSurf);
6384 EngDeleteSurface((HSURF)HSourceGlyph);
6385 }
6386
6387 if (DoBreak)
6388 {
6389 if (Cache.Hashed.Aspect.EmuBoldItalic)
6390 FT_Done_Glyph((FT_Glyph)realglyph);
6391 break;
6392 }
6393
6394 if (NULL == Dx)
6395 {
6396 X64 += realglyph->root.advance.x >> 10;
6397 Y64 -= realglyph->root.advance.y >> 10;
6398 }
6399 else if (fuOptions & ETO_PDY)
6400 {
6401 FT_Vector vec = { Dx[2 * i + 0] << 6, Dx[2 * i + 1] << 6 };
6402 FT_Vector_Transform(&vec, &Cache.Hashed.matTransform);
6403 X64 += vec.x;
6404 Y64 -= vec.y;
6405 }
6406 else
6407 {
6408 FT_Vector vec = { Dx[i] << 6, 0 };
6409 FT_Vector_Transform(&vec, &Cache.Hashed.matTransform);
6410 X64 += vec.x;
6411 Y64 -= vec.y;
6412 }
6413
6414 DPRINT("New X64, New Y64: %I64d, %I64d\n", X64, Y64);
6415
6416 previous = glyph_index;
6417
6418 if (Cache.Hashed.Aspect.EmuBoldItalic)
6419 {
6420 FT_Done_Glyph((FT_Glyph)realglyph);
6421 }
6422 }
6423
6424 if (pdcattr->flTextAlign & TA_UPDATECP)
6425 pdcattr->ptlCurrent.x = DestRect.right - dc->ptlDCOrig.x;
6426
6427 if (plf->lfUnderline || plf->lfStrikeOut) /* Underline or strike-out? */
6428 {
6429 /* Calculate the position and the thickness */
6430 INT underline_position, thickness;
6431 FT_Vector vecA64, vecB64;
6432
6433 DeltaX64 = X64 - RealXStart64;
6434 DeltaY64 = Y64 - RealYStart64;
6435
6436 if (!face->units_per_EM)
6437 {
6439 thickness = 1;
6440 }
6441 else
6442 {
6444 face->underline_position * face->size->metrics.y_ppem / face->units_per_EM;
6445 thickness =
6446 face->underline_thickness * face->size->metrics.y_ppem / face->units_per_EM;
6447 if (thickness <= 0)
6448 thickness = 1;
6449 }
6450
6451 if (plf->lfUnderline) /* Draw underline */
6452 {
6453 vecA64.x = 0;
6454 vecA64.y = (-underline_position - thickness / 2) << 6;
6455 vecB64.x = 0;
6456 vecB64.y = vecA64.y + (thickness << 6);
6457 FT_Vector_Transform(&vecA64, &Cache.Hashed.matTransform);
6458 FT_Vector_Transform(&vecB64, &Cache.Hashed.matTransform);
6459 {
6460 INT X0 = (RealXStart64 - vecA64.x + 32) >> 6;
6461 INT Y0 = (RealYStart64 + vecA64.y + 32) >> 6;
6462 INT DX = (DeltaX64 >> 6);
6463 if (Cache.Hashed.matTransform.xy == 0 && Cache.Hashed.matTransform.yx == 0)
6464 {
6465 INT CY = (vecB64.y - vecA64.y + 32) >> 6;
6466 IntEngFillBox(dc, X0, Y0, DX, CY, &dc->eboText.BrushObject);
6467 }
6468 else
6469 {
6470 INT DY = (DeltaY64 >> 6);
6471 INT X1 = X0 + ((vecA64.x - vecB64.x + 32) >> 6);
6472 INT Y1 = Y0 + ((vecB64.y - vecA64.y + 32) >> 6);
6473 POINT Points[4] =
6474 {
6475 { X0, Y0 },
6476 { X0 + DX, Y0 + DY },
6477 { X1 + DX, Y1 + DY },
6478 { X1, Y1 },
6479 };
6480 IntEngFillPolygon(dc, Points, 4, &dc->eboText.BrushObject);
6481 }
6482 }
6483 }
6484
6485 if (plf->lfStrikeOut) /* Draw strike-out */
6486 {
6487 vecA64.x = 0;
6488 vecA64.y = -(FontGDI->tmAscent << 6) / 3;
6489 vecB64.x = 0;
6490 vecB64.y = vecA64.y + (thickness << 6);
6491 FT_Vector_Transform(&vecA64, &Cache.Hashed.matTransform);
6492 FT_Vector_Transform(&vecB64, &Cache.Hashed.matTransform);
6493 {
6494 INT X0 = (RealXStart64 - vecA64.x + 32) >> 6;
6495 INT Y0 = (RealYStart64 + vecA64.y + 32) >> 6;
6496 INT DX = (DeltaX64 >> 6);
6497 if (Cache.Hashed.matTransform.xy == 0 && Cache.Hashed.matTransform.yx == 0)
6498 {
6499 INT CY = (vecB64.y - vecA64.y + 32) >> 6;
6500 IntEngFillBox(dc, X0, Y0, DX, CY, &dc->eboText.BrushObject);
6501 }
6502 else
6503 {
6504 INT DY = (DeltaY64 >> 6);
6505 INT X1 = X0 + ((vecA64.x - vecB64.x + 32) >> 6);
6506 INT Y1 = Y0 + ((vecB64.y - vecA64.y + 32) >> 6);
6507 POINT Points[4] =
6508 {
6509 { X0, Y0 },
6510 { X0 + DX, Y0 + DY },
6511 { X1 + DX, Y1 + DY },
6512 { X1, Y1 },
6513 };
6514 IntEngFillPolygon(dc, Points, 4, &dc->eboText.BrushObject);
6515 }
6516 }
6517 }
6518 }
6519
6521
6522 EXLATEOBJ_vCleanup(&exloRGB2Dst);
6523 EXLATEOBJ_vCleanup(&exloDst2RGB);
6524
6525Cleanup:
6527
6528 if (TextObj != NULL)
6529 TEXTOBJ_UnlockText(TextObj);
6530
6531 return bResult;
6532}
6533
6534
6535BOOL
6538 IN HDC hDC,
6539 IN INT XStart,
6540 IN INT YStart,
6541 IN UINT fuOptions,
6544 IN INT Count,
6545 IN OPTIONAL LPINT Dx,
6546 IN DWORD dwCodePage)
6547{
6548 BOOL bResult;
6549 DC *dc;
6550
6551 // TODO: Write test-cases to exactly match real Windows in different
6552 // bad parameters (e.g. does Windows check the DC or the RECT first?).
6553 dc = DC_LockDc(hDC);
6554 if (!dc)
6555 {
6557 return FALSE;
6558 }
6559
6560 bResult = IntExtTextOutW( dc,
6561 XStart,
6562 YStart,
6563 fuOptions,
6564 lprc,
6565 String,
6566 Count,
6567 Dx,
6568 dwCodePage );
6569
6570 DC_UnlockDc(dc);
6571
6572 return bResult;
6573}
6574
6575#define STACK_TEXT_BUFFER_SIZE 100
6576BOOL
6579 IN HDC hDC,
6580 IN INT XStart,
6581 IN INT YStart,
6582 IN UINT fuOptions,
6583 IN OPTIONAL LPRECT UnsafeRect,
6584 IN LPWSTR UnsafeString,
6585 IN INT Count,
6586 IN OPTIONAL LPINT UnsafeDx,
6587 IN DWORD dwCodePage)
6588{
6589 BOOL Result = FALSE;
6591 RECTL SafeRect;
6592 BYTE LocalBuffer[STACK_TEXT_BUFFER_SIZE];
6593 PVOID Buffer = LocalBuffer;
6594 LPCWSTR SafeString = NULL;
6595 LPINT SafeDx = NULL;
6596 ULONG BufSize, StringSize, DxSize = 0;
6597
6598 /* Check if String is valid */
6599 if ((Count > 0xFFFF) || (Count > 0 && UnsafeString == NULL))
6600 {
6602 return FALSE;
6603 }
6604
6605 if (Count > 0)
6606 {
6607 /* Calculate buffer size for string and Dx values */
6608 BufSize = StringSize = Count * sizeof(WCHAR);
6609 if (UnsafeDx)
6610 {
6611 /* If ETO_PDY is specified, we have pairs of INTs */
6612 DxSize = (Count * sizeof(INT)) * ((fuOptions & ETO_PDY) ? 2 : 1);
6613 BufSize += DxSize;
6614 }
6615
6616 /* Check if our local buffer is large enough */
6618 {
6619 /* It's not, allocate a temp buffer */
6621 if (!Buffer)
6622 {
6623 return FALSE;
6624 }
6625 }
6626
6627 /* Probe and copy user mode data to the buffer */
6628 _SEH2_TRY
6629 {
6630 /* Put the Dx before the String to assure alignment of 4 */
6631 SafeString = (LPCWSTR)(((ULONG_PTR)Buffer) + DxSize);
6632
6633 /* Probe and copy the string */
6634 ProbeForRead(UnsafeString, StringSize, 1);
6635 RtlCopyMemory((PVOID)SafeString, UnsafeString, StringSize);
6636
6637 /* If we have Dx values... */
6638 if (UnsafeDx)
6639 {
6640 /* ... probe and copy them */
6641 SafeDx = Buffer;
6642 ProbeForRead(UnsafeDx, DxSize, 1);
6643 RtlCopyMemory(SafeDx, UnsafeDx, DxSize);
6644 }
6645 }
6647 {
6649 }
6650 _SEH2_END
6651 if (!NT_SUCCESS(Status))
6652 {
6653 goto cleanup;
6654 }
6655 }
6656
6657 /* If we have a rect, copy it */
6658 if (UnsafeRect)
6659 {
6660 _SEH2_TRY
6661 {
6662 ProbeForRead(UnsafeRect, sizeof(RECT), 1);
6663 SafeRect = *UnsafeRect;
6664 }
6666 {
6668 }
6669 _SEH2_END
6670 if (!NT_SUCCESS(Status))
6671 {
6672 goto cleanup;
6673 }
6674 }
6675
6676 /* Finally call the internal routine */
6678 XStart,
6679 YStart,
6680 fuOptions,
6681 &SafeRect,
6682 SafeString,
6683 Count,
6684 SafeDx,
6685 dwCodePage);
6686
6687cleanup:
6688 /* If we allocated a buffer, free it */
6689 if (Buffer != LocalBuffer)
6690 {
6692 }
6693
6694 return Result;
6695}
6696
6697
6698/*
6699* @implemented
6700*/
6701BOOL
6704 IN HDC hDC,
6705 IN UINT FirstChar,
6706 IN ULONG Count,
6707 IN OPTIONAL PWCHAR UnSafepwch,
6708 IN FLONG fl,
6710{
6711 LPABC SafeBuff;
6712 LPABCFLOAT SafeBuffF = NULL;
6713 PDC dc;
6714 PDC_ATTR pdcattr;
6715 PTEXTOBJ TextObj;
6716 PFONTGDI FontGDI;
6717 FT_Face face;
6718 FT_CharMap charmap, found = NULL;
6719 UINT i, glyph_index, BufferSize;
6720 HFONT hFont = 0;
6722 PWCHAR Safepwch = NULL;
6723 LOGFONTW *plf;
6724
6725 if (!Buffer)
6726 {
6728 return FALSE;
6729 }
6730
6731 if (UnSafepwch)
6732 {
6733 UINT pwchSize = Count * sizeof(WCHAR);
6734 Safepwch = ExAllocatePoolWithTag(PagedPool, pwchSize, GDITAG_TEXT);
6735
6736 if(!Safepwch)
6737 {
6739 return FALSE;
6740 }
6741
6742 _SEH2_TRY
6743 {
6744 ProbeForRead(UnSafepwch, pwchSize, 1);
6745 RtlCopyMemory(Safepwch, UnSafepwch, pwchSize);
6746 }
6748 {
6750 }
6751 _SEH2_END;
6752 }
6753
6754 if (!NT_SUCCESS(Status))
6755 {
6756 if(Safepwch)
6757 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
6758
6760 return FALSE;
6761 }
6762
6763 BufferSize = Count * sizeof(ABC); // Same size!
6765 if (!fl) SafeBuffF = (LPABCFLOAT) SafeBuff;
6766 if (SafeBuff == NULL)
6767 {
6768
6769 if(Safepwch)
6770 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
6771
6773 return FALSE;
6774 }
6775
6776 dc = DC_LockDc(hDC);
6777 if (dc == NULL)
6778 {
6779 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
6780
6781 if(Safepwch)
6782 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
6783
6785 return FALSE;
6786 }
6787 pdcattr = dc->pdcattr;
6788 hFont = pdcattr->hlfntNew;
6789 TextObj = RealizeFontInit(hFont);
6790
6791 DC_UnlockDc(dc);
6792
6793 if (TextObj == NULL)
6794 {
6795 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
6796
6797 if(Safepwch)
6798 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
6799
6801 return FALSE;
6802 }
6803
6804 FontGDI = ObjToGDI(TextObj->Font, FONT);
6805
6806 face = FontGDI->SharedFace->Face;
6807 if (face->charmap == NULL)
6808 {
6809 for (i = 0; i < (UINT)face->num_charmaps; i++)
6810 {
6811 charmap = face->charmaps[i];
6812 if (charmap->encoding != 0)
6813 {
6814 found = charmap;
6815 break;
6816 }
6817 }
6818
6819 if (!found)
6820 {
6821 DPRINT1("WARNING: Could not find desired charmap!\n");
6822 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
6823
6824 if(Safepwch)
6825 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
6826
6828 return FALSE;
6829 }
6830
6832 FT_Set_Charmap(face, found);
6834 }
6835
6836 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
6837
6838 // NOTE: GetCharABCWidths simply ignores lfEscapement and XFORM.
6840 IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
6842
6843 for (i = FirstChar; i < FirstChar+Count; i++)
6844 {
6845 int adv, lsb, bbx, left, right;
6846
6847 if (Safepwch)
6848 {
6849 glyph_index = get_glyph_index_flagged(face, Safepwch[i - FirstChar], GCABCW_INDICES, fl);
6850 }
6851 else
6852 {
6854 }
6855 FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
6856
6857 left = (INT)face->glyph->metrics.horiBearingX & -64;
6858 right = (INT)((face->glyph->metrics.horiBearingX + face->glyph->metrics.width) + 63) & -64;
6859 adv = (face->glyph->advance.x + 32) >> 6;
6860
6861// int test = (INT)(face->glyph->metrics.horiAdvance + 63) >> 6;
6862// DPRINT1("Advance Wine %d and Advance Ros %d\n",test, adv ); /* It's the same! */
6863
6864 lsb = left >> 6;
6865 bbx = (right - left) >> 6;
6866 /*
6867 DPRINT1("lsb %d and bbx %d\n", lsb, bbx );
6868 */
6869 if (!fl)
6870 {
6871 SafeBuffF[i - FirstChar].abcfA = (FLOAT) lsb;
6872 SafeBuffF[i - FirstChar].abcfB = (FLOAT) bbx;
6873 SafeBuffF[i - FirstChar].abcfC = (FLOAT) (adv - lsb - bbx);
6874 }
6875 else
6876 {
6877 SafeBuff[i - FirstChar].abcA = lsb;
6878 SafeBuff[i - FirstChar].abcB = bbx;
6879 SafeBuff[i - FirstChar].abcC = adv - lsb - bbx;
6880 }
6881 }
6883 TEXTOBJ_UnlockText(TextObj);
6884 Status = MmCopyToCaller(Buffer, SafeBuff, BufferSize);
6885
6886 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
6887
6888 if(Safepwch)
6889 ExFreePoolWithTag(Safepwch , GDITAG_TEXT);
6890
6891 if (!NT_SUCCESS(Status))
6892 {
6894 return FALSE;
6895 }
6896
6897 DPRINT("NtGdiGetCharABCWidths Worked!\n");
6898 return TRUE;
6899}
6900
6901/*
6902* @implemented
6903*/
6904BOOL
6907 IN HDC hDC,
6908 IN UINT FirstChar,
6909 IN UINT Count,
6910 IN OPTIONAL PWCHAR UnSafepwc,
6911 IN FLONG fl,
6913{
6915 LPINT SafeBuff;
6916 PFLOAT SafeBuffF = NULL;
6917 PDC dc;
6918 PDC_ATTR pdcattr;
6919 PTEXTOBJ TextObj;
6920 PFONTGDI FontGDI;
6921 FT_Face face;
6922 FT_CharMap charmap, found = NULL;
6923 UINT i, glyph_index, BufferSize;
6924 HFONT hFont = 0;
6925 PWCHAR Safepwc = NULL;
6926 LOGFONTW *plf;
6927
6928 if (UnSafepwc)
6929 {
6930 UINT pwcSize = Count * sizeof(WCHAR);
6931 Safepwc = ExAllocatePoolWithTag(PagedPool, pwcSize, GDITAG_TEXT);
6932
6933 if(!Safepwc)
6934 {
6936 return FALSE;
6937 }
6938 _SEH2_TRY
6939 {
6940 ProbeForRead(UnSafepwc, pwcSize, 1);
6941 RtlCopyMemory(Safepwc, UnSafepwc, pwcSize);
6942 }
6944 {
6946 }
6947 _SEH2_END;
6948 }
6949
6950 if (!NT_SUCCESS(Status))
6951 {
6953 return FALSE;
6954 }
6955
6956 BufferSize = Count * sizeof(INT); // Same size!
6958 if (!fl) SafeBuffF = (PFLOAT) SafeBuff;
6959 if (SafeBuff == NULL)
6960 {
6961 if(Safepwc)
6963
6965 return FALSE;
6966 }
6967
6968 dc = DC_LockDc(hDC);
6969 if (dc == NULL)
6970 {
6971 if(Safepwc)
6973
6974 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
6976 return FALSE;
6977 }
6978 pdcattr = dc->pdcattr;
6979 hFont = pdcattr->hlfntNew;
6980 TextObj = RealizeFontInit(hFont);
6981 DC_UnlockDc(dc);
6982
6983 if (TextObj == NULL)
6984 {
6985 if(Safepwc)
6987
6988 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
6990 return FALSE;
6991 }
6992
6993 FontGDI = ObjToGDI(TextObj->Font, FONT);
6994
6995 face = FontGDI->SharedFace->Face;
6996 if (face->charmap == NULL)
6997 {
6998 for (i = 0; i < (UINT)face->num_charmaps; i++)
6999 {
7000 charmap = face->charmaps[i];
7001 if (charmap->encoding != 0)
7002 {
7003 found = charmap;
7004 break;
7005 }
7006 }
7007
7008 if (!found)
7009 {
7010 DPRINT1("WARNING: Could not find desired charmap!\n");
7011
7012 if(Safepwc)
7014
7015 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7017 return FALSE;
7018 }
7019
7021 FT_Set_Charmap(face, found);
7023 }
7024
7025 plf = &TextObj->logfont.elfEnumLogfontEx.elfLogFont;
7026
7027 // NOTE: GetCharWidth simply ignores lfEscapement and XFORM.
7029 IntRequestFontSize(dc, FontGDI, plf->lfWidth, plf->lfHeight);
7031
7032 for (i = FirstChar; i < FirstChar+Count; i++)
7033 {
7034 if (Safepwc)
7035 {
7036 glyph_index = get_glyph_index_flagged(face, Safepwc[i - FirstChar], GCW_INDICES, fl);
7037 }
7038 else
7039 {
7040 glyph_index = get_glyph_index_flagged(face, i, GCW_INDICES, fl);
7041 }
7042 FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
7043 if (!fl)
7044 SafeBuffF[i - FirstChar] = (FLOAT) ((face->glyph->advance.x + 32) >> 6);
7045 else
7046 SafeBuff[i - FirstChar] = (face->glyph->advance.x + 32) >> 6;
7047 }
7049 TEXTOBJ_UnlockText(TextObj);
7050 MmCopyToCaller(Buffer, SafeBuff, BufferSize);
7051
7052 if(Safepwc)
7054
7055 ExFreePoolWithTag(SafeBuff, GDITAG_TEXT);
7056 return TRUE;
7057}
7058
7059
7060/*
7061* @implemented
7062*/
7063// TODO: Move this code into NtGdiGetGlyphIndicesWInternal and wrap
7064// NtGdiGetGlyphIndicesW around NtGdiGetGlyphIndicesWInternal instead.
7065// NOTE: See also GreGetGlyphIndicesW.
7067W32KAPI
7068DWORD
7071 _In_ HDC hdc,
7072 _In_reads_opt_(cwc) LPCWSTR pwc,
7073 _In_ INT cwc,
7076{
7077 PDC dc;
7078 PDC_ATTR pdcattr;
7079 PTEXTOBJ TextObj;
7080 PFONTGDI FontGDI;
7081 HFONT hFont = NULL;
7083 OUTLINETEXTMETRICW *potm;
7084 INT i;
7085 WCHAR DefChar = 0xffff;
7086 PWSTR Buffer = NULL;
7087 ULONG Size, pwcSize;
7088 PWSTR Safepwc = NULL;
7089 LPCWSTR UnSafepwc = pwc;
7090 LPWORD UnSafepgi = pgi;
7091 FT_Face Face;
7092 TT_OS2 *pOS2;
7093
7094 if (cwc < 0)
7095 {
7096 DPRINT1("cwc < 0\n");
7097 return GDI_ERROR;
7098 }
7099
7100 if (!UnSafepwc && !UnSafepgi && cwc > 0)
7101 {
7102 DPRINT1("!UnSafepwc && !UnSafepgi && cwc > 0\n");
7103 return GDI_ERROR;
7104 }
7105
7106 if (!UnSafepwc != !UnSafepgi)
7107 {
7108 DPRINT1("UnSafepwc == %p, UnSafepgi = %p\n", UnSafepwc, UnSafepgi);
7109 return GDI_ERROR;
7110 }
7111
7112 /* Get FontGDI */
7113 dc = DC_LockDc(hdc);
7114 if (!dc)
7115 {
7116 DPRINT1("!DC_LockDC\n");
7117 return GDI_ERROR;
7118 }
7119 pdcattr = dc->pdcattr;
7120 hFont = pdcattr->hlfntNew;
7121 TextObj = RealizeFontInit(hFont);
7122 DC_UnlockDc(dc);
7123 if (!TextObj)
7124 {
7125 DPRINT1("!TextObj\n");
7126 return GDI_ERROR;
7127 }
7128 FontGDI = ObjToGDI(TextObj->Font, FONT);
7129 TEXTOBJ_UnlockText(TextObj);
7130
7131 if (cwc == 0)
7132 {
7133 if (!UnSafepwc && !UnSafepgi)
7134 {
7135 Face = FontGDI->SharedFace->Face;
7136 return Face->num_glyphs;
7137 }
7138 else
7139 {
7141 goto ErrorRet;
7142 }
7143 }
7144
7146 if (!Buffer)
7147 {
7148 DPRINT1("ExAllocatePoolWithTag\n");
7149 return GDI_ERROR;
7150 }
7151
7152 /* Get DefChar */
7154 {
7155 DefChar = 0xffff;
7156 }
7157 else
7158 {
7159 Face = FontGDI->SharedFace->Face;
7160 if (FT_IS_SFNT(Face))
7161 {
7163 pOS2 = FT_Get_Sfnt_Table(Face, ft_sfnt_os2);
7164 DefChar = (pOS2->usDefaultChar ? get_glyph_index(Face, pOS2->usDefaultChar) : 0);
7166 }
7167 else
7168 {
7169 Size = IntGetOutlineTextMetrics(FontGDI, 0, NULL);
7170 if (!Size)
7171 {
7173 DPRINT1("!Size\n");
7174 goto ErrorRet;
7175 }
7177 if (!potm)
7178 {
7180 DPRINT1("!potm\n");
7181 goto ErrorRet;
7182 }
7183 Size = IntGetOutlineTextMetrics(FontGDI, Size, potm);
7184 if (Size)
7185 DefChar = potm->otmTextMetrics.tmDefaultChar;
7187 }
7188 }
7189
7190 /* Allocate for Safepwc */
7191 pwcSize = cwc * sizeof(WCHAR);
7192 Safepwc = ExAllocatePoolWithTag(PagedPool, pwcSize, GDITAG_TEXT);
7193 if (!Safepwc)
7194 {
7196 DPRINT1("!Safepwc\n");
7197 goto ErrorRet;
7198 }
7199
7200 _SEH2_TRY
7201 {
7202 ProbeForRead(UnSafepwc, pwcSize, 1);
7203 RtlCopyMemory(Safepwc, UnSafepwc, pwcSize);
7204 }
7206 {
7208 }
7209 _SEH2_END;
7210
7211 if (!NT_SUCCESS(Status))
7212 {
7213 DPRINT1("Status: %08lX\n", Status);
7214 goto ErrorRet;
7215 }
7216
7217 /* Get glyph indeces */
7219 for (i = 0; i < cwc; i++)
7220 {
7221 Buffer[i] = get_glyph_index(FontGDI->SharedFace->Face, Safepwc[i]);
7222 if (Buffer[i] == 0)
7223 {
7224 Buffer[i] = DefChar;
7225 }
7226 }
7228
7229 _SEH2_TRY
7230 {
7231 ProbeForWrite(UnSafepgi, cwc * sizeof(WORD), 1);
7232 RtlCopyMemory(UnSafepgi, Buffer, cwc * sizeof(WORD));
7233 }
7235 {
7237 }
7238 _SEH2_END;
7239
7240ErrorRet:
7241 if (Buffer != NULL)
7242 {
7244 }
7245 if (Safepwc != NULL)
7246 {
7248 }
7249
7250 if (NT_SUCCESS(Status))
7251 return cwc;
7252
7253 return GDI_ERROR;
7254}
7255
7256/* EOF */
static HDC hDC
Definition: 3dtext.c:33
@ IgnoreFiles
Definition: ACListISF.cpp:75
NTSTATUS NTAPI MmUnmapViewInSystemSpace(IN PVOID MappedBase)
Definition: section.c:3128
@ ObjectNameInformation
Definition: DriverTester.h:55
#define BufSize
Definition: FsRtlTunnel.c:28
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 DPRINT1
Definition: precomp.h:8
HFONT hFont
Definition: main.c:53
BOOL Error
Definition: chkdsk.c:66
#define ULongToHandle(h)
Definition: basetsd.h:81
#define UNIMPLEMENTED
Definition: debug.h:115
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
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:32
WORD face[3]
Definition: mesh.c:4747
#define APIENTRY
Definition: api.h:79
#define Y(I)
#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:433
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 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:1013
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:1886
#define abs(i)
Definition: fconv.c:206
struct _FileName FileName
Definition: fatprocs.h:896
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
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:7070
BOOL FASTCALL TextIntUpdateSize(PDC dc, PTEXTOBJ TextObj, PFONTGDI FontGDI, BOOL bDoLock)
Definition: freetype.c:3585
VOID APIENTRY IntEngFillPolygon(IN OUT PDC dc, IN POINTL *pPoints, IN UINT cPoints, IN BRUSHOBJ *BrushObj)
Definition: freetype.c:5942
#define CP_OEMCP
Definition: freetype.c:166
static BOOLEAN FASTCALL GetFontFamilyInfoForList(const LOGFONTW *LogFont, PFONTFAMILYINFO Info, LPCWSTR NominalName, LONG *pCount, LONG MaxCount, PLIST_ENTRY Head)
Definition: freetype.c:2947
DWORD FASTCALL ftGdiGetKerningPairs(PFONTGDI Font, DWORD cPairs, LPKERNINGPAIR pKerningPair)
Definition: freetype.c:5667
#define ASSERT_FREETYPE_LOCK_NOT_HELD()
Definition: freetype.c:88
static const CHARSETINFO g_FontTci[MAXTCIINDEX]
Definition: freetype.c:124
LONG FASTCALL IntGetFontFamilyInfo(HDC Dc, const LOGFONTW *SafeLogFont, PFONTFAMILYINFO SafeInfo, LONG InfoCount)
Definition: freetype.c:5718
static PFAST_MUTEX g_FreeTypeLock
Definition: freetype.c:64
VOID FASTCALL IntGdiCleanupMemEntry(PFONT_ENTRY_MEM Head)
Definition: freetype.c:1841
static UINT GetFontPenalty(const LOGFONTW *LogFont, const OUTLINETEXTMETRICW *Otm, const char *style_name)
Definition: freetype.c:4694
static BOOL face_has_symbol_charmap(FT_Face ft_face)
Definition: freetype.c:2080
static DWORD IntGetHash(IN LPCVOID pv, IN DWORD cdw)
Definition: freetype.c:3087
static BOOL FASTCALL IntGetFullFileName(POBJECT_NAME_INFORMATION NameInfo, ULONG Size, PUNICODE_STRING FileName)
Definition: freetype.c:5303
static FT_Error IntRequestFontSize(PDC dc, PFONTGDI FontGDI, LONG lfWidth, LONG lfHeight)
Definition: freetype.c:3445
static void SharedMem_AddRef(PSHARED_MEM Ptr)
Definition: freetype.c:198
BOOL FASTCALL ftGdiGetTextMetricsW(HDC hDC, PTMW_INTERNAL ptmwi)
Definition: freetype.c:4555
static NTSTATUS DuplicateUnicodeString(PUNICODE_STRING Source, PUNICODE_STRING Destination)
Definition: freetype.c:830
static PSHARED_FACE SharedFace_Create(FT_Face Face, PSHARED_MEM Memory)
Definition: freetype.c:214
static VOID FASTCALL IntFontType(PFONTGDI Font)
Definition: freetype.c:5108
FT_Library g_FreeTypeLibrary
Definition: freetype.c:55
BOOL FASTCALL TextIntGetTextExtentPoint(PDC dc, PTEXTOBJ TextObj, LPCWSTR String, INT Count, ULONG MaxExtent, LPINT Fit, LPINT Dx, LPSIZE Size, FLONG fl)
Definition: freetype.c:4258
static LIST_ENTRY g_FontListHead
Definition: freetype.c:66
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:6537
BOOL FASTCALL IntGdiGetFontResourceInfo(PUNICODE_STRING FileName, PVOID pBuffer, DWORD *pdwBytes, DWORD dwType)
Definition: freetype.c:5380
static PWCHAR g_ElfScripts[32]
Definition: freetype.c:96
static PSHARED_MEM SharedMem_Create(PBYTE Buffer, ULONG BufferSize, BOOL IsMapping)
Definition: freetype.c:233
ULONG FASTCALL ftGdiGetGlyphOutline(PDC dc, WCHAR wch, UINT iFormat, LPGLYPHMETRICS pgm, ULONG cjBuf, PVOID pvBuf, LPMAT2 pmat2, BOOL bIgnoreRotation)
Definition: freetype.c:3723
static BOOL SubstituteFontRecurse(LOGFONTW *pLogFont)
Definition: freetype.c:853
static BOOL EqualFamilyInfo(const FONTFAMILYINFO *pInfo1, const FONTFAMILYINFO *pInfo2)
Definition: freetype.c:5346
#define MAXTCIINDEX
Definition: freetype.c:123
BYTE FASTCALL IntCharSetFromCodePage(UINT uCodePage)
Definition: freetype.c:172
static __inline SIZE_T FASTCALL IntStoreName(const UNICODE_STRING *pName, BYTE *pb)
Definition: freetype.c:2353
#define CP_SYMBOL
Definition: freetype.c:122
const MATRIX gmxWorldToPageDefault
Definition: dclife.c:36
static UNICODE_STRING g_FontRegPath
Definition: freetype.c:58
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:6703
VOID FASTCALL IntGdiCleanupPrivateFontsForProcess(VOID)
Definition: freetype.c:1911
static void SharedFaceCache_Init(PSHARED_FACE_CACHE Cache)
Definition: freetype.c:206
static unsigned int get_bezier_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
Definition: freetype.c:3320
BOOL FASTCALL InitFontSupport(VOID)
Definition: freetype.c:657
static FT_UInt FASTCALL get_glyph_index_symbol(FT_Face ft_face, UINT glyph)
Definition: freetype.c:3674
static __inline VOID FindBestFontFromList(FONTOBJ **FontObj, ULONG *MatchPenalty, const LOGFONTW *LogFont, const PLIST_ENTRY Head)
Definition: freetype.c:5040
BOOL FASTCALL IntLoadFontSubstList(PLIST_ENTRY pHead)
Definition: freetype.c:510
static UINT g_FontCacheNumEntries
Definition: freetype.c:94
static LPCWSTR FASTCALL NameFromCharSet(BYTE CharSet)
Definition: freetype.c:1388
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:6025
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:6578
VOID FASTCALL IntLoadSystemFonts(VOID)
Definition: freetype.c:892
DWORD FASTCALL ftGetFontUnicodeRanges(PFONTGDI Font, PGLYPHSET glyphset)
Definition: freetype.c:4481
#define GOT_PENALTY(name, value)
Definition: freetype.c:4690
static void SharedFace_AddRef(PSHARED_FACE Ptr)
Definition: freetype.c:249
BOOL FASTCALL ftGdiGetRasterizerCaps(LPRASTERIZER_STATUS lprs)
Definition: freetype.c:3073
static VOID FASTCALL UnlinkFontMemCollection(PFONT_ENTRY_COLL_MEM Collection)
Definition: freetype.c:1860
#define SCALE_Y(value)
static void FASTCALL FontFamilyFillInfo(PFONTFAMILYINFO Info, LPCWSTR FaceName, LPCWSTR FullName, PFONTGDI FontGDI)
Definition: freetype.c:2763
static void SharedFace_Release(PSHARED_FACE Ptr)
Definition: freetype.c:318
static void SwapEndian(LPVOID pvData, DWORD Size)
Definition: freetype.c:2589
static __inline void FASTCALL IntInitFontNames(FONT_NAMES *Names, PSHARED_FACE SharedFace)
Definition: freetype.c:2325
static void RemoveCacheEntries(FT_Face Face)
Definition: freetype.c:269
LONG NTAPI NtGdiGetFontFamilyInfo(HDC Dc, const LOGFONTW *UnsafeLogFont, PFONTFAMILYINFO UnsafeInfo, LPLONG UnsafeInfoCount)
Definition: freetype.c:5757
#define FM_SEL_USE_TYPO_METRICS
BOOL FASTCALL ftGdiRealizationInfo(PFONTGDI Font, PREALIZATION_INFO Info)
Definition: freetype.c:5648
#define CP_MACCP
Definition: freetype.c:167
static FT_BitmapGlyph IntGetBitmapGlyphNoCache(FT_Face Face, FT_GlyphSlot GlyphSlot, FT_Render_Mode RenderMode)
Definition: freetype.c:3140
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)
Definition: freetype.c:5874
VOID FASTCALL IntEnableFontRendering(BOOL Enable)
Definition: freetype.c:1963
#define IntUnLockFreeType()
Definition: freetype.c:82
static VOID IntUnicodeStringToBuffer(LPWSTR pszBuffer, SIZE_T cbBuffer, const UNICODE_STRING *pString)
Definition: freetype.c:815
static INT FASTCALL IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont, PSHARED_FACE SharedFace, FT_Long FontIndex, INT CharSetIndex)
Definition: freetype.c:1050
static unsigned int get_native_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
Definition: freetype.c:3247
static VOID FASTCALL IntMatrixFromMx(FT_Matrix *pmat, const MATRIX *pmx)
Definition: freetype.c:724
static VOID FASTCALL IntEscapeMatrix(FT_Matrix *pmat, LONG lfEscapement)
Definition: freetype.c:711
static FT_UInt FASTCALL get_glyph_index_flagged(FT_Face face, FT_ULong code, DWORD indexed_flag, DWORD flags)
Definition: freetype.c:3703
static __inline BYTE *FASTCALL IntStoreFontNames(const FONT_NAMES *Names, OUTLINETEXTMETRICW *Otm)
Definition: freetype.c:2361
#define IntUnLockGlobalFonts()
Definition: freetype.c:73
static BOOLEAN IntTranslateCharsetInfo(PDWORD Src, LPCHARSETINFO Cs, DWORD Flags)
Definition: freetype.c:2033
static POINTL PointZero
Definition: freetype.c:50
static VOID IntAddNameFromFamInfo(LPWSTR psz, FONTFAMILYINFO *FamInfo)
Definition: freetype.c:5367
static void FASTCALL FillTM(TEXTMETRICW *TM, PFONTGDI FontGDI, TT_OS2 *pOS2, TT_HoriHeader *pHori, FT_WinFNT_HeaderRec *pFNT)
Definition: freetype.c:2096
#define IntLockFreeType()
Definition: freetype.c:79
static FT_BitmapGlyph IntFindGlyphCache(IN const FONT_CACHE_ENTRY *pCache)
Definition: freetype.c:3102
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:6906
INT FASTCALL IntGdiAddFontResourceEx(PUNICODE_STRING FileName, DWORD Characteristics, DWORD dwFlags)
Definition: freetype.c:1422
static FT_BitmapGlyph IntGetBitmapGlyphWithCache(IN OUT PFONT_CACHE_ENTRY Cache, IN FT_GlyphSlot GlyphSlot)
Definition: freetype.c:3183
#define STACK_TEXT_BUFFER_SIZE
Definition: freetype.c:6575
static __inline void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
Definition: freetype.c:368
NTSTATUS FASTCALL TextIntCreateFontIndirect(CONST LPLOGFONTW lf, HFONT *NewFont)
Definition: freetype.c:1991
static void SharedFaceCache_Release(PSHARED_FACE_CACHE Cache)
Definition: freetype.c:311
static BOOL g_RenderingEnabled
Definition: freetype.c:68
BOOL FASTCALL IntGdiRemoveFontMemResource(HANDLE hMMFont)
Definition: freetype.c:1877
UINT FASTCALL IntGetCharSet(INT nIndex, FT_ULong CodePageRange1)
Definition: freetype.c:1020
#define EMUBOLD_NEEDED(original, request)
Definition: freetype.c:44
static __inline VOID FASTCALL CleanupFontEntry(PFONT_ENTRY FontEntry)
Definition: freetype.c:362
NTSTATUS FASTCALL TextIntRealizeFont(HFONT FontHandle, PTEXTOBJ pTextObj)
Definition: freetype.c:5193
static BOOL SubstituteFontByList(PLIST_ENTRY pHead, PUNICODE_STRING pOutputName, PUNICODE_STRING pInputName, BYTE RequestedCharSet, BYTE CharSetMap[FONTSUBST_FROM_AND_TO])
Definition: freetype.c:753
static LIST_ENTRY g_FontCacheListHead
Definition: freetype.c:93
static FT_UInt FASTCALL get_glyph_index(FT_Face ft_face, UINT glyph)
Definition: freetype.c:3688
static const FT_Matrix identityMat
Definition: freetype.c:49
HANDLE FASTCALL IntGdiAddFontMemResource(PVOID Buffer, DWORD dwSize, PDWORD pNumAdded)
Definition: freetype.c:1789
static LONG ScaleLong(LONG lValue, PFLOATOBJ pef)
Definition: freetype.c:5853
static __inline FT_Fixed FT_FixedFromFIXED(FIXED f)
Definition: freetype.c:382
INT FASTCALL IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
Definition: freetype.c:1621
static PFAST_MUTEX g_FontListLock
Definition: freetype.c:67
static BOOL MatchFontName(PSHARED_FACE SharedFace, PUNICODE_STRING Name1, FT_UShort NameID, FT_UShort LangID)
Definition: freetype.c:5143
static BOOLEAN FASTCALL GetFontFamilyInfoForSubstitutes(const LOGFONTW *LogFont, PFONTFAMILYINFO Info, LONG *pCount, LONG MaxCount)
Definition: freetype.c:3011
#define SCALE_X(value)
static BOOL MatchFontNames(PSHARED_FACE SharedFace, LPCWSTR lfFaceName)
Definition: freetype.c:5166
#define ASSERT_FREETYPE_LOCK_HELD()
Definition: freetype.c:85
static LONG IntNormalizeAngle(LONG nTenthsOfDegrees)
Definition: freetype.c:703
INT FASTCALL IntGetOutlineTextMetrics(PFONTGDI FontGDI, UINT Size, OUTLINETEXTMETRICW *Otm)
Definition: freetype.c:2398
INT FASTCALL ftGdiGetTextCharsetInfo(PDC Dc, LPFONTSIGNATURE lpSig, DWORD dwFlags)
Definition: freetype.c:4368
static FT_BitmapGlyph IntGetRealGlyph(IN OUT PFONT_CACHE_ENTRY Cache)
Definition: freetype.c:4204
static void SharedMem_Release(PSHARED_MEM Ptr)
Definition: freetype.c:290
#define VALIGN_MASK
BOOL FASTCALL IntLoadFontsInRegistry(VOID)
Definition: freetype.c:1637
BOOL FASTCALL IntIsFontRenderingEnabled(VOID)
Definition: freetype.c:1957
DWORD FASTCALL ftGdiGetFontData(PFONTGDI FontGdi, DWORD Table, DWORD Offset, PVOID Buffer, DWORD Size)
Definition: freetype.c:4652
#define IntLockGlobalFonts()
Definition: freetype.c:70
#define gmxWorldToDeviceDefault
Definition: freetype.c:53
struct FONT_NAMES * LPFONT_NAMES
static NTSTATUS IntGetFontLocalizedName(PUNICODE_STRING pNameW, PSHARED_FACE SharedFace, FT_UShort NameID, FT_UShort LangID)
Definition: freetype.c:2603
#define MAX_FONT_CACHE
Definition: freetype.c:91
FT_Render_Mode FASTCALL IntGetFontRenderMode(LOGFONTW *logfont)
Definition: freetype.c:1969
static __inline void FASTCALL IntFreeFontNames(FONT_NAMES *Names)
Definition: freetype.c:2385
static void RemoveCachedEntry(PFONT_CACHE_ENTRY Entry)
Definition: freetype.c:257
#define _TMPF_VARIABLE_PITCH
Definition: freetype.c:40
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:5978
static BYTE CharSetFromLangID(LANGID LangID)
Definition: freetype.c:2545
static VOID FASTCALL CleanupFontEntryEx(PFONT_ENTRY FontEntry, PFONTGDI FontGDI)
Definition: freetype.c:342
BOOL WINAPI PathIsRelativeW(LPCWSTR lpszPath)
Definition: freetype.c:1627
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_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
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
#define FONTSUBST_FROM_AND_TO
Definition: font.h:71
#define FONTSUBST_FROM
Definition: font.h:69
#define FONTSUBST_TO
Definition: font.h:70
struct FONTSUBST_ENTRY * PFONTSUBST_ENTRY
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
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
GLbitfield flags
Definition: glext.h:7161
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
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define LONG_MAX
Definition: limits.h:43
_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 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 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
static LPSTR pName
Definition: security.c:75
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:92
#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
#define _Out_writes_opt_(size)
Definition: ms_sal.h:349
#define _In_reads_opt_(size)
Definition: ms_sal.h:320
#define _In_
Definition: ms_sal.h:308
_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:34
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:3004
NTSYSAPI VOID NTAPI RtlGetDefaultCodePage(_Out_ PUSHORT AnsiCodePage, _Out_ PUSHORT OemCodePage)
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
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:410
unsigned long FLONG
Definition: ntbasedef.h:366
#define UNICODE_NULL
_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
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
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 RtlStringCchCopyW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:127
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:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define long
Definition: qsort.c:33
PVOID pBuffer
_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:4447
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:4620
#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:71
#define _countof(array)
Definition: sndvol32.h:68
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:2320
UNICODE_STRING FamilyNameW
Definition: freetype.c:2317
UNICODE_STRING FaceNameW
Definition: freetype.c:2318
ULONG OtmSize
Definition: freetype.c:2321
UNICODE_STRING StyleNameW
Definition: freetype.c:2319
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_Library library
Definition: freetype.h:1910
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 * Blink
Definition: typedefs.h:122
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:285
UINT PrivateMemFontHandleCount
Definition: win32.h:286
LIST_ENTRY PrivateFontListHead
Definition: win32.h:284
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
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
#define TAG_USTR
Definition: tag.h:145
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
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
@ Start
Definition: partlist.h:33
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:147
FORCEINLINE VOID TEXTOBJ_UnlockText(PLFONT plfnt)
Definition: text.h:96
#define IntUnLockProcessPrivateFonts(W32Process)
Definition: text.h:150
#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
_In_ int _Inout_ LPRECT lprc
Definition: winuser.h:4466
_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:1648
#define RTL_STATIC_LIST_HEAD(x)
Definition: rtlfuncs.h:44
#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