2020-02-06 20:20:58 +00:00
# include <kernel/chroma.h>
# include <kernel/video/bitmapfont.h>
2020-08-22 23:48:49 +00:00
/************************
* * * Team Kitty , 2020 * * *
* * * Chroma * * *
* * * * * * * * * * * * * * * * * * * * * * */
/* This file contains all of the draw-to-screen routines.
* It ( currently ; 23 / 08 / 20 ) handles the keyboard input test routine ,
* moving the current character back and forth , up and down .
*
* It also handles filling the screen with color in the case of an event ,
* and will be hooked into Vector and Shape of lainlib to eventually provide
* geometry .
*
* It will also eventually be plugged into stb_image to provide a way to draw PNGs
* and JPGs from disk .
*/
2020-02-06 20:20:58 +00:00
# define FONT bitfont_latin
static size_t strlen ( const char * String ) {
size_t Len = 0 ;
while ( String [ Len ] ! = ' \0 ' ) {
Len + + ;
}
return Len ;
}
typedef struct {
uint32_t charHeight ;
uint32_t charWidth ;
uint32_t charFGColor ;
uint32_t charHLColor ;
uint32_t charBGColor ;
uint32_t minX ;
uint32_t minY ;
uint32_t charScale ;
size_t charPosX ;
size_t charPosY ;
size_t charsPerRow ;
size_t rowsPerScrn ;
uint32_t scrlMode ;
} PRINTINFO ;
PRINTINFO PrintInfo = { 0 } ;
void InitPrint ( ) {
PrintInfo . charHeight = 8 ;
PrintInfo . charWidth = 8 ;
PrintInfo . charFGColor = 0x00FFFFFF ;
PrintInfo . charHLColor = 0x00000000 ;
PrintInfo . charBGColor = 0x00000000 ;
PrintInfo . charScale = 2 ;
PrintInfo . charPosX = 0 ;
2020-04-11 21:59:39 +00:00
PrintInfo . charPosY = 1 ;
2020-02-06 20:20:58 +00:00
PrintInfo . scrlMode = 0 ;
PrintInfo . charsPerRow = bootldr . fb_width / ( PrintInfo . charScale * PrintInfo . charWidth ) - 5 ;
PrintInfo . rowsPerScrn = bootldr . fb_height / ( PrintInfo . charScale * PrintInfo . charHeight ) ;
2020-11-09 18:41:34 +00:00
SerialPrintf ( " [Print] A single character is %ux%u pixels. \r \n " , PrintInfo . charScale * PrintInfo . charWidth , PrintInfo . charScale * PrintInfo . charHeight ) ;
SerialPrintf ( " [Print] The screen is %ux%u, meaning you can fit %ux%u characters on screen. \r \n " , bootldr . fb_width , bootldr . fb_height , PrintInfo . charsPerRow , PrintInfo . rowsPerScrn ) ;
2020-02-06 20:20:58 +00:00
}
static void DrawChar ( const char character , size_t x , size_t y ) {
x = x + PrintInfo . charPosX * ( PrintInfo . charScale * PrintInfo . charWidth ) ;
y = y + PrintInfo . charPosY * ( PrintInfo . charScale * PrintInfo . charHeight ) ;
uint32_t Y = PrintInfo . charWidth > > 3 , X = 0 ;
if ( ( PrintInfo . charWidth & 0x7 ) ! = 0 ) {
Y + + ;
}
for ( uint32_t Row = 0 ; Row < PrintInfo . charHeight ; Row + + ) {
for ( uint32_t Bit = 0 ; Bit < PrintInfo . charWidth ; Bit + + ) {
if ( ( ( Bit & 0x7 ) = = 0 ) & & ( Bit > 0 ) ) {
X + + ;
}
2020-04-11 21:59:39 +00:00
// This one is crazy. Stick with me.
2020-07-07 23:38:59 +00:00
if ( ( FONT [ ( int ) character ] [ Row * Y + X ] > > ( Bit & 0x7 ) ) & 1 ) { // Check the bit in the bitmap, if it's solid..
2020-04-11 21:59:39 +00:00
for ( uint32_t ScaleY = 0 ; ScaleY < PrintInfo . charScale ; ScaleY + + ) { // Take care of the scale height
for ( uint32_t ScaleX = 0 ; ScaleX < PrintInfo . charScale ; ScaleX + + ) { // And the scale width
2020-02-06 20:20:58 +00:00
2020-04-11 21:59:39 +00:00
size_t offset = ( ( y * bootldr . fb_width + x ) + // Calculate the offset from the framebuffer
PrintInfo . charScale * ( Row * bootldr . fb_width + Bit ) + // With the appropriate scale
( ScaleY * bootldr . fb_width + ScaleX ) + // In X and Y
PrintInfo . charScale * 1 * PrintInfo . charWidth ) - 10 ; // With some offset to start at 0
2020-02-06 20:20:58 +00:00
2020-04-11 21:59:39 +00:00
* ( uint32_t * ) ( & fb + offset * 4 ) // And use it to set the correct pixel on the screen
= PrintInfo . charFGColor ; // In the set foreground color
2020-02-06 20:20:58 +00:00
}
}
} else {
2020-04-11 21:59:39 +00:00
// We need to draw the pixel transparently, using the background color
2020-02-06 20:20:58 +00:00
for ( uint32_t ScaleY = 0 ; ScaleY < PrintInfo . charScale ; ScaleY + + ) {
for ( uint32_t ScaleX = 0 ; ScaleX < PrintInfo . charScale ; ScaleX + + ) {
if ( PrintInfo . charHLColor ! = 0xFF000000 ) {
size_t offset = ( ( y * bootldr . fb_width + x ) +
PrintInfo . charScale * ( Row * bootldr . fb_width + Bit ) +
( ScaleY * bootldr . fb_width + ScaleX ) +
PrintInfo . charScale * 1 * PrintInfo . charWidth ) - 10 ;
if ( y = = 0 & & x = = 0 ) {
2020-04-11 21:59:39 +00:00
//SerialPrintf("Writing first pixel at %x\r\n", offset);
2020-02-06 20:20:58 +00:00
}
* ( uint32_t * ) ( & fb + offset * 4 )
= PrintInfo . charHLColor ;
}
}
}
}
}
}
/*
uint32_t Y = PrintInfo . charWidth > > 3 , X = 0 ;
if ( ( PrintInfo . charWidth & 0x7 ) ! = 0 ) {
Y + + ;
}
for ( size_t CharRow = 0 ; CharRow < PrintInfo . charHeight ; CharRow + + ) {
for ( size_t CharPixel = 0 ; CharPixel < PrintInfo . charWidth ; CharPixel + + ) {
if ( CharPixel & & ( CharPixel & 0x7 ) = = 0 ) {
X + + ;
}
for ( size_t ScaleX = 0 ; ScaleX < PrintInfo . charScale ; ScaleX + + ) {
for ( size_t ScaleY = 0 ; ScaleY < PrintInfo . charScale ; ScaleY + + ) {
if ( FONT [ character ] [ CharRow * Y + X ] > > ( CharRow & 0x7 ) & 1 ) {
size_t offset = ( y * bootldr . fb_width + x ) +
( PrintInfo . charScale * ( CharRow * bootldr . fb_width + CharPixel ) ) +
( ScaleY * ( bootldr . fb_width + ScaleX ) ) ;
* ( ( uint32_t * ) ( & fb + offset * 4 ) )
= PrintInfo . charFGColor ;
//DrawPixel(x * PrintInfo.charWidth + X, Y + y + PrintInfo.charHeight, 0x00FF0000);
}
}
}
}
}
uint32_t Y = PrintInfo . charWidth > > 3 , X = 0 ;
if ( ( PrintInfo . charWidth & 0x7 ) ! = 0 ) {
Y + + ;
}
for ( uint32_t Row = 0 ; Row < PrintInfo . charHeight ; Row + + ) {
for ( uint32_t Bit = 0 ; Bit < PrintInfo . charWidth ; Bit + + ) {
if ( ( ( Bit & 0x7 ) = = 0 ) & & ( Bit > 0 ) )
X + + ;
for ( uint32_t ScaleY = 0 ; ScaleY < PrintInfo . charScale ; ScaleY + + ) {
for ( uint32_t ScaleX = 0 ; ScaleX < PrintInfo . charScale ; ScaleX + + ) {
if ( ( FONT [ character ] [ Row * Y + X ] > > ( Bit & 0x7 ) ) & 1 ) {
size_t offset = ( y * bootldr . fb_width + x ) +
( PrintInfo . charScale * ( Row * bootldr . fb_width + Bit ) ) +
( ScaleY * ( bootldr . fb_width + ScaleX ) ) ;
SerialPrintf ( " Drawing pixel at offset %x, at y %d, x %d, row %d, bit %d with scaley %d and scalex %d. charScale %d and charWidth %d, making a charLength %d. \r \n " , offset , y , x , Row , Bit , ScaleX , ScaleY , PrintInfo . charScale , PrintInfo . charWidth , PrintInfo . charScale * PrintInfo . charWidth ) ;
* ( ( uint32_t * ) ( & fb + offset * 4 ) )
= PrintInfo . charFGColor ;
} else {
if ( PrintInfo . charHLColor ! = 0xFF000000 ) {
size_t offset = ( y * bootldr . fb_width + x ) +
( PrintInfo . charScale * ( Row * bootldr . fb_width + Bit ) ) +
( ScaleY * ( bootldr . fb_width + ScaleX ) ) ;
SerialPrintf ( " Drawing pixel at offset %x \r \n " , offset ) ;
* ( ( uint32_t * ) ( & fb + offset * 4 ) )
= PrintInfo . charHLColor ;
}
}
}
}
}
}
*/
}
void DrawPixel ( uint32_t x , uint32_t y , uint32_t color ) {
if ( x > bootldr . fb_width ) {
DrawPixel ( x - bootldr . fb_width , y + ( PrintInfo . charHeight * PrintInfo . charScale ) , color ) ;
//FillScreen(color);
} else if ( y > bootldr . fb_height ) {
DrawPixel ( x , y - bootldr . fb_height , color ) ;
} else {
2020-04-11 21:59:39 +00:00
* ( ( uint32_t * ) ( & fb + ( y * bootldr . fb_width + x ) * 4 ) ) = color ;
//SerialPrintf("Drawing a pixel at %d, %d with color 0x%x\r\n", x, y, color);
2020-02-06 20:20:58 +00:00
}
}
void FillScreen ( uint32_t color ) {
for ( size_t y = 0 ; y < bootldr . fb_height ; y + + ) {
for ( size_t x = 0 ; x < bootldr . fb_width ; x + + ) {
DrawPixel ( x , y , color ) ;
}
}
}
static void ProgressCursorS ( size_t Steps ) {
if ( PrintInfo . charPosX + Steps > PrintInfo . charsPerRow ) {
PrintInfo . charPosX = 0 ;
size_t Rows = Steps / PrintInfo . charsPerRow ;
if ( PrintInfo . charPosY + Rows > PrintInfo . rowsPerScrn ) {
size_t RowsLeft = PrintInfo . rowsPerScrn - PrintInfo . charPosY ;
ProgressCursorS ( ( Rows - RowsLeft ) * PrintInfo . charsPerRow ) ;
} else {
PrintInfo . charPosY + + ;
}
} else {
PrintInfo . charPosX + = Steps ;
}
}
static void Newline ( ) {
ProgressCursorS ( PrintInfo . charsPerRow ) ;
}
static void ProgressCursor ( ) {
ProgressCursorS ( 1 ) ;
}
2020-04-11 21:59:39 +00:00
static void Backspace ( ) {
SerialPrintf ( " Backspacing from %d to %d \r \n " , PrintInfo . charPosX , PrintInfo . charPosX - 1 ) ;
if ( PrintInfo . charPosX - 1 < = 0 ) {
if ( PrintInfo . charPosY - 1 < = 0 ) {
PrintInfo . charPosY = 0 ;
} else {
PrintInfo . charPosY - - ;
}
PrintInfo . charPosX = 0 ;
} else {
PrintInfo . charPosX - = 1 ;
}
}
2020-02-06 20:20:58 +00:00
void WriteChar ( const char character ) {
//size_t y = PrintInfo.charPos / RowsWidth * (PrintInfo.charScale * PrintInfo.charHeight);
//size_t x = (PrintInfo.charPos % RowsWidth) * (PrintInfo.charScale * PrintInfo.charWidth);
switch ( character ) {
case ' \b ' :
2020-04-11 21:59:39 +00:00
Backspace ( ) ;
DrawChar ( ( char ) 32 , PrintInfo . charPosX , PrintInfo . charPosY ) ;
2020-02-06 20:20:58 +00:00
break ;
case ' \n ' :
Newline ( ) ;
break ;
2020-04-11 21:59:39 +00:00
case ' \t ' :
ProgressCursorS ( 4 ) ;
break ;
2020-02-06 20:20:58 +00:00
default :
DrawChar ( character , PrintInfo . charPosX , PrintInfo . charPosY ) ;
ProgressCursor ( ) ;
break ;
}
}
void WriteString ( const char * string ) {
2020-07-07 23:38:59 +00:00
for ( unsigned int i = 0 ; i < strlen ( string ) ; i + + ) {
2020-02-06 20:20:58 +00:00
WriteChar ( string [ i ] ) ;
}
}
2020-04-11 21:59:39 +00:00
void WriteStringWithFont ( const char * inChar )
{
psf_t * font = ( psf_t * ) & _binary_font_psf_start ;
2020-07-07 23:38:59 +00:00
unsigned int drawX , drawY , kx = 0 , fontLine , bitMask , offset ;
2020-04-11 21:59:39 +00:00
2020-07-07 23:38:59 +00:00
const unsigned int bytesPerLine = ( font - > glyphWidth + 7 ) / 8 ;
2020-04-11 21:59:39 +00:00
while ( * inChar ) {
unsigned char * glyph =
( unsigned char * ) & _binary_font_psf_start
+ font - > headerSize
2020-07-07 23:38:59 +00:00
+ ( * inChar > 0 & & * inChar < ( int ) font - > numGlyphs ? * inChar : 0 ) *
2020-04-11 21:59:39 +00:00
font - > glyphSize ;
offset = ( kx * ( font - > glyphWidth + 1 ) * 4 ) ;
for ( drawY = 0 ; drawY < font - > glyphHeight ; drawY + + ) {
fontLine = offset ;
bitMask = 1 < < ( font - > glyphWidth - 1 ) ;
for ( drawX = 0 ; drawX < font - > glyphWidth ; drawX + + ) {
* ( ( uint32_t * ) ( ( uint64_t ) & fb + fontLine ) ) =
( ( int ) * glyph ) & ( bitMask ) ? 0xFFFFFF : 0 ;
bitMask > > = 1 ;
fontLine + = 4 ;
}
* ( ( uint32_t * ) ( ( uint64_t ) & fb + fontLine ) ) = 0 ;
glyph + = bytesPerLine ;
offset + = bootldr . fb_scanline ;
}
inChar + + ; kx + + ;
}
}