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.55 2003/12/08 20:58:44 chorns 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
= ZwOpenFile(&FileHandle
,
161 GENERIC_READ
|SYNCHRONIZE
,
165 FILE_SYNCHRONOUS_IO_NONALERT
);
167 if (!NT_SUCCESS(Status
))
169 DPRINT1("Could not open module file: %S\n", Filename
);
173 // Get the size of the file
174 Status
= NtQueryInformationFile(FileHandle
, &Iosb
, &FileStdInfo
, sizeof(FileStdInfo
), FileStandardInformation
);
175 if (!NT_SUCCESS(Status
))
177 DPRINT1("Could not get file size\n");
181 // Allocate nonpageable memory for driver
182 size
= FileStdInfo
.EndOfFile
.u
.LowPart
;
183 buffer
= ExAllocatePool(NonPagedPool
, size
);
187 DPRINT1("could not allocate memory for module");
191 // Load driver into memory chunk
192 Status
= ZwReadFile(FileHandle
,
198 FileStdInfo
.EndOfFile
.u
.LowPart
,
202 if (!NT_SUCCESS(Status
))
204 DPRINT1("could not read module file into memory");
211 error
= FT_New_Memory_Face(library
, buffer
, size
, 0, &face
);
212 if (error
== FT_Err_Unknown_File_Format
)
214 DPRINT1("Unknown font file format\n");
219 DPRINT1("Error reading font file (error code: %u)\n", error
); // 48
223 // FontGDI->Filename = Filename; perform strcpy
224 FontGDI
->face
= face
;
226 // FIXME: Complete text metrics
227 FontGDI
->TextMetric
.tmAscent
= (face
->size
->metrics
.ascender
+ 32) / 64; // units above baseline
228 FontGDI
->TextMetric
.tmDescent
= (- face
->size
->metrics
.descender
+ 32) / 64; // units below baseline
229 FontGDI
->TextMetric
.tmHeight
= FontGDI
->TextMetric
.tmAscent
+ FontGDI
->TextMetric
.tmDescent
;
231 DPRINT("Font loaded: %s (%s)\n", face
->family_name
, face
->style_name
);
232 DPRINT("Num glyphs: %u\n", face
->num_glyphs
);
234 // Add this font resource to the font table
235 FontTable
[FontsLoaded
].hFont
= NewFont
;
237 RtlInitAnsiString(&StringA
, (LPSTR
)face
->family_name
);
238 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, TRUE
);
239 FontTable
[FontsLoaded
].FaceName
= ExAllocatePool(NonPagedPool
, (StringU
.Length
+ 1) * 2);
240 wcscpy((LPWSTR
)FontTable
[FontsLoaded
].FaceName
, StringU
.Buffer
);
241 RtlFreeUnicodeString(&StringU
);
249 TextIntCreateFontIndirect(CONST LPLOGFONTW lf
, HFONT
*NewFont
)
252 NTSTATUS Status
= STATUS_SUCCESS
;
254 *NewFont
= TEXTOBJ_AllocText();
255 if (NULL
!= *NewFont
)
257 TextObj
= TEXTOBJ_LockText(*NewFont
);
260 memcpy(&TextObj
->logfont
, lf
, sizeof(LOGFONTW
));
261 if (lf
->lfEscapement
!= lf
->lfOrientation
)
263 /* this should really depend on whether GM_ADVANCED is set */
264 TextObj
->logfont
.lfOrientation
= TextObj
->logfont
.lfEscapement
;
266 TEXTOBJ_UnlockText(*NewFont
);
272 Status
= STATUS_INVALID_HANDLE
;
277 Status
= STATUS_NO_MEMORY
;
285 NtGdiCreateFont(int Height
,
294 DWORD OutputPrecision
,
297 DWORD PitchAndFamily
,
302 NTSTATUS Status
= STATUS_SUCCESS
;
304 logfont
.lfHeight
= Height
;
305 logfont
.lfWidth
= Width
;
306 logfont
.lfEscapement
= Escapement
;
307 logfont
.lfOrientation
= Orientation
;
308 logfont
.lfWeight
= Weight
;
309 logfont
.lfItalic
= Italic
;
310 logfont
.lfUnderline
= Underline
;
311 logfont
.lfStrikeOut
= StrikeOut
;
312 logfont
.lfCharSet
= CharSet
;
313 logfont
.lfOutPrecision
= OutputPrecision
;
314 logfont
.lfClipPrecision
= ClipPrecision
;
315 logfont
.lfQuality
= Quality
;
316 logfont
.lfPitchAndFamily
= PitchAndFamily
;
320 int Size
= sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
);
321 wcsncpy((wchar_t *)logfont
.lfFaceName
, Face
, Size
- 1);
322 /* Be 101% sure to have '\0' at end of string */
323 logfont
.lfFaceName
[Size
- 1] = '\0';
327 logfont
.lfFaceName
[0] = L
'\0';
330 if (NT_SUCCESS(Status
))
332 Status
= TextIntCreateFontIndirect(&logfont
, &NewFont
);
335 return NT_SUCCESS(Status
) ? NewFont
: NULL
;
340 NtGdiCreateFontIndirect(CONST LPLOGFONTW lf
)
342 LOGFONTW SafeLogfont
;
344 NTSTATUS Status
= STATUS_SUCCESS
;
348 Status
= MmCopyFromCaller(&SafeLogfont
, lf
, sizeof(LOGFONTW
));
349 if (NT_SUCCESS(Status
))
351 Status
= TextIntCreateFontIndirect(&SafeLogfont
, &NewFont
);
356 Status
= STATUS_INVALID_PARAMETER
;
359 return NT_SUCCESS(Status
) ? NewFont
: NULL
;
364 NtGdiCreateScalableFontResource(DWORD Hidden
,
374 NtGdiEnumFontFamilies(HDC hDC
,
376 FONTENUMPROCW EnumFontFamProc
,
384 NtGdiEnumFontFamiliesEx(HDC hDC
,
386 FONTENUMEXPROCW EnumFontFamExProc
,
395 NtGdiEnumFonts(HDC hDC
,
397 FONTENUMPROCW FontFunc
,
405 NtGdiExtTextOut(HDC hdc
,
414 /* FIXME: Implement */
415 return NtGdiTextOut(hdc
, X
, Y
, lpString
, cbCount
);
420 NtGdiGetAspectRatioFilterEx(HDC hDC
,
428 NtGdiGetCharABCWidths(HDC hDC
,
438 NtGdiGetCharABCWidthsFloat(HDC hDC
,
448 NtGdiGetCharacterPlacement(HDC hDC
,
452 LPGCP_RESULTSW Results
,
460 NtGdiGetCharWidth(HDC hDC
,
470 NtGdiGetCharWidth32(HDC hDC
,
480 NtGdiGetCharWidthFloat(HDC hDC
,
490 NtGdiGetFontLanguageInfo(HDC hDC
)
497 NtGdiGetGlyphOutline(HDC hDC
,
512 NtGdiGetKerningPairs(HDC hDC
,
514 LPKERNINGPAIR krnpair
)
521 NtGdiGetOutlineTextMetrics(HDC hDC
,
523 LPOUTLINETEXTMETRICW otm
)
530 NtGdiGetRasterizerCaps(LPRASTERIZER_STATUS rs
,
538 NtGdiGetTextCharset(HDC hDC
)
545 NtGdiGetTextCharsetInfo(HDC hDC
,
554 TextIntGetTextExtentPoint(PTEXTOBJ TextObj
,
565 INT error
, n
, glyph_index
, i
, previous
;
566 LONG TotalWidth
= 0, MaxHeight
= 0;
567 FT_CharMap charmap
, found
= NULL
;
570 GetFontObjectsFromTextObj(TextObj
, NULL
, NULL
, &FontGDI
);
571 face
= FontGDI
->face
;
577 if (face
->charmap
== NULL
)
579 DPRINT("WARNING: No charmap selected!\n");
580 DPRINT("This font face has %d charmaps\n", face
->num_charmaps
);
582 for (n
= 0; n
< face
->num_charmaps
; n
++)
584 charmap
= face
->charmaps
[n
];
585 DPRINT("found charmap encoding: %u\n", charmap
->encoding
);
586 if (charmap
->encoding
!= 0)
595 DPRINT1("WARNING: Could not find desired charmap!\n");
598 error
= FT_Set_Charmap(face
, found
);
601 DPRINT1("WARNING: Could not set the charmap!\n");
605 error
= FT_Set_Pixel_Sizes(face
,
606 /* FIXME should set character height if neg */
607 (TextObj
->logfont
.lfHeight
< 0 ?
608 - TextObj
->logfont
.lfHeight
:
609 TextObj
->logfont
.lfHeight
),
610 TextObj
->logfont
.lfWidth
);
613 DPRINT1("Error in setting pixel sizes: %u\n", error
);
616 use_kerning
= FT_HAS_KERNING(face
);
619 for (i
= 0; i
< Count
; i
++)
621 glyph_index
= FT_Get_Char_Index(face
, *String
);
622 error
= FT_Load_Glyph(face
, glyph_index
, FT_LOAD_DEFAULT
);
625 DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index
);
629 /* retrieve kerning distance */
630 if (use_kerning
&& previous
&& glyph_index
)
633 FT_Get_Kerning(face
, previous
, glyph_index
, 0, &delta
);
634 TotalWidth
+= delta
.x
>> 6;
637 TotalWidth
+= glyph
->advance
.x
>> 6;
638 if (glyph
->format
== ft_glyph_format_outline
)
640 error
= FT_Render_Glyph(glyph
, ft_render_mode_mono
);
643 DPRINT1("WARNING: Failed to render glyph!\n");
646 if (0 != glyph
->bitmap
.rows
&& MaxHeight
< (glyph
->bitmap
.rows
- 1))
648 MaxHeight
= glyph
->bitmap
.rows
- 1;
652 if (TotalWidth
<= MaxExtent
&& NULL
!= Fit
)
661 previous
= glyph_index
;
665 Size
->cx
= TotalWidth
;
666 Size
->cy
= MaxHeight
;
673 NtGdiGetTextExtentExPoint(HDC hDC
,
674 LPCWSTR UnsafeString
,
692 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
699 Status
= MmCopyToCaller(UnsafeSize
, &Size
, sizeof(SIZE
));
700 if (! NT_SUCCESS(Status
))
702 SetLastNtError(Status
);
708 String
= ExAllocatePool(PagedPool
, Count
* sizeof(WCHAR
));
711 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
715 if (NULL
!= UnsafeDx
)
717 Dx
= ExAllocatePool(PagedPool
, Count
* sizeof(INT
));
721 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
730 Status
= MmCopyFromCaller(String
, UnsafeString
, Count
* sizeof(WCHAR
));
731 if (! NT_SUCCESS(Status
))
738 SetLastNtError(Status
);
750 SetLastWin32Error(ERROR_INVALID_HANDLE
);
753 TextObj
= TEXTOBJ_LockText(dc
->w
.hFont
);
755 Result
= TextIntGetTextExtentPoint(TextObj
, String
, Count
, MaxExtent
,
756 NULL
== UnsafeFit
? NULL
: &Fit
, Dx
, &Size
);
757 TEXTOBJ_UnlockText(dc
->w
.hFont
);
769 if (NULL
!= UnsafeFit
)
771 Status
= MmCopyToCaller(UnsafeFit
, &Fit
, sizeof(INT
));
772 if (! NT_SUCCESS(Status
))
778 SetLastNtError(Status
);
783 if (NULL
!= UnsafeDx
)
785 Status
= MmCopyToCaller(UnsafeDx
, Dx
, Count
* sizeof(INT
));
786 if (! NT_SUCCESS(Status
))
792 SetLastNtError(Status
);
801 Status
= MmCopyToCaller(UnsafeSize
, &Size
, sizeof(SIZE
));
802 if (! NT_SUCCESS(Status
))
804 SetLastNtError(Status
);
813 NtGdiGetTextExtentPoint(HDC hDC
,
818 return NtGdiGetTextExtentExPoint(hDC
, String
, Count
, 0, NULL
, NULL
, Size
);
823 NtGdiGetTextExtentPoint32(HDC hDC
,
824 LPCWSTR UnsafeString
,
837 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
844 Status
= MmCopyToCaller(UnsafeSize
, &Size
, sizeof(SIZE
));
845 if (! NT_SUCCESS(Status
))
847 SetLastNtError(Status
);
853 String
= ExAllocatePool(PagedPool
, Count
* sizeof(WCHAR
));
856 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
860 Status
= MmCopyFromCaller(String
, UnsafeString
, Count
* sizeof(WCHAR
));
861 if (! NT_SUCCESS(Status
))
864 SetLastNtError(Status
);
872 SetLastWin32Error(ERROR_INVALID_HANDLE
);
875 TextObj
= TEXTOBJ_LockText(dc
->w
.hFont
);
877 Result
= TextIntGetTextExtentPoint (
878 TextObj
, String
, Count
, 0, NULL
, NULL
, &Size
);
880 ASSERT(dc
); // it succeeded earlier, it should now, too
881 TEXTOBJ_UnlockText(dc
->w
.hFont
);
890 Status
= MmCopyToCaller(UnsafeSize
, &Size
, sizeof(SIZE
));
891 if (! NT_SUCCESS(Status
))
893 SetLastNtError(Status
);
902 NtGdiGetTextFace(HDC hDC
,
911 NtGdiGetTextMetrics(HDC hDC
,
917 NTSTATUS Status
= STATUS_SUCCESS
;
923 if (NULL
== dc
|| NULL
== tm
)
925 Status
= STATUS_INVALID_PARAMETER
;
929 TextObj
= TEXTOBJ_LockText(dc
->w
.hFont
);
932 Status
= GetFontObjectsFromTextObj(TextObj
, NULL
, NULL
, &FontGDI
);
933 if (NT_SUCCESS(Status
))
935 Face
= FontGDI
->face
;
936 Error
= FT_Set_Pixel_Sizes(Face
,
937 /* FIXME should set character height if neg */
938 (TextObj
->logfont
.lfHeight
< 0 ?
939 - TextObj
->logfont
.lfHeight
:
940 TextObj
->logfont
.lfHeight
),
941 TextObj
->logfont
.lfWidth
);
944 DPRINT1("Error in setting pixel sizes: %u\n", Error
);
945 Status
= STATUS_UNSUCCESSFUL
;
949 memcpy(&SafeTm
, &FontGDI
->TextMetric
, sizeof(TEXTMETRICW
));
950 SafeTm
.tmAscent
= (Face
->size
->metrics
.ascender
+ 32) / 64; // units above baseline
951 SafeTm
.tmDescent
= (- Face
->size
->metrics
.descender
+ 32) / 64; // units below baseline
952 SafeTm
.tmHeight
= SafeTm
.tmAscent
+ SafeTm
.tmDescent
;
953 SafeTm
.tmMaxCharWidth
= (Face
->size
->metrics
.max_advance
+ 32) / 64;
954 Status
= MmCopyToCaller(tm
, &SafeTm
, sizeof(TEXTMETRICW
));
957 TEXTOBJ_UnlockText(dc
->w
.hFont
);
962 Status
= STATUS_INVALID_HANDLE
;
967 return NT_SUCCESS(Status
);
972 NtGdiPolyTextOut(HDC hDC
,
973 CONST LPPOLYTEXTW txt
,
981 NtGdiRemoveFontResource(LPCWSTR FileName
)
988 NtGdiSetMapperFlags(HDC hDC
,
996 NtGdiSetTextAlign(HDC hDC
,
1002 dc
= DC_LockDc(hDC
);
1007 prevAlign
= dc
->w
.textAlign
;
1008 dc
->w
.textAlign
= Mode
;
1015 NtGdiSetTextColor(HDC hDC
,
1019 PDC dc
= DC_LockDc(hDC
);
1026 oldColor
= dc
->w
.textColor
;
1027 dc
->w
.textColor
= color
;
1034 NtGdiSetTextJustification(HDC hDC
,
1043 NtGdiTextOut(HDC hDC
,
1049 // Fixme: Call EngTextOut, which does the real work (calling DrvTextOut where appropriate)
1053 int error
, glyph_index
, n
, i
;
1056 ULONG TextLeft
, TextTop
, pitch
, previous
, BackgroundLeft
;
1057 FT_Bool use_kerning
;
1058 RECTL DestRect
, MaskRect
;
1059 POINTL SourcePoint
, BrushOrigin
;
1060 HBRUSH hBrushFg
= NULL
;
1061 PBRUSHOBJ BrushFg
= NULL
;
1062 HBRUSH hBrushBg
= NULL
;
1063 PBRUSHOBJ BrushBg
= NULL
;
1064 HBITMAP HSourceGlyph
;
1065 PSURFOBJ SourceGlyphSurf
;
1067 FT_CharMap found
= 0, charmap
;
1076 dc
= DC_LockDc(hDC
);
1079 SurfObj
= (SURFOBJ
*)AccessUserObject((ULONG
) dc
->Surface
);
1081 XStart
+= dc
->w
.DCOrgX
;
1082 YStart
+= dc
->w
.DCOrgY
;
1085 BackgroundLeft
= XStart
;
1087 TextObj
= TEXTOBJ_LockText(dc
->w
.hFont
);
1089 if (! NT_SUCCESS(GetFontObjectsFromTextObj(TextObj
, NULL
, &FontObj
, &FontGDI
)))
1093 face
= FontGDI
->face
;
1095 if (face
->charmap
== NULL
)
1097 DPRINT("WARNING: No charmap selected!\n");
1098 DPRINT("This font face has %d charmaps\n", face
->num_charmaps
);
1100 for (n
= 0; n
< face
->num_charmaps
; n
++)
1102 charmap
= face
->charmaps
[n
];
1103 DPRINT("found charmap encoding: %u\n", charmap
->encoding
);
1104 if (charmap
->encoding
!= 0)
1110 if (!found
) DPRINT1("WARNING: Could not find desired charmap!\n");
1111 error
= FT_Set_Charmap(face
, found
);
1112 if (error
) DPRINT1("WARNING: Could not set the charmap!\n");
1115 error
= FT_Set_Pixel_Sizes(face
,
1116 /* FIXME should set character height if neg */
1117 (TextObj
->logfont
.lfHeight
< 0 ?
1118 - TextObj
->logfont
.lfHeight
:
1119 TextObj
->logfont
.lfHeight
),
1120 TextObj
->logfont
.lfWidth
);
1122 DPRINT1("Error in setting pixel sizes: %u\n", error
);
1126 // Create the brushes
1127 PalDestGDI
= PALETTE_LockPalette(dc
->w
.hPalette
);
1128 Mode
= PalDestGDI
->Mode
;
1129 PALETTE_UnlockPalette(dc
->w
.hPalette
);
1130 XlateObj
= (PXLATEOBJ
)IntEngCreateXlate(Mode
, PAL_RGB
, dc
->w
.hPalette
, NULL
);
1131 hBrushFg
= NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj
, dc
->w
.textColor
));
1132 BrushFg
= BRUSHOBJ_LockBrush(hBrushFg
);
1133 if (OPAQUE
== dc
->w
.backgroundMode
)
1135 hBrushBg
= NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj
, dc
->w
.backgroundColor
));
1138 BrushBg
= BRUSHOBJ_LockBrush(hBrushBg
);
1142 EngDeleteXlate(XlateObj
);
1146 EngDeleteXlate(XlateObj
);
1155 // Determine the yoff from the dc's w.textAlign
1156 if (dc
->w
.textAlign
& TA_BASELINE
) {
1160 if (dc
->w
.textAlign
& TA_BOTTOM
) {
1161 yoff
= -face
->size
->metrics
.descender
/ 64;
1164 yoff
= face
->size
->metrics
.ascender
/ 64;
1167 use_kerning
= FT_HAS_KERNING(face
);
1170 for(i
=0; i
<Count
; i
++)
1172 glyph_index
= FT_Get_Char_Index(face
, *String
);
1173 error
= FT_Load_Glyph(face
, glyph_index
, FT_LOAD_DEFAULT
);
1175 DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index
);
1178 glyph
= face
->glyph
;
1180 // retrieve kerning distance and move pen position
1181 if (use_kerning
&& previous
&& glyph_index
)
1184 FT_Get_Kerning(face
, previous
, glyph_index
, 0, &delta
);
1185 TextLeft
+= delta
.x
>> 6;
1188 if (glyph
->format
== ft_glyph_format_outline
)
1190 error
= FT_Render_Glyph(glyph
, ft_render_mode_mono
);
1192 DPRINT1("WARNING: Failed to render glyph!\n");
1195 pitch
= glyph
->bitmap
.pitch
;
1197 pitch
= glyph
->bitmap
.width
;
1200 if (OPAQUE
== dc
->w
.backgroundMode
)
1202 DestRect
.left
= BackgroundLeft
;
1203 DestRect
.right
= TextLeft
+ (glyph
->advance
.x
+ 32) / 64;
1204 DestRect
.top
= TextTop
+ yoff
- (face
->size
->metrics
.ascender
+ 32) / 64;
1205 DestRect
.bottom
= TextTop
+ yoff
+ (- face
->size
->metrics
.descender
+ 32) / 64;
1206 IntEngBitBlt(SurfObj
,
1217 BackgroundLeft
= DestRect
.right
;
1220 DestRect
.left
= TextLeft
;
1221 DestRect
.right
= TextLeft
+ glyph
->bitmap
.width
;
1222 DestRect
.top
= TextTop
+ yoff
- glyph
->bitmap_top
;
1223 DestRect
.bottom
= DestRect
.top
+ glyph
->bitmap
.rows
;
1225 bitSize
.cx
= glyph
->bitmap
.width
;
1226 bitSize
.cy
= glyph
->bitmap
.rows
;
1227 MaskRect
.right
= glyph
->bitmap
.width
;
1228 MaskRect
.bottom
= glyph
->bitmap
.rows
;
1230 // We should create the bitmap out of the loop at the biggest possible glyph size
1231 // Then use memset with 0 to clear it and sourcerect to limit the work of the transbitblt
1233 HSourceGlyph
= EngCreateBitmap(bitSize
, pitch
, BMF_1BPP
, 0, glyph
->bitmap
.buffer
);
1234 SourceGlyphSurf
= (PSURFOBJ
)AccessUserObject((ULONG
) HSourceGlyph
);
1236 // Use the font data as a mask to paint onto the DCs surface using a brush
1250 EngDeleteSurface(HSourceGlyph
);
1252 TextLeft
+= (glyph
->advance
.x
+ 32) / 64;
1253 previous
= glyph_index
;
1257 TEXTOBJ_UnlockText(dc
->w
.hFont
);
1258 if (NULL
!= hBrushBg
)
1260 BRUSHOBJ_UnlockBrush(hBrushBg
);
1261 NtGdiDeleteObject(hBrushBg
);
1263 BRUSHOBJ_UnlockBrush(hBrushFg
);
1264 NtGdiDeleteObject(hBrushFg
);
1269 TEXTOBJ_UnlockText( dc
->w
.hFont
);
1270 if (NULL
!= hBrushBg
)
1272 BRUSHOBJ_UnlockBrush(hBrushBg
);
1273 NtGdiDeleteObject(hBrushBg
);
1275 if (NULL
!= hBrushFg
)
1277 BRUSHOBJ_UnlockBrush(hBrushFg
);
1278 NtGdiDeleteObject(hBrushFg
);
1286 NtGdiTranslateCharsetInfo(PDWORD Src
,
1294 TextIntRealizeFont(HFONT FontHandle
)
1297 NTSTATUS Status
= STATUS_SUCCESS
;
1300 TextObj
= TEXTOBJ_LockText(FontHandle
);
1302 if (NULL
!= TextObj
)
1304 for(i
= 0; NULL
== TextObj
->GDIFontHandle
&& i
< FontsLoaded
; i
++)
1306 if (0 == wcscmp(FontTable
[i
].FaceName
, TextObj
->logfont
.lfFaceName
))
1308 TextObj
->GDIFontHandle
= FontTable
[i
].hFont
;
1312 if (NULL
== TextObj
->GDIFontHandle
)
1314 if (0 != FontsLoaded
)
1316 DPRINT("Requested font %S not found, using first available font\n",
1317 TextObj
->logfont
.lfFaceName
)
1318 TextObj
->GDIFontHandle
= FontTable
[0].hFont
;
1322 DPRINT1("Requested font %S not found, no fonts loaded at all\n",
1323 TextObj
->logfont
.lfFaceName
)
1324 Status
= STATUS_NOT_FOUND
;
1328 ASSERT(! NT_SUCCESS(Status
) || NULL
!= TextObj
->GDIFontHandle
);
1330 TEXTOBJ_UnlockText(FontHandle
);
1334 Status
= STATUS_INVALID_HANDLE
;