1
+ use crate :: binary:: logger:: font_constants:: BACKUP_CHAR ;
1
2
use crate :: boot_info:: { FrameBufferInfo , PixelFormat } ;
2
3
use conquer_once:: spin:: OnceCell ;
3
4
use core:: {
4
5
fmt:: { self , Write } ,
5
6
ptr,
6
7
} ;
7
- use noto_sans_mono_bitmap:: { get_bitmap, get_bitmap_width, BitmapChar , BitmapHeight , FontWeight } ;
8
+ use noto_sans_mono_bitmap:: {
9
+ get_raster, get_raster_width, FontWeight , RasterHeight , RasterizedChar ,
10
+ } ;
8
11
use spinning_top:: Spinlock ;
9
12
10
13
/// The global logger instance used for the `log` crate.
@@ -14,9 +17,41 @@ pub static LOGGER: OnceCell<LockedLogger> = OnceCell::uninit();
14
17
pub struct LockedLogger ( Spinlock < Logger > ) ;
15
18
16
19
/// Additional vertical space between lines
17
- const LINE_SPACING : usize = 0 ;
18
- /// Additional vertical space between separate log messages
19
- const LOG_SPACING : usize = 2 ;
20
+ const LINE_SPACING : usize = 2 ;
21
+ /// Additional horizontal space between characters.
22
+ const LETTER_SPACING : usize = 0 ;
23
+
24
+ /// Padding from the border. Prevent that font is too close to border.
25
+ const BORDER_PADDING : usize = 1 ;
26
+
27
+ /// Constants for the usage of the [`noto_sans_mono_bitmap`] crate.
28
+ mod font_constants {
29
+ use super :: * ;
30
+
31
+ /// Height of each char raster. The font size is ~0.84% of this. Thus, this is the line height that
32
+ /// enables multiple characters to be side-by-side and appear optically in one line in a natural way.
33
+ pub const CHAR_RASTER_HEIGHT : RasterHeight = RasterHeight :: Size16 ;
34
+
35
+ /// The width of each single symbol of the mono space font.
36
+ pub const CHAR_RASTER_WIDTH : usize = get_raster_width ( FontWeight :: Regular , CHAR_RASTER_HEIGHT ) ;
37
+
38
+ /// Requires feature "unicode-specials"
39
+ pub const BACKUP_CHAR : char = '�' ;
40
+
41
+ pub const FONT_WEIGHT : FontWeight = FontWeight :: Regular ;
42
+ }
43
+
44
+ /// Returns the raster of the given char or the raster of [`font_constants::BACKUP_CHAR`].
45
+ fn get_char_raster ( c : char ) -> RasterizedChar {
46
+ fn get ( c : char ) -> Option < RasterizedChar > {
47
+ get_raster (
48
+ c,
49
+ font_constants:: FONT_WEIGHT ,
50
+ font_constants:: CHAR_RASTER_HEIGHT ,
51
+ )
52
+ }
53
+ get ( c) . unwrap_or ( get ( BACKUP_CHAR ) . expect ( "Should get raster of backup char." ) )
54
+ }
20
55
21
56
impl LockedLogger {
22
57
/// Create a new instance that logs to the given framebuffer.
@@ -39,8 +74,7 @@ impl log::Log for LockedLogger {
39
74
40
75
fn log ( & self , record : & log:: Record ) {
41
76
let mut logger = self . 0 . lock ( ) ;
42
- writeln ! ( logger, "{}: {}" , record. level( ) , record. args( ) ) . unwrap ( ) ;
43
- logger. add_vspace ( LOG_SPACING ) ;
77
+ writeln ! ( logger, "{:5}: {}" , record. level( ) , record. args( ) ) . unwrap ( ) ;
44
78
}
45
79
46
80
fn flush ( & self ) { }
@@ -68,22 +102,18 @@ impl Logger {
68
102
}
69
103
70
104
fn newline ( & mut self ) {
71
- self . y_pos += 14 + LINE_SPACING ;
105
+ self . y_pos += font_constants :: CHAR_RASTER_HEIGHT . val ( ) + LINE_SPACING ;
72
106
self . carriage_return ( )
73
107
}
74
108
75
- fn add_vspace ( & mut self , space : usize ) {
76
- self . y_pos += space;
77
- }
78
-
79
109
fn carriage_return ( & mut self ) {
80
- self . x_pos = 0 ;
110
+ self . x_pos = BORDER_PADDING ;
81
111
}
82
112
83
- /// Erases all text on the screen.
113
+ /// Erases all text on the screen. Resets `self.x_pos` and `self.y_pos`.
84
114
pub fn clear ( & mut self ) {
85
- self . x_pos = 0 ;
86
- self . y_pos = 0 ;
115
+ self . x_pos = BORDER_PADDING ;
116
+ self . y_pos = BORDER_PADDING ;
87
117
self . framebuffer . fill ( 0 ) ;
88
118
}
89
119
@@ -95,32 +125,36 @@ impl Logger {
95
125
self . info . vertical_resolution
96
126
}
97
127
128
+ /// Writes a single char to the framebuffer. Takes care of special control characters, such as
129
+ /// newlines and carriage returns.
98
130
fn write_char ( & mut self , c : char ) {
99
131
match c {
100
132
'\n' => self . newline ( ) ,
101
133
'\r' => self . carriage_return ( ) ,
102
134
c => {
103
- if self . x_pos >= self . width ( ) {
135
+ let new_xpos = self . x_pos + font_constants:: CHAR_RASTER_WIDTH ;
136
+ if new_xpos >= self . width ( ) {
104
137
self . newline ( ) ;
105
138
}
106
- const BITMAP_LETTER_WIDTH : usize =
107
- get_bitmap_width ( FontWeight :: Regular , BitmapHeight :: Size14 ) ;
108
- if self . y_pos >= ( self . height ( ) - BITMAP_LETTER_WIDTH ) {
139
+ let new_ypos =
140
+ self . y_pos + font_constants :: CHAR_RASTER_HEIGHT . val ( ) + BORDER_PADDING ;
141
+ if new_ypos >= self . height ( ) {
109
142
self . clear ( ) ;
110
143
}
111
- let bitmap_char = get_bitmap ( c, FontWeight :: Regular , BitmapHeight :: Size14 ) . unwrap ( ) ;
112
- self . write_rendered_char ( bitmap_char) ;
144
+ self . write_rendered_char ( get_char_raster ( c) ) ;
113
145
}
114
146
}
115
147
}
116
148
117
- fn write_rendered_char ( & mut self , rendered_char : BitmapChar ) {
118
- for ( y, row) in rendered_char. bitmap ( ) . iter ( ) . enumerate ( ) {
149
+ /// Prints a rendered char into the framebuffer.
150
+ /// Updates `self.x_pos`.
151
+ fn write_rendered_char ( & mut self , rendered_char : RasterizedChar ) {
152
+ for ( y, row) in rendered_char. raster ( ) . iter ( ) . enumerate ( ) {
119
153
for ( x, byte) in row. iter ( ) . enumerate ( ) {
120
154
self . write_pixel ( self . x_pos + x, self . y_pos + y, * byte) ;
121
155
}
122
156
}
123
- self . x_pos += rendered_char. width ( ) ;
157
+ self . x_pos += rendered_char. width ( ) + LETTER_SPACING ;
124
158
}
125
159
126
160
fn write_pixel ( & mut self , x : usize , y : usize , intensity : u8 ) {
0 commit comments