WIN32K code cleanup.
[reactos.git] / reactos / subsys / win32k / objects / text.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: text.c,v 1.32 2003/05/18 17:16:18 ea Exp $ */
20
21
22 #undef WIN32_LEAN_AND_MEAN
23 #include <windows.h>
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 <ft2build.h>
31 #include FT_FREETYPE_H
32
33 #include "../eng/handle.h"
34
35 #include <include/inteng.h>
36 #include <include/text.h>
37 #include <include/eng.h>
38
39 #define NDEBUG
40 #include <win32k/debug1.h>
41
42 FT_Library library;
43
44 typedef struct _FONTTABLE {
45 HFONT hFont;
46 LPCWSTR FaceName;
47 } FONTTABLE, *PFONTTABLE;
48
49 FONTTABLE FontTable[256];
50 INT FontsLoaded = 0;
51
52 BOOL FASTCALL InitFontSupport(VOID)
53 {
54 ULONG error;
55 UINT File;
56 static WCHAR *FontFiles[] =
57 {
58 L"\\SystemRoot\\media\\fonts\\helb____.ttf",
59 L"\\SystemRoot\\media\\fonts\\timr____.ttf",
60 L"\\SystemRoot\\media\\fonts\\Vera.ttf",
61 L"\\SystemRoot\\media\\fonts\\VeraBd.ttf",
62 L"\\SystemRoot\\media\\fonts\\VeraBI.ttf",
63 L"\\SystemRoot\\media\\fonts\\VeraIt.ttf",
64 L"\\SystemRoot\\media\\fonts\\VeraMoBd.ttf",
65 L"\\SystemRoot\\media\\fonts\\VeraMoBI.ttf",
66 L"\\SystemRoot\\media\\fonts\\VeraMoIt.ttf",
67 L"\\SystemRoot\\media\\fonts\\VeraMono.ttf",
68 L"\\SystemRoot\\media\\fonts\\VeraSe.ttf",
69 L"\\SystemRoot\\media\\fonts\\VeraSeBd.ttf"
70 };
71
72 error = FT_Init_FreeType(&library);
73 if(error)
74 {
75 return FALSE;
76 }
77
78 for (File = 0; File < sizeof(FontFiles) / sizeof(WCHAR *); File++)
79 {
80 DPRINT("Loading font %S\n", FontFiles[File]);
81
82 W32kAddFontResource(FontFiles[File]);
83 }
84
85 DPRINT("All fonts loaded\n");
86
87 return TRUE;
88 }
89
90 static NTSTATUS STDCALL
91 GetFontObjectsFromTextObj(PTEXTOBJ TextObj, HFONT *FontHandle, PFONTOBJ *FontObj, PFONTGDI *FontGDI)
92 {
93 NTSTATUS Status = STATUS_SUCCESS;
94
95 ASSERT(NULL != TextObj && NULL != TextObj->GDIFontHandle);
96 if (NULL != TextObj && NULL != TextObj->GDIFontHandle)
97 {
98 if (NT_SUCCESS(Status) && NULL != FontHandle)
99 {
100 *FontHandle = TextObj->GDIFontHandle;
101 }
102 if (NT_SUCCESS(Status) && NULL != FontObj)
103 {
104 *FontObj = AccessUserObject((ULONG) TextObj->GDIFontHandle);
105 if (NULL == *FontObj)
106 {
107 ASSERT(FALSE);
108 Status = STATUS_INVALID_HANDLE;
109 }
110 }
111 if (NT_SUCCESS(Status) && NULL != FontGDI)
112 {
113 *FontGDI = AccessInternalObject((ULONG) TextObj->GDIFontHandle);
114 if (NULL == *FontGDI)
115 {
116 ASSERT(FALSE);
117 Status = STATUS_INVALID_HANDLE;
118 }
119 }
120 }
121 else
122 {
123 Status = STATUS_INVALID_HANDLE;
124 }
125
126 return Status;
127 }
128
129 int
130 STDCALL
131 W32kAddFontResource(LPCWSTR Filename)
132 {
133 HFONT NewFont;
134 PFONTOBJ FontObj;
135 PFONTGDI FontGDI;
136 UNICODE_STRING uFileName;
137 NTSTATUS Status;
138 HANDLE FileHandle;
139 OBJECT_ATTRIBUTES ObjectAttributes;
140 FILE_STANDARD_INFORMATION FileStdInfo;
141 PVOID buffer;
142 ULONG size;
143 INT error;
144 FT_Face face;
145 ANSI_STRING StringA;
146 UNICODE_STRING StringU;
147 IO_STATUS_BLOCK Iosb;
148
149 NewFont = (HFONT)CreateGDIHandle(sizeof( FONTGDI ), sizeof( FONTOBJ ));
150 FontObj = (PFONTOBJ) AccessUserObject( (ULONG) NewFont );
151 FontGDI = (PFONTGDI) AccessInternalObject( (ULONG) NewFont );
152
153 RtlCreateUnicodeString(&uFileName, (LPWSTR)Filename);
154
155 // Open the Module
156 InitializeObjectAttributes(&ObjectAttributes, &uFileName, 0, NULL, NULL);
157
158 Status = NtOpenFile(&FileHandle, FILE_ALL_ACCESS, &ObjectAttributes, &Iosb, 0, 0);
159
160 if (!NT_SUCCESS(Status))
161 {
162 DPRINT1("Could not open module file: %S\n", Filename);
163 return 0;
164 }
165
166 // Get the size of the file
167 Status = NtQueryInformationFile(FileHandle, &Iosb, &FileStdInfo, sizeof(FileStdInfo), FileStandardInformation);
168 if (!NT_SUCCESS(Status))
169 {
170 DPRINT1("Could not get file size\n");
171 return 0;
172 }
173
174 // Allocate nonpageable memory for driver
175 size = FileStdInfo.EndOfFile.u.LowPart;
176 buffer = ExAllocatePool(NonPagedPool, size);
177
178 if (buffer == NULL)
179 {
180 DPRINT1("could not allocate memory for module");
181 return 0;
182 }
183
184 // Load driver into memory chunk
185 Status = NtReadFile(FileHandle, 0, 0, 0, &Iosb, buffer, FileStdInfo.EndOfFile.u.LowPart, 0, 0);
186 if (!NT_SUCCESS(Status))
187 {
188 DPRINT1("could not read module file into memory");
189 ExFreePool(buffer);
190 return 0;
191 }
192
193 NtClose(FileHandle);
194
195 error = FT_New_Memory_Face(library, buffer, size, 0, &face);
196 if (error == FT_Err_Unknown_File_Format)
197 {
198 DPRINT1("Unknown font file format\n");
199 return 0;
200 }
201 else if (error)
202 {
203 DPRINT1("Error reading font file (error code: %u)\n", error); // 48
204 return 0;
205 }
206
207 // FontGDI->Filename = Filename; perform strcpy
208 FontGDI->face = face;
209
210 // FIXME: Complete text metrics
211 FontGDI->TextMetric.tmAscent = face->size->metrics.ascender; // units above baseline
212 FontGDI->TextMetric.tmDescent = face->size->metrics.descender; // units below baseline
213 FontGDI->TextMetric.tmHeight = FontGDI->TextMetric.tmAscent + FontGDI->TextMetric.tmDescent;
214
215 DPRINT("Font loaded: %s (%s)\n", face->family_name, face->style_name);
216 DPRINT("Num glyphs: %u\n", face->num_glyphs);
217
218 // Add this font resource to the font table
219 FontTable[FontsLoaded].hFont = NewFont;
220
221 RtlInitAnsiString(&StringA, (LPSTR)face->family_name);
222 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
223 FontTable[FontsLoaded].FaceName = ExAllocatePool(NonPagedPool, (StringU.Length + 1) * 2);
224 wcscpy((LPWSTR)FontTable[FontsLoaded].FaceName, StringU.Buffer);
225 RtlFreeUnicodeString(&StringU);
226
227 FontsLoaded++;
228
229 return 1;
230 }
231
232 NTSTATUS FASTCALL
233 TextIntCreateFontIndirect(CONST LPLOGFONTW lf, HFONT *NewFont)
234 {
235 PTEXTOBJ TextObj;
236 NTSTATUS Status = STATUS_SUCCESS;
237
238 *NewFont = TEXTOBJ_AllocText();
239 if (NULL != *NewFont)
240 {
241 TextObj = TEXTOBJ_LockText(*NewFont);
242 if (NULL != TextObj)
243 {
244 memcpy(&TextObj->logfont, lf, sizeof(LOGFONTW));
245 if (lf->lfEscapement != lf->lfOrientation)
246 {
247 /* this should really depend on whether GM_ADVANCED is set */
248 TextObj->logfont.lfOrientation = TextObj->logfont.lfEscapement;
249 }
250 TEXTOBJ_UnlockText(*NewFont);
251 }
252 else
253 {
254 ASSERT(FALSE);
255 Status = STATUS_INVALID_HANDLE;
256 }
257 }
258 else
259 {
260 Status = STATUS_NO_MEMORY;
261 }
262
263 return Status;
264 }
265
266 HFONT
267 STDCALL
268 W32kCreateFont(int Height,
269 int Width,
270 int Escapement,
271 int Orientation,
272 int Weight,
273 DWORD Italic,
274 DWORD Underline,
275 DWORD StrikeOut,
276 DWORD CharSet,
277 DWORD OutputPrecision,
278 DWORD ClipPrecision,
279 DWORD Quality,
280 DWORD PitchAndFamily,
281 LPCWSTR Face)
282 {
283 LOGFONTW logfont;
284 HFONT NewFont;
285 NTSTATUS Status = STATUS_SUCCESS;
286
287 logfont.lfHeight = Height;
288 logfont.lfWidth = Width;
289 logfont.lfEscapement = Escapement;
290 logfont.lfOrientation = Orientation;
291 logfont.lfWeight = Weight;
292 logfont.lfItalic = Italic;
293 logfont.lfUnderline = Underline;
294 logfont.lfStrikeOut = StrikeOut;
295 logfont.lfCharSet = CharSet;
296 logfont.lfOutPrecision = OutputPrecision;
297 logfont.lfClipPrecision = ClipPrecision;
298 logfont.lfQuality = Quality;
299 logfont.lfPitchAndFamily = PitchAndFamily;
300
301 if (NULL != Face)
302 {
303 Status = MmCopyFromCaller(logfont.lfFaceName, Face, sizeof(logfont.lfFaceName));
304 }
305 else
306 {
307 logfont.lfFaceName[0] = L'\0';
308 }
309
310 if (NT_SUCCESS(Status))
311 {
312 Status = TextIntCreateFontIndirect(&logfont, &NewFont);
313 }
314
315 return NT_SUCCESS(Status) ? NewFont : NULL;
316 }
317
318 HFONT
319 STDCALL
320 W32kCreateFontIndirect(CONST LPLOGFONTW lf)
321 {
322 LOGFONTW SafeLogfont;
323 HFONT NewFont;
324 NTSTATUS Status = STATUS_SUCCESS;
325
326 if (NULL != lf)
327 {
328 Status = MmCopyFromCaller(&SafeLogfont, lf, sizeof(LOGFONTW));
329 if (NT_SUCCESS(Status))
330 {
331 Status = TextIntCreateFontIndirect(&SafeLogfont, &NewFont);
332 }
333 }
334 else
335 {
336 Status = STATUS_INVALID_PARAMETER;
337 }
338
339 return NT_SUCCESS(Status) ? NewFont : NULL;
340 }
341
342 BOOL
343 STDCALL
344 W32kCreateScalableFontResource(DWORD Hidden,
345 LPCWSTR FontRes,
346 LPCWSTR FontFile,
347 LPCWSTR CurrentPath)
348 {
349 UNIMPLEMENTED;
350 }
351
352 int
353 STDCALL
354 W32kEnumFontFamilies(HDC hDC,
355 LPCWSTR Family,
356 FONTENUMPROCW EnumFontFamProc,
357 LPARAM lParam)
358 {
359 UNIMPLEMENTED;
360 }
361
362 int
363 STDCALL
364 W32kEnumFontFamiliesEx(HDC hDC,
365 LPLOGFONTW Logfont,
366 FONTENUMPROCW EnumFontFamExProc,
367 LPARAM lParam,
368 DWORD Flags)
369 {
370 UNIMPLEMENTED;
371 }
372
373 int
374 STDCALL
375 W32kEnumFonts(HDC hDC,
376 LPCWSTR FaceName,
377 FONTENUMPROCW FontFunc,
378 LPARAM lParam)
379 {
380 UNIMPLEMENTED;
381 }
382
383 BOOL
384 STDCALL
385 W32kExtTextOut(HDC hDC,
386 int X,
387 int Y,
388 UINT Options,
389 CONST LPRECT rc,
390 LPCWSTR String,
391 UINT Count,
392 CONST LPINT Dx)
393 {
394 UNIMPLEMENTED;
395 }
396
397 BOOL
398 STDCALL
399 W32kGetAspectRatioFilterEx(HDC hDC,
400 LPSIZE AspectRatio)
401 {
402 UNIMPLEMENTED;
403 }
404
405 BOOL
406 STDCALL
407 W32kGetCharABCWidths(HDC hDC,
408 UINT FirstChar,
409 UINT LastChar,
410 LPABC abc)
411 {
412 UNIMPLEMENTED;
413 }
414
415 BOOL
416 STDCALL
417 W32kGetCharABCWidthsFloat(HDC hDC,
418 UINT FirstChar,
419 UINT LastChar,
420 LPABCFLOAT abcF)
421 {
422 UNIMPLEMENTED;
423 }
424
425 DWORD
426 STDCALL
427 W32kGetCharacterPlacement(HDC hDC,
428 LPCWSTR String,
429 int Count,
430 int MaxExtent,
431 LPGCP_RESULTS Results,
432 DWORD Flags)
433 {
434 UNIMPLEMENTED;
435 }
436
437 BOOL
438 STDCALL
439 W32kGetCharWidth(HDC hDC,
440 UINT FirstChar,
441 UINT LastChar,
442 LPINT Buffer)
443 {
444 UNIMPLEMENTED;
445 }
446
447 BOOL
448 STDCALL
449 W32kGetCharWidth32(HDC hDC,
450 UINT FirstChar,
451 UINT LastChar,
452 LPINT Buffer)
453 {
454 UNIMPLEMENTED;
455 }
456
457 BOOL
458 STDCALL
459 W32kGetCharWidthFloat(HDC hDC,
460 UINT FirstChar,
461 UINT LastChar,
462 PFLOAT Buffer)
463 {
464 UNIMPLEMENTED;
465 }
466
467 DWORD
468 STDCALL
469 W32kGetFontLanguageInfo(HDC hDC)
470 {
471 UNIMPLEMENTED;
472 }
473
474 DWORD
475 STDCALL
476 W32kGetGlyphOutline(HDC hDC,
477 UINT Char,
478 UINT Format,
479 LPGLYPHMETRICS gm,
480 DWORD Bufsize,
481 LPVOID Buffer,
482 CONST LPMAT2 mat2)
483 {
484 UNIMPLEMENTED;
485
486
487 }
488
489 DWORD
490 STDCALL
491 W32kGetKerningPairs(HDC hDC,
492 DWORD NumPairs,
493 LPKERNINGPAIR krnpair)
494 {
495 UNIMPLEMENTED;
496 }
497
498 UINT
499 STDCALL
500 W32kGetOutlineTextMetrics(HDC hDC,
501 UINT Data,
502 LPOUTLINETEXTMETRICW otm)
503 {
504 UNIMPLEMENTED;
505 }
506
507 BOOL
508 STDCALL
509 W32kGetRasterizerCaps(LPRASTERIZER_STATUS rs,
510 UINT Size)
511 {
512 UNIMPLEMENTED;
513 }
514
515 UINT
516 STDCALL
517 W32kGetTextCharset(HDC hDC)
518 {
519 UNIMPLEMENTED;
520 }
521
522 UINT
523 STDCALL
524 W32kGetTextCharsetInfo(HDC hDC,
525 LPFONTSIGNATURE Sig,
526 DWORD Flags)
527 {
528 UNIMPLEMENTED;
529 }
530
531 BOOL
532 STDCALL
533 W32kGetTextExtentExPoint(HDC hDC,
534 LPCWSTR String,
535 int Count,
536 int MaxExtent,
537 LPINT Fit,
538 LPINT Dx,
539 LPSIZE Size)
540 {
541 UNIMPLEMENTED;
542 }
543
544 BOOL
545 STDCALL
546 W32kGetTextExtentPoint(HDC hDC,
547 LPCWSTR String,
548 int Count,
549 LPSIZE Size)
550 {
551 PDC dc = (PDC)AccessUserObject((ULONG) hDC);
552 PFONTGDI FontGDI;
553 FT_Face face;
554 FT_GlyphSlot glyph;
555 INT error, pitch, glyph_index, i;
556 ULONG TotalWidth = 0, MaxHeight = 0, CurrentChar = 0, SpaceBetweenChars = 5;
557
558 FontGDI = (PFONTGDI)AccessInternalObject((ULONG) dc->w.hFont);
559
560 for(i=0; i<Count; i++)
561 {
562 glyph_index = FT_Get_Char_Index(face, *String);
563 error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
564 if(error) DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
565 glyph = face->glyph;
566
567 if (glyph->format == ft_glyph_format_outline)
568 {
569 error = FT_Render_Glyph(glyph, ft_render_mode_mono);
570 if(error) DPRINT1("WARNING: Failed to render glyph!\n");
571 pitch = glyph->bitmap.pitch;
572 } else {
573 pitch = glyph->bitmap.width;
574 }
575
576 TotalWidth += pitch-1;
577 if((glyph->bitmap.rows-1) > MaxHeight) MaxHeight = glyph->bitmap.rows-1;
578
579 CurrentChar++;
580
581 if(CurrentChar < Size->cx) TotalWidth += SpaceBetweenChars;
582 String++;
583 }
584
585 Size->cx = TotalWidth;
586 Size->cy = MaxHeight;
587 }
588
589 BOOL
590 STDCALL
591 W32kGetTextExtentPoint32(HDC hDC,
592 LPCWSTR String,
593 int Count,
594 LPSIZE Size)
595 {
596 UNIMPLEMENTED;
597 }
598
599 int
600 STDCALL
601 W32kGetTextFace(HDC hDC,
602 int Count,
603 LPWSTR FaceName)
604 {
605 UNIMPLEMENTED;
606 }
607
608 BOOL
609 STDCALL
610 W32kGetTextMetrics(HDC hDC,
611 LPTEXTMETRICW tm)
612 {
613 PDC dc;
614 PTEXTOBJ TextObj;
615 PFONTGDI FontGDI;
616 NTSTATUS Status = STATUS_SUCCESS;
617 TEXTMETRICW SafeTm;
618 FT_Face Face;
619 ULONG Error;
620
621 dc = DC_HandleToPtr(hDC);
622 if (NULL == dc || NULL == tm)
623 {
624 Status = STATUS_INVALID_PARAMETER;
625 }
626 else
627 {
628 TextObj = TEXTOBJ_LockText(dc->w.hFont);
629 if (NULL != TextObj)
630 {
631 Status = GetFontObjectsFromTextObj(TextObj, NULL, NULL, &FontGDI);
632 if (NT_SUCCESS(Status))
633 {
634 Face = FontGDI->face;
635 Error = FT_Set_Pixel_Sizes(Face, TextObj->logfont.lfHeight,
636 TextObj->logfont.lfWidth);
637 if (0 != Error)
638 {
639 DPRINT1("Error in setting pixel sizes: %u\n", Error);
640 Status = STATUS_UNSUCCESSFUL;
641 }
642 else
643 {
644 memcpy(&SafeTm, &FontGDI->TextMetric, sizeof(TEXTMETRICW));
645 SafeTm.tmAscent = (Face->size->metrics.ascender + 32) / 64; // units above baseline
646 SafeTm.tmDescent = (Face->size->metrics.descender + 32) / 64; // units below baseline
647 SafeTm.tmHeight = (Face->size->metrics.ascender +
648 Face->size->metrics.descender + 32) / 64;
649 Status = MmCopyToCaller(tm, &SafeTm, sizeof(TEXTMETRICW));
650 }
651 }
652 TEXTOBJ_UnlockText(dc->w.hFont);
653 }
654 else
655 {
656 ASSERT(FALSE);
657 Status = STATUS_INVALID_HANDLE;
658 }
659 DC_ReleasePtr(hDC);
660 }
661
662 return NT_SUCCESS(Status);
663 }
664
665 BOOL
666 STDCALL
667 W32kPolyTextOut(HDC hDC,
668 CONST LPPOLYTEXT txt,
669 int Count)
670 {
671 UNIMPLEMENTED;
672 }
673
674 BOOL
675 STDCALL
676 W32kRemoveFontResource(LPCWSTR FileName)
677 {
678 UNIMPLEMENTED;
679 }
680
681 DWORD
682 STDCALL
683 W32kSetMapperFlags(HDC hDC,
684 DWORD Flag)
685 {
686 UNIMPLEMENTED;
687 }
688
689 UINT
690 STDCALL
691 W32kSetTextAlign(HDC hDC,
692 UINT Mode)
693 {
694 UINT prevAlign;
695 DC *dc;
696
697 dc = DC_HandleToPtr(hDC);
698 if (!dc)
699 {
700 return 0;
701 }
702 prevAlign = dc->w.textAlign;
703 dc->w.textAlign = Mode;
704 DC_ReleasePtr( hDC );
705 return prevAlign;
706 }
707
708 COLORREF
709 STDCALL
710 W32kSetTextColor(HDC hDC,
711 COLORREF color)
712 {
713 COLORREF oldColor;
714 PDC dc = DC_HandleToPtr(hDC);
715
716 if (!dc)
717 {
718 return 0x80000000;
719 }
720
721 oldColor = dc->w.textColor;
722 dc->w.textColor = color;
723 DC_ReleasePtr( hDC );
724 return oldColor;
725 }
726
727 BOOL
728 STDCALL
729 W32kSetTextJustification(HDC hDC,
730 int BreakExtra,
731 int BreakCount)
732 {
733 UNIMPLEMENTED;
734 }
735
736 BOOL
737 STDCALL
738 W32kTextOut(HDC hDC,
739 int XStart,
740 int YStart,
741 LPCWSTR String,
742 int Count)
743 {
744 // Fixme: Call EngTextOut, which does the real work (calling DrvTextOut where appropriate)
745
746 DC *dc = DC_HandleToPtr(hDC);
747 SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject((ULONG) dc->Surface);
748 int error, glyph_index, n, i;
749 FT_Face face;
750 FT_GlyphSlot glyph;
751 ULONG TextLeft, TextTop, pitch, previous;
752 FT_Bool use_kerning;
753 RECTL DestRect, MaskRect;
754 POINTL SourcePoint, BrushOrigin;
755 HBRUSH hBrush = NULL;
756 PBRUSHOBJ Brush = NULL;
757 HBITMAP HSourceGlyph;
758 PSURFOBJ SourceGlyphSurf;
759 SIZEL bitSize;
760 FT_CharMap found = 0, charmap;
761 INT yoff;
762 PFONTOBJ FontObj;
763 PFONTGDI FontGDI;
764 PTEXTOBJ TextObj;
765 PPALGDI PalDestGDI;
766 PXLATEOBJ XlateObj;
767
768 if( !dc )
769 return FALSE;
770
771 XStart += dc->w.DCOrgX;
772 YStart += dc->w.DCOrgY;
773 TextLeft = XStart;
774 TextTop = YStart;
775
776 TextObj = TEXTOBJ_LockText(dc->w.hFont);
777
778 if (! NT_SUCCESS(GetFontObjectsFromTextObj(TextObj, NULL, &FontObj, &FontGDI)))
779 {
780 goto fail;
781 }
782 face = FontGDI->face;
783
784 if (face->charmap == NULL)
785 {
786 DPRINT("WARNING: No charmap selected!\n");
787 DPRINT("This font face has %d charmaps\n", face->num_charmaps);
788
789 for (n = 0; n < face->num_charmaps; n++)
790 {
791 charmap = face->charmaps[n];
792 DPRINT("found charmap encoding: %u\n", charmap->encoding);
793 if (charmap->encoding != 0)
794 {
795 found = charmap;
796 break;
797 }
798 }
799 if (!found) DPRINT1("WARNING: Could not find desired charmap!\n");
800 error = FT_Set_Charmap(face, found);
801 if (error) DPRINT1("WARNING: Could not set the charmap!\n");
802 }
803
804 error = FT_Set_Pixel_Sizes(face, TextObj->logfont.lfHeight, TextObj->logfont.lfWidth);
805 if(error) {
806 DPRINT1("Error in setting pixel sizes: %u\n", error);
807 goto fail;
808 }
809
810 // Create the brush
811 PalDestGDI = (PPALGDI)AccessInternalObject((ULONG) dc->w.hPalette);
812 XlateObj = (PXLATEOBJ)IntEngCreateXlate(PalDestGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
813 hBrush = W32kCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.textColor));
814 Brush = BRUSHOBJ_LockBrush(hBrush);
815 EngDeleteXlate(XlateObj);
816
817 SourcePoint.x = 0;
818 SourcePoint.y = 0;
819 MaskRect.left = 0;
820 MaskRect.top = 0;
821 BrushOrigin.x = 0;
822 BrushOrigin.y = 0;
823
824 // Determine the yoff from the dc's w.textAlign
825 if (dc->w.textAlign & TA_BASELINE) {
826 yoff = 0;
827 }
828 else
829 if (dc->w.textAlign & TA_BOTTOM) {
830 yoff = -face->size->metrics.descender / 64;
831 }
832 else { // TA_TOP
833 yoff = face->size->metrics.ascender / 64;
834 }
835
836 use_kerning = FT_HAS_KERNING(face);
837 previous = 0;
838
839 for(i=0; i<Count; i++)
840 {
841 glyph_index = FT_Get_Char_Index(face, *String);
842 error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
843 if(error) {
844 DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
845 goto fail;
846 }
847 glyph = face->glyph;
848
849 // retrieve kerning distance and move pen position
850 if (use_kerning && previous && glyph_index)
851 {
852 FT_Vector delta;
853 FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
854 TextLeft += delta.x >> 6;
855 }
856
857 if (glyph->format == ft_glyph_format_outline)
858 {
859 error = FT_Render_Glyph(glyph, ft_render_mode_mono);
860 if(error) {
861 DPRINT1("WARNING: Failed to render glyph!\n");
862 goto fail;
863 }
864 pitch = glyph->bitmap.pitch;
865 } else {
866 pitch = glyph->bitmap.width;
867 }
868
869 DestRect.left = TextLeft;
870 DestRect.top = TextTop + yoff - glyph->bitmap_top;
871 DestRect.right = TextLeft + glyph->bitmap.width;
872 DestRect.bottom = DestRect.top + glyph->bitmap.rows;
873 bitSize.cx = pitch;
874 bitSize.cy = glyph->bitmap.rows;
875 MaskRect.right = glyph->bitmap.width;
876 MaskRect.bottom = glyph->bitmap.rows;
877
878 // We should create the bitmap out of the loop at the biggest possible glyph size
879 // Then use memset with 0 to clear it and sourcerect to limit the work of the transbitblt
880
881 HSourceGlyph = EngCreateBitmap(bitSize, pitch, BMF_1BPP, 0, glyph->bitmap.buffer);
882 SourceGlyphSurf = (PSURFOBJ)AccessUserObject((ULONG) HSourceGlyph);
883
884 // Use the font data as a mask to paint onto the DCs surface using a brush
885 IntEngBitBlt(SurfObj, NULL, SourceGlyphSurf, NULL, NULL, &DestRect, &SourcePoint, &MaskRect, Brush, &BrushOrigin, 0xAACC);
886
887 EngDeleteSurface(HSourceGlyph);
888
889 TextLeft += glyph->advance.x >> 6;
890 previous = glyph_index;
891
892 String++;
893 }
894 TEXTOBJ_UnlockText( dc->w.hFont );
895 BRUSHOBJ_UnlockBrush(hBrush);
896 W32kDeleteObject( hBrush );
897 DC_ReleasePtr( hDC );
898 return TRUE;
899
900 fail:
901 TEXTOBJ_UnlockText( dc->w.hFont );
902 if( hBrush ){
903 BRUSHOBJ_UnlockBrush(hBrush);
904 W32kDeleteObject( hBrush );
905 }
906 DC_ReleasePtr( hDC );
907 return FALSE;
908 }
909
910 UINT
911 STDCALL
912 W32kTranslateCharsetInfo(PDWORD Src,
913 LPCHARSETINFO CSI,
914 DWORD Flags)
915 {
916 UNIMPLEMENTED;
917 }
918
919 NTSTATUS FASTCALL
920 TextIntRealizeFont(HFONT FontHandle)
921 {
922 UINT i;
923 NTSTATUS Status = STATUS_SUCCESS;
924 PTEXTOBJ TextObj;
925
926 TextObj = TEXTOBJ_LockText(FontHandle);
927 ASSERT(TextObj);
928 if (NULL != TextObj)
929 {
930 for(i = 0; NULL == TextObj->GDIFontHandle && i < FontsLoaded; i++)
931 {
932 if (0 == wcscmp(FontTable[i].FaceName, TextObj->logfont.lfFaceName))
933 {
934 TextObj->GDIFontHandle = FontTable[i].hFont;
935 }
936 }
937
938 if (NULL == TextObj->GDIFontHandle)
939 {
940 if (0 != FontsLoaded)
941 {
942 DPRINT("Requested font %S not found, using first available font\n",
943 TextObj->logfont.lfFaceName)
944 TextObj->GDIFontHandle = FontTable[0].hFont;
945 }
946 else
947 {
948 DPRINT1("Requested font %S not found, no fonts loaded at all\n",
949 TextObj->logfont.lfFaceName)
950 Status = STATUS_NOT_FOUND;
951 }
952 }
953
954 ASSERT(! NT_SUCCESS(Status) || NULL != TextObj->GDIFontHandle);
955
956 TEXTOBJ_UnlockText(FontHandle);
957 }
958 else
959 {
960 Status = STATUS_INVALID_HANDLE;
961 }
962
963 return Status;
964 }
965
966 /* EOF */