3 #undef WIN32_LEAN_AND_MEAN
7 #include <win32k/text.h>
8 #include <win32k/kapi.h>
9 #include <freetype/freetype.h>
11 #include "../eng/handle.h"
14 #include <win32k/debug1.h>
18 typedef struct _FONTTABLE {
21 } FONTTABLE, *PFONTTABLE;
23 FONTTABLE FontTable[256];
26 BOOL InitFontSupport()
30 error = FT_Init_FreeType(&library);
36 W32kAddFontResource(L"\\SystemRoot\\media\\fonts\\helb____.ttf");
37 W32kAddFontResource(L"\\SystemRoot\\media\\fonts\\timr____.ttf");
39 DbgPrint("All fonts loaded\n");
46 W32kAddFontResource(LPCWSTR Filename)
51 UNICODE_STRING uFileName;
54 OBJECT_ATTRIBUTES ObjectAttributes;
55 FILE_STANDARD_INFORMATION FileStdInfo;
61 UNICODE_STRING StringU;
64 NewFont = (HFONT)CreateGDIHandle(sizeof( FONTGDI ), sizeof( FONTOBJ ));
65 FontObj = (PFONTOBJ) AccessUserObject( NewFont );
66 FontGDI = (PFONTGDI) AccessInternalObject( NewFont );
68 RtlCreateUnicodeString(&uFileName, (LPWSTR)Filename);
71 InitializeObjectAttributes(&ObjectAttributes, &uFileName, 0, NULL, NULL);
73 Status = NtOpenFile(&FileHandle, FILE_ALL_ACCESS, &ObjectAttributes, &Iosb, 0, 0);
75 if (!NT_SUCCESS(Status))
77 DbgPrint("Could not open module file: %S\n", Filename);
81 // Get the size of the file
82 Status = NtQueryInformationFile(FileHandle, &Iosb, &FileStdInfo, sizeof(FileStdInfo), FileStandardInformation);
83 if (!NT_SUCCESS(Status))
85 DbgPrint("Could not get file size\n");
89 // Allocate nonpageable memory for driver
90 size = FileStdInfo.EndOfFile.u.LowPart;
91 buffer = ExAllocatePool(NonPagedPool, size);
95 DbgPrint("could not allocate memory for module");
99 // Load driver into memory chunk
100 Status = NtReadFile(FileHandle, 0, 0, 0, &Iosb, buffer, FileStdInfo.EndOfFile.u.LowPart, 0, 0);
101 if (!NT_SUCCESS(Status))
103 DbgPrint("could not read module file into memory");
110 error = FT_New_Memory_Face(library, buffer, size, 0, &face);
111 if (error == FT_Err_Unknown_File_Format)
113 DbgPrint("Unknown font file format\n");
118 DbgPrint("Error reading font file (error code: %u)\n", error); // 48
122 // FontGDI->Filename = Filename; perform strcpy
123 FontGDI->face = face;
125 // FIXME: Complete text metrics
126 FontGDI->TextMetric.tmAscent = face->size->metrics.ascender; // units above baseline
127 FontGDI->TextMetric.tmDescent = face->size->metrics.descender; // units below baseline
128 FontGDI->TextMetric.tmHeight = FontGDI->TextMetric.tmAscent + FontGDI->TextMetric.tmDescent;
130 DbgPrint("Family name: %s\n", face->family_name);
131 DbgPrint("Style name: %s\n", face->style_name);
132 DbgPrint("Num glyphs: %u\n", face->num_glyphs);
134 // Add this font resource to the font table
135 FontTable[FontsLoaded].hFont = NewFont;
137 RtlInitAnsiString(&StringA, (LPSTR)face->family_name);
138 RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE);
139 FontTable[FontsLoaded].FaceName = ExAllocatePool(NonPagedPool, (StringU.Length + 1) * 2);
140 wcscpy((LPWSTR)FontTable[FontsLoaded].FaceName, StringU.Buffer);
141 RtlFreeUnicodeString(&StringU);
150 W32kCreateFont(int Height,
159 DWORD OutputPrecision,
162 DWORD PitchAndFamily,
167 logfont.lfHeight = Height;
168 logfont.lfWidth = Width;
169 logfont.lfEscapement = Escapement;
170 logfont.lfOrientation = Orientation;
171 logfont.lfWeight = Weight;
172 logfont.lfItalic = Italic;
173 logfont.lfUnderline = Underline;
174 logfont.lfStrikeOut = StrikeOut;
175 logfont.lfCharSet = CharSet;
176 logfont.lfOutPrecision = OutputPrecision;
177 logfont.lfClipPrecision = ClipPrecision;
178 logfont.lfQuality = Quality;
179 logfont.lfPitchAndFamily = PitchAndFamily;
182 memcpy(logfont.lfFaceName, Face, sizeof(logfont.lfFaceName));
184 logfont.lfFaceName[0] = '\0';
186 return W32kCreateFontIndirect(&logfont);
191 W32kCreateFontIndirect(CONST LPLOGFONT lf)
198 if(hFont = TEXTOBJ_AllocText())
200 fontPtr = TEXTOBJ_LockText( hFont );
201 ASSERT( fontPtr ); //I want to know when this happens
203 memcpy(&fontPtr->logfont, lf, sizeof(LOGFONT));
205 if (lf->lfEscapement != lf->lfOrientation) {
206 /* this should really depend on whether GM_ADVANCED is set */
207 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
209 TEXTOBJ_UnlockText( hFont );
219 W32kCreateScalableFontResource(DWORD Hidden,
229 W32kEnumFontFamilies(HDC hDC,
231 FONTENUMPROC EnumFontFamProc,
239 W32kEnumFontFamiliesEx(HDC hDC,
241 FONTENUMPROC EnumFontFamExProc,
250 W32kEnumFonts(HDC hDC,
252 FONTENUMPROC FontFunc,
260 W32kExtTextOut(HDC hDC,
274 W32kGetAspectRatioFilterEx(HDC hDC,
282 W32kGetCharABCWidths(HDC hDC,
292 W32kGetCharABCWidthsFloat(HDC hDC,
302 W32kGetCharacterPlacement(HDC hDC,
306 LPGCP_RESULTS Results,
314 W32kGetCharWidth(HDC hDC,
324 W32kGetCharWidth32(HDC hDC,
334 W32kGetCharWidthFloat(HDC hDC,
344 W32kGetFontLanguageInfo(HDC hDC)
351 W32kGetGlyphOutline(HDC hDC,
366 W32kGetKerningPairs(HDC hDC,
368 LPKERNINGPAIR krnpair)
375 W32kGetOutlineTextMetrics(HDC hDC,
377 LPOUTLINETEXTMETRIC otm)
384 W32kGetRasterizerCaps(LPRASTERIZER_STATUS rs,
392 W32kGetTextCharset(HDC hDC)
399 W32kGetTextCharsetInfo(HDC hDC,
408 W32kGetTextExtentExPoint(HDC hDC,
421 W32kGetTextExtentPoint(HDC hDC,
426 PDC dc = (PDC)AccessUserObject(hDC);
430 INT error, pitch, glyph_index, i;
431 ULONG TotalWidth = 0, MaxHeight = 0, CurrentChar = 0, SpaceBetweenChars = 5;
433 FontGDI = (PFONTGDI)AccessInternalObject(dc->w.hFont);
435 for(i=0; i<Count; i++)
437 glyph_index = FT_Get_Char_Index(face, *String);
438 error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
439 if(error) DbgPrint("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
442 if (glyph->format == ft_glyph_format_outline)
444 error = FT_Render_Glyph(glyph, ft_render_mode_mono);
445 if(error) DbgPrint("WARNING: Failed to render glyph!\n");
446 pitch = glyph->bitmap.pitch;
448 pitch = glyph->bitmap.width;
451 TotalWidth += pitch-1;
452 if((glyph->bitmap.rows-1) > MaxHeight) MaxHeight = glyph->bitmap.rows-1;
456 if(CurrentChar < Size->cx) TotalWidth += SpaceBetweenChars;
460 Size->cx = TotalWidth;
461 Size->cy = MaxHeight;
466 W32kGetTextExtentPoint32(HDC hDC,
476 W32kGetTextFace(HDC hDC,
485 W32kGetTextMetrics(HDC hDC,
488 PDC dc = (PDC)AccessUserObject(hDC);
491 FontGDI = (PFONTGDI)AccessInternalObject(dc->w.hFont);
492 memcpy(tm, &FontGDI->TextMetric, sizeof(TEXTMETRIC));
499 W32kPolyTextOut(HDC hDC,
500 CONST LPPOLYTEXT txt,
508 W32kRemoveFontResource(LPCWSTR FileName)
515 W32kSetMapperFlags(HDC hDC,
523 W32kSetTextAlign(HDC hDC,
529 dc = DC_HandleToPtr(hDC);
534 prevAlign = dc->w.textAlign;
535 dc->w.textAlign = Mode;
536 DC_ReleasePtr( hDC );
542 W32kSetTextColor(HDC hDC,
546 PDC dc = DC_HandleToPtr(hDC);
553 oldColor = dc->w.textColor;
554 dc->w.textColor = color;
555 DC_ReleasePtr( hDC );
561 W32kSetTextJustification(HDC hDC,
576 // Fixme: Call EngTextOut, which does the real work (calling DrvTextOut where appropriate)
578 DC *dc = DC_HandleToPtr(hDC);
579 SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject(dc->Surface);
580 int error, glyph_index, n, load_flags = FT_LOAD_RENDER, i, j, sx, sy, scc;
583 ULONG TextLeft, TextTop, SpaceBetweenChars = 2, pitch, previous;
585 RECTL DestRect, MaskRect;
586 POINTL SourcePoint, BrushOrigin;
587 HBRUSH hBrush = NULL;
588 PBRUSHOBJ Brush = NULL;
589 HBITMAP HSourceGlyph;
590 PSURFOBJ SourceGlyphSurf;
592 FT_CharMap found = 0, charmap;
604 XStart += dc->w.DCOrgX;
605 YStart += dc->w.DCOrgY;
609 TextObj = TEXTOBJ_LockText(dc->w.hFont);
611 for(i=0; i<FontsLoaded; i++)
613 if(wcscmp(FontTable[i].FaceName, (LPSTR)TextObj->logfont.lfFaceName) == 0)
614 hFont = FontTable[i].hFont;
619 DbgPrint("Specified font %s is not loaded\n", TextObj->logfont.lfFaceName);
623 FontObj = (PFONTOBJ)AccessUserObject(hFont);
624 FontGDI = (PFONTGDI)AccessInternalObject(hFont);
625 face = FontGDI->face;
627 if (face->charmap == NULL)
629 DbgPrint("WARNING: No charmap selected!\n");
630 DbgPrint("This font face has %d charmaps\n", face->num_charmaps);
632 for (n = 0; n < face->num_charmaps; n++)
634 charmap = face->charmaps[n];
635 DbgPrint("found charmap encoding: %u\n", charmap->encoding);
636 if (charmap->encoding != 0)
642 if (!found) DbgPrint("WARNING: Could not find desired charmap!\n");
643 error = FT_Set_Charmap(face, found);
644 if (error) DbgPrint("WARNING: Could not set the charmap!\n");
647 error = FT_Set_Pixel_Sizes(face, TextObj->logfont.lfHeight, TextObj->logfont.lfWidth);
649 DbgPrint("Error in setting pixel sizes: %u\n", error);
654 PalDestGDI = (PPALGDI)AccessInternalObject(dc->w.hPalette);
655 XlateObj = (PXLATEOBJ)EngCreateXlate(PalDestGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
656 hBrush = W32kCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.textColor));
657 Brush = BRUSHOBJ_LockBrush(hBrush);
658 EngDeleteXlate(XlateObj);
667 // Determine the yoff from the dc's w.textAlign
668 if (dc->w.textAlign & TA_BASELINE) {
672 if (dc->w.textAlign & TA_BOTTOM) {
673 yoff = -face->size->metrics.descender / 64;
676 yoff = face->size->metrics.ascender / 64;
679 use_kerning = FT_HAS_KERNING(face);
682 for(i=0; i<Count; i++)
684 glyph_index = FT_Get_Char_Index(face, *String);
685 error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
687 DbgPrint("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
692 // retrieve kerning distance and move pen position
693 if (use_kerning && previous && glyph_index)
696 FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
697 TextLeft += delta.x >> 6;
700 if (glyph->format == ft_glyph_format_outline)
702 error = FT_Render_Glyph(glyph, ft_render_mode_mono);
704 DbgPrint("WARNING: Failed to render glyph!\n");
707 pitch = glyph->bitmap.pitch;
709 pitch = glyph->bitmap.width;
712 DestRect.left = TextLeft;
713 DestRect.top = TextTop + yoff - glyph->bitmap_top;
714 DestRect.right = TextLeft + glyph->bitmap.width;
715 DestRect.bottom = DestRect.top + glyph->bitmap.rows;
716 bitSize.cx = pitch-1;
717 bitSize.cy = glyph->bitmap.rows-1;
718 MaskRect.right = glyph->bitmap.width;
719 MaskRect.bottom = glyph->bitmap.rows;
721 // We should create the bitmap out of the loop at the biggest possible glyph size
722 // Then use memset with 0 to clear it and sourcerect to limit the work of the transbitblt
724 HSourceGlyph = EngCreateBitmap(bitSize, pitch, BMF_1BPP, 0, glyph->bitmap.buffer);
725 SourceGlyphSurf = (PSURFOBJ)AccessUserObject(HSourceGlyph);
727 // Use the font data as a mask to paint onto the DCs surface using a brush
728 EngBitBlt(SurfObj, NULL, SourceGlyphSurf, NULL, NULL, &DestRect, &SourcePoint, &MaskRect, Brush, &BrushOrigin, 0xAACC);
730 EngDeleteSurface(HSourceGlyph);
732 TextLeft += glyph->advance.x >> 6;
733 previous = glyph_index;
737 TEXTOBJ_UnlockText( dc->w.hFont );
738 BRUSHOBJ_UnlockBrush(hBrush);
739 W32kDeleteObject( hBrush );
740 DC_ReleasePtr( hDC );
744 TEXTOBJ_UnlockText( dc->w.hFont );
746 BRUSHOBJ_UnlockBrush(hBrush);
747 W32kDeleteObject( hBrush );
749 DC_ReleasePtr( hDC );
755 W32kTranslateCharsetInfo(PDWORD Src,