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