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.
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 + 32) / 64; // units above baseline
214 FontGDI->TextMetric.tmDescent = (- face->size->metrics.descender + 32) / 64; // 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 = SafeTm.tmAscent + SafeTm.tmDescent;
938 Status = MmCopyToCaller(tm, &SafeTm, sizeof(TEXTMETRICW));
941 TEXTOBJ_UnlockText(dc->w.hFont);
946 Status = STATUS_INVALID_HANDLE;
951 return NT_SUCCESS(Status);
956 NtGdiPolyTextOut(HDC hDC,
957 CONST LPPOLYTEXTW txt,
965 NtGdiRemoveFontResource(LPCWSTR FileName)
972 NtGdiSetMapperFlags(HDC hDC,
980 NtGdiSetTextAlign(HDC hDC,
991 prevAlign = dc->w.textAlign;
992 dc->w.textAlign = Mode;
999 NtGdiSetTextColor(HDC hDC,
1003 PDC dc = DC_LockDc(hDC);
1010 oldColor = dc->w.textColor;
1011 dc->w.textColor = color;
1018 NtGdiSetTextJustification(HDC hDC,
1027 NtGdiTextOut(HDC hDC,
1033 // Fixme: Call EngTextOut, which does the real work (calling DrvTextOut where appropriate)
1035 DC *dc = DC_LockDc(hDC);
1037 int error, glyph_index, n, i;
1040 ULONG TextLeft, TextTop, pitch, previous, BackgroundLeft;
1041 FT_Bool use_kerning;
1042 RECTL DestRect, MaskRect;
1043 POINTL SourcePoint, BrushOrigin;
1044 HBRUSH hBrushFg = NULL;
1045 PBRUSHOBJ BrushFg = NULL;
1046 HBRUSH hBrushBg = NULL;
1047 PBRUSHOBJ BrushBg = NULL;
1048 HBITMAP HSourceGlyph;
1049 PSURFOBJ SourceGlyphSurf;
1051 FT_CharMap found = 0, charmap;
1062 SurfObj = (SURFOBJ*)AccessUserObject((ULONG) dc->Surface);
1064 XStart += dc->w.DCOrgX;
1065 YStart += dc->w.DCOrgY;
1068 BackgroundLeft = XStart;
1070 TextObj = TEXTOBJ_LockText(dc->w.hFont);
1072 if (! NT_SUCCESS(GetFontObjectsFromTextObj(TextObj, NULL, &FontObj, &FontGDI)))
1076 face = FontGDI->face;
1078 if (face->charmap == NULL)
1080 DPRINT("WARNING: No charmap selected!\n");
1081 DPRINT("This font face has %d charmaps\n", face->num_charmaps);
1083 for (n = 0; n < face->num_charmaps; n++)
1085 charmap = face->charmaps[n];
1086 DPRINT("found charmap encoding: %u\n", charmap->encoding);
1087 if (charmap->encoding != 0)
1093 if (!found) DPRINT1("WARNING: Could not find desired charmap!\n");
1094 error = FT_Set_Charmap(face, found);
1095 if (error) DPRINT1("WARNING: Could not set the charmap!\n");
1098 error = FT_Set_Pixel_Sizes(face,
1099 /* FIXME should set character height if neg */
1100 (TextObj->logfont.lfHeight < 0 ?
1101 - TextObj->logfont.lfHeight :
1102 TextObj->logfont.lfHeight),
1103 TextObj->logfont.lfWidth);
1105 DPRINT1("Error in setting pixel sizes: %u\n", error);
1109 // Create the brushes
1110 PalDestGDI = PALETTE_LockPalette(dc->w.hPalette);
1111 Mode = PalDestGDI->Mode;
1112 PALETTE_UnlockPalette(dc->w.hPalette);
1113 XlateObj = (PXLATEOBJ)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
1114 hBrushFg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.textColor));
1115 BrushFg = BRUSHOBJ_LockBrush(hBrushFg);
1116 if (OPAQUE == dc->w.backgroundMode)
1118 hBrushBg = NtGdiCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.backgroundColor));
1119 BrushBg = BRUSHOBJ_LockBrush(hBrushBg);
1121 EngDeleteXlate(XlateObj);
1130 // Determine the yoff from the dc's w.textAlign
1131 if (dc->w.textAlign & TA_BASELINE) {
1135 if (dc->w.textAlign & TA_BOTTOM) {
1136 yoff = -face->size->metrics.descender / 64;
1139 yoff = face->size->metrics.ascender / 64;
1142 use_kerning = FT_HAS_KERNING(face);
1145 for(i=0; i<Count; i++)
1147 glyph_index = FT_Get_Char_Index(face, *String);
1148 error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
1150 DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
1153 glyph = face->glyph;
1155 // retrieve kerning distance and move pen position
1156 if (use_kerning && previous && glyph_index)
1159 FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
1160 TextLeft += delta.x >> 6;
1163 if (glyph->format == ft_glyph_format_outline)
1165 error = FT_Render_Glyph(glyph, ft_render_mode_mono);
1167 DPRINT1("WARNING: Failed to render glyph!\n");
1170 pitch = glyph->bitmap.pitch;
1172 pitch = glyph->bitmap.width;
1175 if (OPAQUE == dc->w.backgroundMode)
1177 DestRect.left = BackgroundLeft;
1178 DestRect.right = TextLeft + (glyph->advance.x + 32) / 64;
1179 DestRect.top = TextTop + yoff - (face->size->metrics.ascender + 32) / 64;
1180 DestRect.bottom = TextTop + yoff + (- face->size->metrics.descender + 32) / 64;
1181 IntEngBitBlt(SurfObj,
1192 BackgroundLeft = DestRect.right;
1195 DestRect.left = TextLeft;
1196 DestRect.right = TextLeft + glyph->bitmap.width;
1197 DestRect.top = TextTop + yoff - glyph->bitmap_top;
1198 DestRect.bottom = DestRect.top + glyph->bitmap.rows;
1200 bitSize.cx = glyph->bitmap.width;
1201 bitSize.cy = glyph->bitmap.rows;
1202 MaskRect.right = glyph->bitmap.width;
1203 MaskRect.bottom = glyph->bitmap.rows;
1205 // We should create the bitmap out of the loop at the biggest possible glyph size
1206 // Then use memset with 0 to clear it and sourcerect to limit the work of the transbitblt
1208 HSourceGlyph = EngCreateBitmap(bitSize, pitch, BMF_1BPP, 0, glyph->bitmap.buffer);
1209 SourceGlyphSurf = (PSURFOBJ)AccessUserObject((ULONG) HSourceGlyph);
1211 // Use the font data as a mask to paint onto the DCs surface using a brush
1225 EngDeleteSurface(HSourceGlyph);
1227 TextLeft += (glyph->advance.x + 32) / 64;
1228 previous = glyph_index;
1232 TEXTOBJ_UnlockText(dc->w.hFont);
1233 if (NULL != hBrushBg)
1235 BRUSHOBJ_UnlockBrush(hBrushBg);
1236 NtGdiDeleteObject(hBrushBg);
1238 BRUSHOBJ_UnlockBrush(hBrushFg);
1239 NtGdiDeleteObject(hBrushFg);
1244 TEXTOBJ_UnlockText( dc->w.hFont );
1245 if (NULL != hBrushBg)
1247 BRUSHOBJ_UnlockBrush(hBrushBg);
1248 NtGdiDeleteObject(hBrushBg);
1250 if (NULL != hBrushFg)
1252 BRUSHOBJ_UnlockBrush(hBrushFg);
1253 NtGdiDeleteObject(hBrushFg);
1261 NtGdiTranslateCharsetInfo(PDWORD Src,
1269 TextIntRealizeFont(HFONT FontHandle)
1272 NTSTATUS Status = STATUS_SUCCESS;
1275 TextObj = TEXTOBJ_LockText(FontHandle);
1277 if (NULL != TextObj)
1279 for(i = 0; NULL == TextObj->GDIFontHandle && i < FontsLoaded; i++)
1281 if (0 == wcscmp(FontTable[i].FaceName, TextObj->logfont.lfFaceName))
1283 TextObj->GDIFontHandle = FontTable[i].hFont;
1287 if (NULL == TextObj->GDIFontHandle)
1289 if (0 != FontsLoaded)
1291 DPRINT("Requested font %S not found, using first available font\n",
1292 TextObj->logfont.lfFaceName)
1293 TextObj->GDIFontHandle = FontTable[0].hFont;
1297 DPRINT1("Requested font %S not found, no fonts loaded at all\n",
1298 TextObj->logfont.lfFaceName)
1299 Status = STATUS_NOT_FOUND;
1303 ASSERT(! NT_SUCCESS(Status) || NULL != TextObj->GDIFontHandle);
1305 TEXTOBJ_UnlockText(FontHandle);
1309 Status = STATUS_INVALID_HANDLE;