2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: text.c,v 1.49 2003/08/29 21:53:50 rcampbell Exp $ */
22 #undef WIN32_LEAN_AND_MEAN
24 #include <ddk/ntddk.h>
25 #include <internal/safe.h>
26 #include <win32k/brush.h>
27 #include <win32k/dc.h>
28 #include <win32k/text.h>
29 #include <win32k/kapi.h>
30 #include <include/error.h>
32 #include FT_FREETYPE_H
34 #include "../eng/handle.h"
36 #include <include/inteng.h>
37 #include <include/text.h>
38 #include <include/eng.h>
39 #include <include/palette.h>
42 #include <win32k/debug1.h>
46 typedef struct _FONTTABLE
{
49 } FONTTABLE
, *PFONTTABLE
;
51 FONTTABLE FontTable
[256];
54 BOOL FASTCALL
InitFontSupport(VOID
)
58 static WCHAR
*FontFiles
[] =
60 L
"\\SystemRoot\\media\\fonts\\Vera.ttf",
61 L
"\\SystemRoot\\media\\fonts\\helb____.ttf",
62 L
"\\SystemRoot\\media\\fonts\\timr____.ttf",
63 L
"\\SystemRoot\\media\\fonts\\VeraBd.ttf",
64 L
"\\SystemRoot\\media\\fonts\\VeraBI.ttf",
65 L
"\\SystemRoot\\media\\fonts\\VeraIt.ttf",
66 L
"\\SystemRoot\\media\\fonts\\VeraMoBd.ttf",
67 L
"\\SystemRoot\\media\\fonts\\VeraMoBI.ttf",
68 L
"\\SystemRoot\\media\\fonts\\VeraMoIt.ttf",
69 L
"\\SystemRoot\\media\\fonts\\VeraMono.ttf",
70 L
"\\SystemRoot\\media\\fonts\\VeraSe.ttf",
71 L
"\\SystemRoot\\media\\fonts\\VeraSeBd.ttf"
74 error
= FT_Init_FreeType(&library
);
80 for (File
= 0; File
< sizeof(FontFiles
) / sizeof(WCHAR
*); File
++)
82 DPRINT("Loading font %S\n", FontFiles
[File
]);
84 NtGdiAddFontResource(FontFiles
[File
]);
87 DPRINT("All fonts loaded\n");
92 static NTSTATUS STDCALL
93 GetFontObjectsFromTextObj(PTEXTOBJ TextObj
, HFONT
*FontHandle
, PFONTOBJ
*FontObj
, PFONTGDI
*FontGDI
)
95 NTSTATUS Status
= STATUS_SUCCESS
;
97 ASSERT(NULL
!= TextObj
&& NULL
!= TextObj
->GDIFontHandle
);
98 if (NULL
!= TextObj
&& NULL
!= TextObj
->GDIFontHandle
)
100 if (NT_SUCCESS(Status
) && NULL
!= FontHandle
)
102 *FontHandle
= TextObj
->GDIFontHandle
;
104 if (NT_SUCCESS(Status
) && NULL
!= FontObj
)
106 *FontObj
= AccessUserObject((ULONG
) TextObj
->GDIFontHandle
);
107 if (NULL
== *FontObj
)
110 Status
= STATUS_INVALID_HANDLE
;
113 if (NT_SUCCESS(Status
) && NULL
!= FontGDI
)
115 *FontGDI
= AccessInternalObject((ULONG
) TextObj
->GDIFontHandle
);
116 if (NULL
== *FontGDI
)
119 Status
= STATUS_INVALID_HANDLE
;
125 Status
= STATUS_INVALID_HANDLE
;
133 NtGdiAddFontResource(LPCWSTR Filename
)
138 UNICODE_STRING uFileName
;
141 OBJECT_ATTRIBUTES ObjectAttributes
;
142 FILE_STANDARD_INFORMATION FileStdInfo
;
148 UNICODE_STRING StringU
;
149 IO_STATUS_BLOCK Iosb
;
151 NewFont
= (HFONT
)CreateGDIHandle(sizeof( FONTGDI
), sizeof( FONTOBJ
));
152 FontObj
= (PFONTOBJ
) AccessUserObject( (ULONG
) NewFont
);
153 FontGDI
= (PFONTGDI
) AccessInternalObject( (ULONG
) NewFont
);
155 RtlCreateUnicodeString(&uFileName
, (LPWSTR
)Filename
);
158 InitializeObjectAttributes(&ObjectAttributes
, &uFileName
, 0, NULL
, NULL
);
160 Status
= NtOpenFile(&FileHandle
, FILE_ALL_ACCESS
, &ObjectAttributes
, &Iosb
, 0, 0);
162 if (!NT_SUCCESS(Status
))
164 DPRINT1("Could not open module file: %S\n", Filename
);
168 // Get the size of the file
169 Status
= NtQueryInformationFile(FileHandle
, &Iosb
, &FileStdInfo
, sizeof(FileStdInfo
), FileStandardInformation
);
170 if (!NT_SUCCESS(Status
))
172 DPRINT1("Could not get file size\n");
176 // Allocate nonpageable memory for driver
177 size
= FileStdInfo
.EndOfFile
.u
.LowPart
;
178 buffer
= ExAllocatePool(NonPagedPool
, size
);
182 DPRINT1("could not allocate memory for module");
186 // Load driver into memory chunk
187 Status
= NtReadFile(FileHandle
, 0, 0, 0, &Iosb
, buffer
, FileStdInfo
.EndOfFile
.u
.LowPart
, 0, 0);
188 if (!NT_SUCCESS(Status
))
190 DPRINT1("could not read module file into memory");
197 error
= FT_New_Memory_Face(library
, buffer
, size
, 0, &face
);
198 if (error
== FT_Err_Unknown_File_Format
)
200 DPRINT1("Unknown font file format\n");
205 DPRINT1("Error reading font file (error code: %u)\n", error
); // 48
209 // FontGDI->Filename = Filename; perform strcpy
210 FontGDI
->face
= face
;
212 // FIXME: Complete text metrics
213 FontGDI
->TextMetric
.tmAscent
= face
->size
->metrics
.ascender
; // units above baseline
214 FontGDI
->TextMetric
.tmDescent
= face
->size
->metrics
.descender
; // units below baseline
215 FontGDI
->TextMetric
.tmHeight
= FontGDI
->TextMetric
.tmAscent
+ FontGDI
->TextMetric
.tmDescent
;
217 DPRINT("Font loaded: %s (%s)\n", face
->family_name
, face
->style_name
);
218 DPRINT("Num glyphs: %u\n", face
->num_glyphs
);
220 // Add this font resource to the font table
221 FontTable
[FontsLoaded
].hFont
= NewFont
;
223 RtlInitAnsiString(&StringA
, (LPSTR
)face
->family_name
);
224 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, TRUE
);
225 FontTable
[FontsLoaded
].FaceName
= ExAllocatePool(NonPagedPool
, (StringU
.Length
+ 1) * 2);
226 wcscpy((LPWSTR
)FontTable
[FontsLoaded
].FaceName
, StringU
.Buffer
);
227 RtlFreeUnicodeString(&StringU
);
235 TextIntCreateFontIndirect(CONST LPLOGFONTW lf
, HFONT
*NewFont
)
238 NTSTATUS Status
= STATUS_SUCCESS
;
240 *NewFont
= TEXTOBJ_AllocText();
241 if (NULL
!= *NewFont
)
243 TextObj
= TEXTOBJ_LockText(*NewFont
);
246 memcpy(&TextObj
->logfont
, lf
, sizeof(LOGFONTW
));
247 if (lf
->lfEscapement
!= lf
->lfOrientation
)
249 /* this should really depend on whether GM_ADVANCED is set */
250 TextObj
->logfont
.lfOrientation
= TextObj
->logfont
.lfEscapement
;
252 TEXTOBJ_UnlockText(*NewFont
);
258 Status
= STATUS_INVALID_HANDLE
;
263 Status
= STATUS_NO_MEMORY
;
271 NtGdiCreateFont(int Height
,
280 DWORD OutputPrecision
,
283 DWORD PitchAndFamily
,
288 NTSTATUS Status
= STATUS_SUCCESS
;
290 logfont
.lfHeight
= Height
;
291 logfont
.lfWidth
= Width
;
292 logfont
.lfEscapement
= Escapement
;
293 logfont
.lfOrientation
= Orientation
;
294 logfont
.lfWeight
= Weight
;
295 logfont
.lfItalic
= Italic
;
296 logfont
.lfUnderline
= Underline
;
297 logfont
.lfStrikeOut
= StrikeOut
;
298 logfont
.lfCharSet
= CharSet
;
299 logfont
.lfOutPrecision
= OutputPrecision
;
300 logfont
.lfClipPrecision
= ClipPrecision
;
301 logfont
.lfQuality
= Quality
;
302 logfont
.lfPitchAndFamily
= PitchAndFamily
;
306 int Size
= sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
);
307 wcsncpy((wchar_t *)logfont
.lfFaceName
, Face
, Size
- 1);
308 /* Be 101% sure to have '\0' at end of string */
309 logfont
.lfFaceName
[Size
- 1] = '\0';
313 logfont
.lfFaceName
[0] = L
'\0';
316 if (NT_SUCCESS(Status
))
318 Status
= TextIntCreateFontIndirect(&logfont
, &NewFont
);
321 return NT_SUCCESS(Status
) ? NewFont
: NULL
;
326 NtGdiCreateFontIndirect(CONST LPLOGFONTW lf
)
328 LOGFONTW SafeLogfont
;
330 NTSTATUS Status
= STATUS_SUCCESS
;
334 Status
= MmCopyFromCaller(&SafeLogfont
, lf
, sizeof(LOGFONTW
));
335 if (NT_SUCCESS(Status
))
337 Status
= TextIntCreateFontIndirect(&SafeLogfont
, &NewFont
);
342 Status
= STATUS_INVALID_PARAMETER
;
345 return NT_SUCCESS(Status
) ? NewFont
: NULL
;
350 NtGdiCreateScalableFontResource(DWORD Hidden
,
360 NtGdiEnumFontFamilies(HDC hDC
,
362 FONTENUMPROCW EnumFontFamProc
,
370 NtGdiEnumFontFamiliesEx(HDC hDC
,
372 FONTENUMEXPROCW EnumFontFamExProc
,
381 NtGdiEnumFonts(HDC hDC
,
383 FONTENUMPROCW FontFunc
,
391 NtGdiExtTextOut(HDC hDC
,
405 NtGdiGetAspectRatioFilterEx(HDC hDC
,
413 NtGdiGetCharABCWidths(HDC hDC
,
423 NtGdiGetCharABCWidthsFloat(HDC hDC
,
433 NtGdiGetCharacterPlacement(HDC hDC
,
437 LPGCP_RESULTSW Results
,
445 NtGdiGetCharWidth(HDC hDC
,
455 NtGdiGetCharWidth32(HDC hDC
,
465 NtGdiGetCharWidthFloat(HDC hDC
,
475 NtGdiGetFontLanguageInfo(HDC hDC
)
482 NtGdiGetGlyphOutline(HDC hDC
,
497 NtGdiGetKerningPairs(HDC hDC
,
499 LPKERNINGPAIR krnpair
)
506 NtGdiGetOutlineTextMetrics(HDC hDC
,
508 LPOUTLINETEXTMETRICW otm
)
515 NtGdiGetRasterizerCaps(LPRASTERIZER_STATUS rs
,
523 NtGdiGetTextCharset(HDC hDC
)
530 NtGdiGetTextCharsetInfo(HDC hDC
,
539 TextIntGetTextExtentPoint(PTEXTOBJ TextObj
,
550 INT error
, n
, glyph_index
, i
, previous
;
551 LONG TotalWidth
= 0, MaxHeight
= 0;
552 FT_CharMap charmap
, found
= NULL
;
555 GetFontObjectsFromTextObj(TextObj
, NULL
, NULL
, &FontGDI
);
556 face
= FontGDI
->face
;
562 if (face
->charmap
== NULL
)
564 DPRINT("WARNING: No charmap selected!\n");
565 DPRINT("This font face has %d charmaps\n", face
->num_charmaps
);
567 for (n
= 0; n
< face
->num_charmaps
; n
++)
569 charmap
= face
->charmaps
[n
];
570 DPRINT("found charmap encoding: %u\n", charmap
->encoding
);
571 if (charmap
->encoding
!= 0)
580 DPRINT1("WARNING: Could not find desired charmap!\n");
583 error
= FT_Set_Charmap(face
, found
);
586 DPRINT1("WARNING: Could not set the charmap!\n");
590 error
= FT_Set_Pixel_Sizes(face
,
591 /* FIXME should set character height if neg */
592 (TextObj
->logfont
.lfHeight
< 0 ?
593 - TextObj
->logfont
.lfHeight
:
594 TextObj
->logfont
.lfHeight
),
595 TextObj
->logfont
.lfWidth
);
598 DPRINT1("Error in setting pixel sizes: %u\n", error
);
601 use_kerning
= FT_HAS_KERNING(face
);
604 for (i
= 0; i
< Count
; i
++)
606 glyph_index
= FT_Get_Char_Index(face
, *String
);
607 error
= FT_Load_Glyph(face
, glyph_index
, FT_LOAD_DEFAULT
);
610 DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index
);
614 /* retrieve kerning distance */
615 if (use_kerning
&& previous
&& glyph_index
)
618 FT_Get_Kerning(face
, previous
, glyph_index
, 0, &delta
);
619 TotalWidth
+= delta
.x
>> 6;
622 TotalWidth
+= glyph
->advance
.x
>> 6;
623 if (glyph
->format
== ft_glyph_format_outline
)
625 error
= FT_Render_Glyph(glyph
, ft_render_mode_mono
);
628 DPRINT1("WARNING: Failed to render glyph!\n");
631 if (0 != glyph
->bitmap
.rows
&& MaxHeight
< (glyph
->bitmap
.rows
- 1))
633 MaxHeight
= glyph
->bitmap
.rows
- 1;
637 if (TotalWidth
<= MaxExtent
&& NULL
!= Fit
)
646 previous
= glyph_index
;
650 Size
->cx
= TotalWidth
;
651 Size
->cy
= MaxHeight
;
658 NtGdiGetTextExtentExPoint(HDC hDC
,
659 LPCWSTR UnsafeString
,
677 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
684 Status
= MmCopyToCaller(UnsafeSize
, &Size
, sizeof(SIZE
));
685 if (! NT_SUCCESS(Status
))
687 SetLastNtError(Status
);
693 String
= ExAllocatePool(PagedPool
, Count
* sizeof(WCHAR
));
696 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
700 if (NULL
!= UnsafeDx
)
702 Dx
= ExAllocatePool(PagedPool
, Count
* sizeof(INT
));
706 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
715 Status
= MmCopyFromCaller(String
, UnsafeString
, Count
* sizeof(WCHAR
));
716 if (! NT_SUCCESS(Status
))
723 SetLastNtError(Status
);
735 SetLastWin32Error(ERROR_INVALID_HANDLE
);
738 TextObj
= TEXTOBJ_LockText(dc
->w
.hFont
);
740 Result
= TextIntGetTextExtentPoint(TextObj
, String
, Count
, MaxExtent
,
741 NULL
== UnsafeFit
? NULL
: &Fit
, Dx
, &Size
);
742 TEXTOBJ_UnlockText(dc
->w
.hFont
);
754 if (NULL
!= UnsafeFit
)
756 Status
= MmCopyToCaller(UnsafeFit
, &Fit
, sizeof(INT
));
757 if (! NT_SUCCESS(Status
))
763 SetLastNtError(Status
);
768 if (NULL
!= UnsafeDx
)
770 Status
= MmCopyToCaller(UnsafeDx
, Dx
, Count
* sizeof(INT
));
771 if (! NT_SUCCESS(Status
))
777 SetLastNtError(Status
);
786 Status
= MmCopyToCaller(UnsafeSize
, &Size
, sizeof(SIZE
));
787 if (! NT_SUCCESS(Status
))
789 SetLastNtError(Status
);
798 NtGdiGetTextExtentPoint(HDC hDC
,
803 return NtGdiGetTextExtentExPoint(hDC
, String
, Count
, 0, NULL
, NULL
, Size
);
808 NtGdiGetTextExtentPoint32(HDC hDC
,
809 LPCWSTR UnsafeString
,
822 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
829 Status
= MmCopyToCaller(UnsafeSize
, &Size
, sizeof(SIZE
));
830 if (! NT_SUCCESS(Status
))
832 SetLastNtError(Status
);
838 String
= ExAllocatePool(PagedPool
, Count
* sizeof(WCHAR
));
841 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
845 Status
= MmCopyFromCaller(String
, UnsafeString
, Count
* sizeof(WCHAR
));
846 if (! NT_SUCCESS(Status
))
849 SetLastNtError(Status
);
857 SetLastWin32Error(ERROR_INVALID_HANDLE
);
860 TextObj
= TEXTOBJ_LockText(dc
->w
.hFont
);
862 Result
= TextIntGetTextExtentPoint (
863 TextObj
, String
, Count
, 0, NULL
, NULL
, &Size
);
865 ASSERT(dc
); // it succeeded earlier, it should now, too
866 TEXTOBJ_UnlockText(dc
->w
.hFont
);
875 Status
= MmCopyToCaller(UnsafeSize
, &Size
, sizeof(SIZE
));
876 if (! NT_SUCCESS(Status
))
878 SetLastNtError(Status
);
887 NtGdiGetTextFace(HDC hDC
,
896 NtGdiGetTextMetrics(HDC hDC
,
902 NTSTATUS Status
= STATUS_SUCCESS
;
908 if (NULL
== dc
|| NULL
== tm
)
910 Status
= STATUS_INVALID_PARAMETER
;
914 TextObj
= TEXTOBJ_LockText(dc
->w
.hFont
);
917 Status
= GetFontObjectsFromTextObj(TextObj
, NULL
, NULL
, &FontGDI
);
918 if (NT_SUCCESS(Status
))
920 Face
= FontGDI
->face
;
921 Error
= FT_Set_Pixel_Sizes(Face
,
922 /* FIXME should set character height if neg */
923 (TextObj
->logfont
.lfHeight
< 0 ?
924 - TextObj
->logfont
.lfHeight
:
925 TextObj
->logfont
.lfHeight
),
926 TextObj
->logfont
.lfWidth
);
929 DPRINT1("Error in setting pixel sizes: %u\n", Error
);
930 Status
= STATUS_UNSUCCESSFUL
;
934 memcpy(&SafeTm
, &FontGDI
->TextMetric
, sizeof(TEXTMETRICW
));
935 SafeTm
.tmAscent
= (Face
->size
->metrics
.ascender
+ 32) / 64; // units above baseline
936 SafeTm
.tmDescent
= (Face
->size
->metrics
.descender
+ 32) / 64; // units below baseline
937 SafeTm
.tmHeight
= (Face
->size
->metrics
.ascender
+
938 Face
->size
->metrics
.descender
+ 32) / 64;
939 Status
= MmCopyToCaller(tm
, &SafeTm
, sizeof(TEXTMETRICW
));
942 TEXTOBJ_UnlockText(dc
->w
.hFont
);
947 Status
= STATUS_INVALID_HANDLE
;
952 return NT_SUCCESS(Status
);
957 NtGdiPolyTextOut(HDC hDC
,
958 CONST LPPOLYTEXTW txt
,
966 NtGdiRemoveFontResource(LPCWSTR FileName
)
973 NtGdiSetMapperFlags(HDC hDC
,
981 NtGdiSetTextAlign(HDC hDC
,
992 prevAlign
= dc
->w
.textAlign
;
993 dc
->w
.textAlign
= Mode
;
1000 NtGdiSetTextColor(HDC hDC
,
1004 PDC dc
= DC_LockDc(hDC
);
1011 oldColor
= dc
->w
.textColor
;
1012 dc
->w
.textColor
= color
;
1019 NtGdiSetTextJustification(HDC hDC
,
1028 NtGdiTextOut(HDC hDC
,
1034 // Fixme: Call EngTextOut, which does the real work (calling DrvTextOut where appropriate)
1036 DC
*dc
= DC_LockDc(hDC
);
1037 SURFOBJ
*SurfObj
= (SURFOBJ
*)AccessUserObject((ULONG
) dc
->Surface
);
1038 int error
, glyph_index
, n
, i
;
1041 ULONG TextLeft
, TextTop
, pitch
, previous
;
1042 FT_Bool use_kerning
;
1043 RECTL DestRect
, MaskRect
;
1044 POINTL SourcePoint
, BrushOrigin
;
1045 HBRUSH hBrush
= NULL
;
1046 PBRUSHOBJ Brush
= NULL
;
1047 HBITMAP HSourceGlyph
;
1048 PSURFOBJ SourceGlyphSurf
;
1050 FT_CharMap found
= 0, charmap
;
1062 XStart
+= dc
->w
.DCOrgX
;
1063 YStart
+= dc
->w
.DCOrgY
;
1067 TextObj
= TEXTOBJ_LockText(dc
->w
.hFont
);
1069 if (! NT_SUCCESS(GetFontObjectsFromTextObj(TextObj
, NULL
, &FontObj
, &FontGDI
)))
1073 face
= FontGDI
->face
;
1075 if (face
->charmap
== NULL
)
1077 DPRINT("WARNING: No charmap selected!\n");
1078 DPRINT("This font face has %d charmaps\n", face
->num_charmaps
);
1080 for (n
= 0; n
< face
->num_charmaps
; n
++)
1082 charmap
= face
->charmaps
[n
];
1083 DPRINT("found charmap encoding: %u\n", charmap
->encoding
);
1084 if (charmap
->encoding
!= 0)
1090 if (!found
) DPRINT1("WARNING: Could not find desired charmap!\n");
1091 error
= FT_Set_Charmap(face
, found
);
1092 if (error
) DPRINT1("WARNING: Could not set the charmap!\n");
1095 error
= FT_Set_Pixel_Sizes(face
,
1096 /* FIXME should set character height if neg */
1097 (TextObj
->logfont
.lfHeight
< 0 ?
1098 - TextObj
->logfont
.lfHeight
:
1099 TextObj
->logfont
.lfHeight
),
1100 TextObj
->logfont
.lfWidth
);
1102 DPRINT1("Error in setting pixel sizes: %u\n", error
);
1107 PalDestGDI
= PALETTE_LockPalette(dc
->w
.hPalette
);
1108 Mode
= PalDestGDI
->Mode
;
1109 PALETTE_UnlockPalette(dc
->w
.hPalette
);
1110 XlateObj
= (PXLATEOBJ
)IntEngCreateXlate(Mode
, PAL_RGB
, dc
->w
.hPalette
, NULL
);
1111 hBrush
= NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj
, dc
->w
.textColor
));
1112 Brush
= BRUSHOBJ_LockBrush(hBrush
);
1113 EngDeleteXlate(XlateObj
);
1122 // Determine the yoff from the dc's w.textAlign
1123 if (dc
->w
.textAlign
& TA_BASELINE
) {
1127 if (dc
->w
.textAlign
& TA_BOTTOM
) {
1128 yoff
= -face
->size
->metrics
.descender
/ 64;
1131 yoff
= face
->size
->metrics
.ascender
/ 64;
1134 use_kerning
= FT_HAS_KERNING(face
);
1137 for(i
=0; i
<Count
; i
++)
1139 glyph_index
= FT_Get_Char_Index(face
, *String
);
1140 error
= FT_Load_Glyph(face
, glyph_index
, FT_LOAD_DEFAULT
);
1142 DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index
);
1145 glyph
= face
->glyph
;
1147 // retrieve kerning distance and move pen position
1148 if (use_kerning
&& previous
&& glyph_index
)
1151 FT_Get_Kerning(face
, previous
, glyph_index
, 0, &delta
);
1152 TextLeft
+= delta
.x
>> 6;
1155 if (glyph
->format
== ft_glyph_format_outline
)
1157 error
= FT_Render_Glyph(glyph
, ft_render_mode_mono
);
1159 DPRINT1("WARNING: Failed to render glyph!\n");
1162 pitch
= glyph
->bitmap
.pitch
;
1164 pitch
= glyph
->bitmap
.width
;
1167 DestRect
.left
= TextLeft
;
1168 DestRect
.top
= TextTop
+ yoff
- glyph
->bitmap_top
;
1169 DestRect
.right
= TextLeft
+ glyph
->bitmap
.width
;
1170 DestRect
.bottom
= DestRect
.top
+ glyph
->bitmap
.rows
;
1172 bitSize
.cy
= glyph
->bitmap
.rows
;
1173 MaskRect
.right
= glyph
->bitmap
.width
;
1174 MaskRect
.bottom
= glyph
->bitmap
.rows
;
1176 // We should create the bitmap out of the loop at the biggest possible glyph size
1177 // Then use memset with 0 to clear it and sourcerect to limit the work of the transbitblt
1179 HSourceGlyph
= EngCreateBitmap(bitSize
, pitch
, BMF_1BPP
, 0, glyph
->bitmap
.buffer
);
1180 SourceGlyphSurf
= (PSURFOBJ
)AccessUserObject((ULONG
) HSourceGlyph
);
1182 // Use the font data as a mask to paint onto the DCs surface using a brush
1196 EngDeleteSurface(HSourceGlyph
);
1198 TextLeft
+= glyph
->advance
.x
>> 6;
1199 previous
= glyph_index
;
1203 TEXTOBJ_UnlockText( dc
->w
.hFont
);
1204 BRUSHOBJ_UnlockBrush(hBrush
);
1205 NtGdiDeleteObject( hBrush
);
1210 TEXTOBJ_UnlockText( dc
->w
.hFont
);
1212 BRUSHOBJ_UnlockBrush(hBrush
);
1213 NtGdiDeleteObject( hBrush
);
1221 NtGdiTranslateCharsetInfo(PDWORD Src
,
1229 TextIntRealizeFont(HFONT FontHandle
)
1232 NTSTATUS Status
= STATUS_SUCCESS
;
1235 TextObj
= TEXTOBJ_LockText(FontHandle
);
1237 if (NULL
!= TextObj
)
1239 for(i
= 0; NULL
== TextObj
->GDIFontHandle
&& i
< FontsLoaded
; i
++)
1241 if (0 == wcscmp(FontTable
[i
].FaceName
, TextObj
->logfont
.lfFaceName
))
1243 TextObj
->GDIFontHandle
= FontTable
[i
].hFont
;
1247 if (NULL
== TextObj
->GDIFontHandle
)
1249 if (0 != FontsLoaded
)
1251 DPRINT("Requested font %S not found, using first available font\n",
1252 TextObj
->logfont
.lfFaceName
)
1253 TextObj
->GDIFontHandle
= FontTable
[0].hFont
;
1257 DPRINT1("Requested font %S not found, no fonts loaded at all\n",
1258 TextObj
->logfont
.lfFaceName
)
1259 Status
= STATUS_NOT_FOUND
;
1263 ASSERT(! NT_SUCCESS(Status
) || NULL
!= TextObj
->GDIFontHandle
);
1265 TEXTOBJ_UnlockText(FontHandle
);
1269 Status
= STATUS_INVALID_HANDLE
;