diff --git a/sdk/xtdk/xtfont.h b/sdk/xtdk/xtfont.h index 509da38..ac74062 100644 --- a/sdk/xtdk/xtfont.h +++ b/sdk/xtdk/xtfont.h @@ -12,6 +12,7 @@ #include #include + /* SSF2 font header */ typedef struct _SSFN_FONT_HEADER { diff --git a/xtoskrnl/hl/efifb.c b/xtoskrnl/hl/efifb.c index d110f0e..5b87b19 100644 --- a/xtoskrnl/hl/efifb.c +++ b/xtoskrnl/hl/efifb.c @@ -136,3 +136,156 @@ HlInitializeFrameBuffer(VOID) /* Return success */ return STATUS_SUCCESS; } + +/** + * Puts a wide character on the framebuffer at the given position and color using the SSFN font. + * + * @param PositionX + * Supplies the X coordinate of the character. + * + * @param PositionY + * Supplies the Y coordinate of the character. + * + * @param Color + * Supplies the font color. + * + * @param WideCharacter + * Supplies the wide character to be drawn on the framebuffer. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +HlPutCharacter(IN ULONG PositionX, + IN ULONG PositionY, + IN ULONG Color, + IN WCHAR WideCharacter) +{ + UINT CurrentFragment, Glyph, GlyphLimit, Index, Line, Mapping; + PUCHAR Character, CharacterMapping, Fragment; + UINT_PTR GlyphPixel, Pixel; + PSSFN_FONT_HEADER FbFont; + + /* Get pointers to font data */ + FbFont = (PSSFN_FONT_HEADER)HlpFrameBufferData.Font; + CharacterMapping = (PUCHAR)FbFont + FbFont->CharactersOffset; + + /* Find the character in the font's character table */ + Character = 0; + for(Index = 0; Index < 0x110000; Index++) + { + if(CharacterMapping[0] == 0xFF) + { + /* Skip 65535 code points */ + Index += 65535; + CharacterMapping++; + } + else if((CharacterMapping[0] & 0xC0) == 0xC0) + { + /* Skip (N << 8 + additional byte) + 1 code points (up to 16128) */ + Index += (((CharacterMapping[0] & 0x3F) << 8) | CharacterMapping[1]); + CharacterMapping += 2; + } + else if((CharacterMapping[0] & 0xC0) == 0x80) + { + /* Skip N + 1 code points (up to 64) */ + Index += (CharacterMapping[0] & 0x3F); + CharacterMapping++; + } + else + { + /* There's a glyph for this character, check if it matches */ + if(Index == WideCharacter) + { + /* Found the character, break loop */ + Character = CharacterMapping; + break; + } + + /* Move to next character table entry */ + CharacterMapping += (6 + CharacterMapping[1] * (CharacterMapping[0] & 0x40 ? 6 : 5)); + } + } + + /* Make sure the character has been found in the font */ + if(!Character) + { + /* Character not found, don't draw anything */ + return; + } + + /* Find the glyph position on the frame buffer */ + GlyphPixel = (UINT_PTR)HlpFrameBufferData.Address + PositionY * HlpFrameBufferData.Pitch + PositionX * 4; + + /* Check all kerning fragments */ + Mapping = 0; + CharacterMapping = Character + 6; + for(Index = 0; Index < Character[1]; Index++) + { + /* Check if number of fragments is not exceeded */ + if(CharacterMapping[0] == 255 && CharacterMapping[1] == 255) + { + /* Get next mapping */ + continue; + } + + /* Get pointer to fragment */ + Fragment = (PUCHAR)FbFont + (CharacterMapping[2] | + (CharacterMapping[3] << 8) | + (CharacterMapping[4] << 16) | + ((Character[0] & 0x40) ? (CharacterMapping[5] << 24) : 0)); + + /* Check if fragment is printable */ + if((Fragment[0] & 0xE0) != 0x80) + { + /* Skip fragment */ + continue; + } + + /* Get initial glyph line */ + GlyphPixel += (CharacterMapping[1] - Mapping) * HlpFrameBufferData.Pitch; + Mapping = CharacterMapping[1]; + + /* Extract glyph data from fragments table and advance */ + Glyph = ((Fragment[0] & 0x1F) + 1) << 3; + GlyphLimit = Fragment[1] + 1; + Fragment += 2; + + /* Look for kerning group for next code point */ + CurrentFragment = 1; + while(GlyphLimit--) + { + Pixel = GlyphPixel; + for(Line = 0; Line < Glyph; Line++) + { + /* Decode compressed offsets */ + if(CurrentFragment > 0x80) + { + /* Advance to next fragment */ + Fragment++; + CurrentFragment = 1; + } + + /* Check if pixel should be drawn */ + if(*Fragment & CurrentFragment) + { + /* Draw glyph pixel */ + *((PULONG)Pixel) = Color; + } + + /* Advance pixel pointer */ + Pixel += 4; + CurrentFragment <<= 1; + } + + /* Advance to next line and increase mapping */ + GlyphPixel += HlpFrameBufferData.Pitch; + Mapping++; + } + + /* Get next mapping */ + CharacterMapping += Character[0] & 0x40 ? 6 : 5; + } +} diff --git a/xtoskrnl/includes/hli.h b/xtoskrnl/includes/hli.h index 0a7f0d7..208390e 100644 --- a/xtoskrnl/includes/hli.h +++ b/xtoskrnl/includes/hli.h @@ -55,6 +55,13 @@ XTAPI XTSTATUS HlInitializeFrameBuffer(VOID); +XTAPI +VOID +HlPutCharacter(IN ULONG PositionX, + IN ULONG PositionY, + IN ULONG Color, + IN WCHAR WideCharacter); + XTFASTCALL VOID HlSetRunLevel(IN KRUNLEVEL RunLevel);