3 #undef WIN32_LEAN_AND_MEAN
6 #include <win32k/brush.h>
8 #include <win32k/text.h>
9 #include <win32k/kapi.h>
10 #include <freetype/freetype.h>
12 #include "../eng/handle.h"
14 #include <include/inteng.h>
17 #include <win32k/debug1.h>
21 typedef struct _FONTTABLE
{
24 } FONTTABLE
, *PFONTTABLE
;
26 FONTTABLE FontTable
[256];
29 BOOL
InitFontSupport()
33 error
= FT_Init_FreeType(&library
);
39 W32kAddFontResource(L
"\\SystemRoot\\media\\fonts\\helb____.ttf");
40 W32kAddFontResource(L
"\\SystemRoot\\media\\fonts\\timr____.ttf");
42 DbgPrint("All fonts loaded\n");
49 W32kAddFontResource(LPCWSTR Filename
)
54 UNICODE_STRING uFileName
;
57 OBJECT_ATTRIBUTES ObjectAttributes
;
58 FILE_STANDARD_INFORMATION FileStdInfo
;
64 UNICODE_STRING StringU
;
67 NewFont
= (HFONT
)CreateGDIHandle(sizeof( FONTGDI
), sizeof( FONTOBJ
));
68 FontObj
= (PFONTOBJ
) AccessUserObject( NewFont
);
69 FontGDI
= (PFONTGDI
) AccessInternalObject( NewFont
);
71 RtlCreateUnicodeString(&uFileName
, (LPWSTR
)Filename
);
74 InitializeObjectAttributes(&ObjectAttributes
, &uFileName
, 0, NULL
, NULL
);
76 Status
= NtOpenFile(&FileHandle
, FILE_ALL_ACCESS
, &ObjectAttributes
, &Iosb
, 0, 0);
78 if (!NT_SUCCESS(Status
))
80 DbgPrint("Could not open module file: %S\n", Filename
);
84 // Get the size of the file
85 Status
= NtQueryInformationFile(FileHandle
, &Iosb
, &FileStdInfo
, sizeof(FileStdInfo
), FileStandardInformation
);
86 if (!NT_SUCCESS(Status
))
88 DbgPrint("Could not get file size\n");
92 // Allocate nonpageable memory for driver
93 size
= FileStdInfo
.EndOfFile
.u
.LowPart
;
94 buffer
= ExAllocatePool(NonPagedPool
, size
);
98 DbgPrint("could not allocate memory for module");
102 // Load driver into memory chunk
103 Status
= NtReadFile(FileHandle
, 0, 0, 0, &Iosb
, buffer
, FileStdInfo
.EndOfFile
.u
.LowPart
, 0, 0);
104 if (!NT_SUCCESS(Status
))
106 DbgPrint("could not read module file into memory");
113 error
= FT_New_Memory_Face(library
, buffer
, size
, 0, &face
);
114 if (error
== FT_Err_Unknown_File_Format
)
116 DbgPrint("Unknown font file format\n");
121 DbgPrint("Error reading font file (error code: %u)\n", error
); // 48
125 // FontGDI->Filename = Filename; perform strcpy
126 FontGDI
->face
= face
;
128 // FIXME: Complete text metrics
129 FontGDI
->TextMetric
.tmAscent
= face
->size
->metrics
.ascender
; // units above baseline
130 FontGDI
->TextMetric
.tmDescent
= face
->size
->metrics
.descender
; // units below baseline
131 FontGDI
->TextMetric
.tmHeight
= FontGDI
->TextMetric
.tmAscent
+ FontGDI
->TextMetric
.tmDescent
;
133 DbgPrint("Family name: %s\n", face
->family_name
);
134 DbgPrint("Style name: %s\n", face
->style_name
);
135 DbgPrint("Num glyphs: %u\n", face
->num_glyphs
);
137 // Add this font resource to the font table
138 FontTable
[FontsLoaded
].hFont
= NewFont
;
140 RtlInitAnsiString(&StringA
, (LPSTR
)face
->family_name
);
141 RtlAnsiStringToUnicodeString(&StringU
, &StringA
, TRUE
);
142 FontTable
[FontsLoaded
].FaceName
= ExAllocatePool(NonPagedPool
, (StringU
.Length
+ 1) * 2);
143 wcscpy((LPWSTR
)FontTable
[FontsLoaded
].FaceName
, StringU
.Buffer
);
144 RtlFreeUnicodeString(&StringU
);
153 W32kCreateFont(int Height
,
162 DWORD OutputPrecision
,
165 DWORD PitchAndFamily
,
170 logfont
.lfHeight
= Height
;
171 logfont
.lfWidth
= Width
;
172 logfont
.lfEscapement
= Escapement
;
173 logfont
.lfOrientation
= Orientation
;
174 logfont
.lfWeight
= Weight
;
175 logfont
.lfItalic
= Italic
;
176 logfont
.lfUnderline
= Underline
;
177 logfont
.lfStrikeOut
= StrikeOut
;
178 logfont
.lfCharSet
= CharSet
;
179 logfont
.lfOutPrecision
= OutputPrecision
;
180 logfont
.lfClipPrecision
= ClipPrecision
;
181 logfont
.lfQuality
= Quality
;
182 logfont
.lfPitchAndFamily
= PitchAndFamily
;
185 memcpy(logfont
.lfFaceName
, Face
, sizeof(logfont
.lfFaceName
));
187 logfont
.lfFaceName
[0] = '\0';
189 return W32kCreateFontIndirect(&logfont
);
194 W32kCreateFontIndirect(CONST LPLOGFONT lf
)
201 if(hFont
= TEXTOBJ_AllocText())
203 fontPtr
= TEXTOBJ_LockText( hFont
);
204 ASSERT( fontPtr
); //I want to know when this happens
206 memcpy(&fontPtr
->logfont
, lf
, sizeof(LOGFONT
));
208 if (lf
->lfEscapement
!= lf
->lfOrientation
) {
209 /* this should really depend on whether GM_ADVANCED is set */
210 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
212 TEXTOBJ_UnlockText( hFont
);
222 W32kCreateScalableFontResource(DWORD Hidden
,
232 W32kEnumFontFamilies(HDC hDC
,
234 FONTENUMPROC EnumFontFamProc
,
242 W32kEnumFontFamiliesEx(HDC hDC
,
244 FONTENUMPROC EnumFontFamExProc
,
253 W32kEnumFonts(HDC hDC
,
255 FONTENUMPROC FontFunc
,
263 W32kExtTextOut(HDC hDC
,
277 W32kGetAspectRatioFilterEx(HDC hDC
,
285 W32kGetCharABCWidths(HDC hDC
,
295 W32kGetCharABCWidthsFloat(HDC hDC
,
305 W32kGetCharacterPlacement(HDC hDC
,
309 LPGCP_RESULTS Results
,
317 W32kGetCharWidth(HDC hDC
,
327 W32kGetCharWidth32(HDC hDC
,
337 W32kGetCharWidthFloat(HDC hDC
,
347 W32kGetFontLanguageInfo(HDC hDC
)
354 W32kGetGlyphOutline(HDC hDC
,
369 W32kGetKerningPairs(HDC hDC
,
371 LPKERNINGPAIR krnpair
)
378 W32kGetOutlineTextMetrics(HDC hDC
,
380 LPOUTLINETEXTMETRIC otm
)
387 W32kGetRasterizerCaps(LPRASTERIZER_STATUS rs
,
395 W32kGetTextCharset(HDC hDC
)
402 W32kGetTextCharsetInfo(HDC hDC
,
411 W32kGetTextExtentExPoint(HDC hDC
,
424 W32kGetTextExtentPoint(HDC hDC
,
429 PDC dc
= (PDC
)AccessUserObject(hDC
);
433 INT error
, pitch
, glyph_index
, i
;
434 ULONG TotalWidth
= 0, MaxHeight
= 0, CurrentChar
= 0, SpaceBetweenChars
= 5;
436 FontGDI
= (PFONTGDI
)AccessInternalObject(dc
->w
.hFont
);
438 for(i
=0; i
<Count
; i
++)
440 glyph_index
= FT_Get_Char_Index(face
, *String
);
441 error
= FT_Load_Glyph(face
, glyph_index
, FT_LOAD_DEFAULT
);
442 if(error
) DbgPrint("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index
);
445 if (glyph
->format
== ft_glyph_format_outline
)
447 error
= FT_Render_Glyph(glyph
, ft_render_mode_mono
);
448 if(error
) DbgPrint("WARNING: Failed to render glyph!\n");
449 pitch
= glyph
->bitmap
.pitch
;
451 pitch
= glyph
->bitmap
.width
;
454 TotalWidth
+= pitch
-1;
455 if((glyph
->bitmap
.rows
-1) > MaxHeight
) MaxHeight
= glyph
->bitmap
.rows
-1;
459 if(CurrentChar
< Size
->cx
) TotalWidth
+= SpaceBetweenChars
;
463 Size
->cx
= TotalWidth
;
464 Size
->cy
= MaxHeight
;
469 W32kGetTextExtentPoint32(HDC hDC
,
479 W32kGetTextFace(HDC hDC
,
488 W32kGetTextMetrics(HDC hDC
,
491 PDC dc
= (PDC
)AccessUserObject(hDC
);
494 FontGDI
= (PFONTGDI
)AccessInternalObject(dc
->w
.hFont
);
495 memcpy(tm
, &FontGDI
->TextMetric
, sizeof(TEXTMETRIC
));
502 W32kPolyTextOut(HDC hDC
,
503 CONST LPPOLYTEXT txt
,
511 W32kRemoveFontResource(LPCWSTR FileName
)
518 W32kSetMapperFlags(HDC hDC
,
526 W32kSetTextAlign(HDC hDC
,
532 dc
= DC_HandleToPtr(hDC
);
537 prevAlign
= dc
->w
.textAlign
;
538 dc
->w
.textAlign
= Mode
;
539 DC_ReleasePtr( hDC
);
545 W32kSetTextColor(HDC hDC
,
549 PDC dc
= DC_HandleToPtr(hDC
);
556 oldColor
= dc
->w
.textColor
;
557 dc
->w
.textColor
= color
;
558 DC_ReleasePtr( hDC
);
564 W32kSetTextJustification(HDC hDC
,
579 // Fixme: Call EngTextOut, which does the real work (calling DrvTextOut where appropriate)
581 DC
*dc
= DC_HandleToPtr(hDC
);
582 SURFOBJ
*SurfObj
= (SURFOBJ
*)AccessUserObject(dc
->Surface
);
583 int error
, glyph_index
, n
, load_flags
= FT_LOAD_RENDER
, i
, j
, sx
, sy
, scc
;
586 ULONG TextLeft
, TextTop
, SpaceBetweenChars
= 2, pitch
, previous
;
588 RECTL DestRect
, MaskRect
;
589 POINTL SourcePoint
, BrushOrigin
;
590 HBRUSH hBrush
= NULL
;
591 PBRUSHOBJ Brush
= NULL
;
592 HBITMAP HSourceGlyph
;
593 PSURFOBJ SourceGlyphSurf
;
595 FT_CharMap found
= 0, charmap
;
607 XStart
+= dc
->w
.DCOrgX
;
608 YStart
+= dc
->w
.DCOrgY
;
612 TextObj
= TEXTOBJ_LockText(dc
->w
.hFont
);
614 for(i
=0; i
<FontsLoaded
; i
++)
616 if(wcscmp(FontTable
[i
].FaceName
, (LPSTR
)TextObj
->logfont
.lfFaceName
) == 0)
617 hFont
= FontTable
[i
].hFont
;
622 DbgPrint("Specified font %s is not loaded\n", TextObj
->logfont
.lfFaceName
);
626 FontObj
= (PFONTOBJ
)AccessUserObject(hFont
);
627 FontGDI
= (PFONTGDI
)AccessInternalObject(hFont
);
628 face
= FontGDI
->face
;
630 if (face
->charmap
== NULL
)
632 DbgPrint("WARNING: No charmap selected!\n");
633 DbgPrint("This font face has %d charmaps\n", face
->num_charmaps
);
635 for (n
= 0; n
< face
->num_charmaps
; n
++)
637 charmap
= face
->charmaps
[n
];
638 DbgPrint("found charmap encoding: %u\n", charmap
->encoding
);
639 if (charmap
->encoding
!= 0)
645 if (!found
) DbgPrint("WARNING: Could not find desired charmap!\n");
646 error
= FT_Set_Charmap(face
, found
);
647 if (error
) DbgPrint("WARNING: Could not set the charmap!\n");
650 error
= FT_Set_Pixel_Sizes(face
, TextObj
->logfont
.lfHeight
, TextObj
->logfont
.lfWidth
);
652 DbgPrint("Error in setting pixel sizes: %u\n", error
);
657 PalDestGDI
= (PPALGDI
)AccessInternalObject(dc
->w
.hPalette
);
658 XlateObj
= (PXLATEOBJ
)IntEngCreateXlate(PalDestGDI
->Mode
, PAL_RGB
, dc
->w
.hPalette
, NULL
);
659 hBrush
= W32kCreateSolidBrush(XLATEOBJ_iXlate(XlateObj
, dc
->w
.textColor
));
660 Brush
= BRUSHOBJ_LockBrush(hBrush
);
661 EngDeleteXlate(XlateObj
);
670 // Determine the yoff from the dc's w.textAlign
671 if (dc
->w
.textAlign
& TA_BASELINE
) {
675 if (dc
->w
.textAlign
& TA_BOTTOM
) {
676 yoff
= -face
->size
->metrics
.descender
/ 64;
679 yoff
= face
->size
->metrics
.ascender
/ 64;
682 use_kerning
= FT_HAS_KERNING(face
);
685 for(i
=0; i
<Count
; i
++)
687 glyph_index
= FT_Get_Char_Index(face
, *String
);
688 error
= FT_Load_Glyph(face
, glyph_index
, FT_LOAD_DEFAULT
);
690 DbgPrint("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index
);
695 // retrieve kerning distance and move pen position
696 if (use_kerning
&& previous
&& glyph_index
)
699 FT_Get_Kerning(face
, previous
, glyph_index
, 0, &delta
);
700 TextLeft
+= delta
.x
>> 6;
703 if (glyph
->format
== ft_glyph_format_outline
)
705 error
= FT_Render_Glyph(glyph
, ft_render_mode_mono
);
707 DbgPrint("WARNING: Failed to render glyph!\n");
710 pitch
= glyph
->bitmap
.pitch
;
712 pitch
= glyph
->bitmap
.width
;
715 DestRect
.left
= TextLeft
;
716 DestRect
.top
= TextTop
+ yoff
- glyph
->bitmap_top
;
717 DestRect
.right
= TextLeft
+ glyph
->bitmap
.width
;
718 DestRect
.bottom
= DestRect
.top
+ glyph
->bitmap
.rows
;
720 bitSize
.cy
= glyph
->bitmap
.rows
;
721 MaskRect
.right
= glyph
->bitmap
.width
;
722 MaskRect
.bottom
= glyph
->bitmap
.rows
;
724 // We should create the bitmap out of the loop at the biggest possible glyph size
725 // Then use memset with 0 to clear it and sourcerect to limit the work of the transbitblt
727 HSourceGlyph
= EngCreateBitmap(bitSize
, pitch
, BMF_1BPP
, 0, glyph
->bitmap
.buffer
);
728 SourceGlyphSurf
= (PSURFOBJ
)AccessUserObject(HSourceGlyph
);
730 // Use the font data as a mask to paint onto the DCs surface using a brush
731 IntEngBitBlt(SurfObj
, NULL
, SourceGlyphSurf
, NULL
, NULL
, &DestRect
, &SourcePoint
, &MaskRect
, Brush
, &BrushOrigin
, 0xAACC);
733 EngDeleteSurface(HSourceGlyph
);
735 TextLeft
+= glyph
->advance
.x
>> 6;
736 previous
= glyph_index
;
740 TEXTOBJ_UnlockText( dc
->w
.hFont
);
741 BRUSHOBJ_UnlockBrush(hBrush
);
742 W32kDeleteObject( hBrush
);
743 DC_ReleasePtr( hDC
);
747 TEXTOBJ_UnlockText( dc
->w
.hFont
);
749 BRUSHOBJ_UnlockBrush(hBrush
);
750 W32kDeleteObject( hBrush
);
752 DC_ReleasePtr( hDC
);
758 W32kTranslateCharsetInfo(PDWORD Src
,