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,46 @@ 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
+ get_raster (
47
+ c,
48
+ font_constants:: FONT_WEIGHT ,
49
+ font_constants:: CHAR_RASTER_HEIGHT ,
50
+ )
51
+ . unwrap_or (
52
+ get_raster (
53
+ BACKUP_CHAR ,
54
+ font_constants:: FONT_WEIGHT ,
55
+ font_constants:: CHAR_RASTER_HEIGHT ,
56
+ )
57
+ . unwrap ( ) ,
58
+ )
59
+ }
20
60
21
61
impl LockedLogger {
22
62
/// Create a new instance that logs to the given framebuffer.
@@ -39,8 +79,7 @@ impl log::Log for LockedLogger {
39
79
40
80
fn log ( & self , record : & log:: Record ) {
41
81
let mut logger = self . 0 . lock ( ) ;
42
- writeln ! ( logger, "{}: {}" , record. level( ) , record. args( ) ) . unwrap ( ) ;
43
- logger. add_vspace ( LOG_SPACING ) ;
82
+ writeln ! ( logger, "{:5}: {}" , record. level( ) , record. args( ) ) . unwrap ( ) ;
44
83
}
45
84
46
85
fn flush ( & self ) { }
@@ -68,22 +107,18 @@ impl Logger {
68
107
}
69
108
70
109
fn newline ( & mut self ) {
71
- self . y_pos += 14 + LINE_SPACING ;
110
+ self . y_pos += font_constants :: CHAR_RASTER_HEIGHT . val ( ) + LINE_SPACING ;
72
111
self . carriage_return ( )
73
112
}
74
113
75
- fn add_vspace ( & mut self , space : usize ) {
76
- self . y_pos += space;
77
- }
78
-
79
114
fn carriage_return ( & mut self ) {
80
- self . x_pos = 0 ;
115
+ self . x_pos = BORDER_PADDING ;
81
116
}
82
117
83
- /// Erases all text on the screen.
118
+ /// Erases all text on the screen. Resets `self.x_pos` and `self.y_pos`.
84
119
pub fn clear ( & mut self ) {
85
- self . x_pos = 0 ;
86
- self . y_pos = 0 ;
120
+ self . x_pos = BORDER_PADDING ;
121
+ self . y_pos = BORDER_PADDING ;
87
122
self . framebuffer . fill ( 0 ) ;
88
123
}
89
124
@@ -95,32 +130,35 @@ impl Logger {
95
130
self . info . vertical_resolution
96
131
}
97
132
133
+ /// Writes a single char to the framebuffer. Takes care of special control characters, such as
134
+ /// newlines and carriage returns.
98
135
fn write_char ( & mut self , c : char ) {
99
136
match c {
100
137
'\n' => self . newline ( ) ,
101
138
'\r' => self . carriage_return ( ) ,
102
139
c => {
103
- if self . x_pos >= self . width ( ) {
140
+ let new_xpos = self . x_pos + font_constants:: CHAR_RASTER_WIDTH ;
141
+ if new_xpos >= self . width ( ) {
104
142
self . newline ( ) ;
105
143
}
106
- const BITMAP_LETTER_WIDTH : usize =
107
- get_bitmap_width ( FontWeight :: Regular , BitmapHeight :: Size14 ) ;
108
- if self . y_pos >= ( self . height ( ) - BITMAP_LETTER_WIDTH ) {
144
+ let new_ypos = self . y_pos + font_constants:: CHAR_RASTER_HEIGHT . val ( ) + BORDER_PADDING ;
145
+ if new_ypos >= self . height ( ) {
109
146
self . clear ( ) ;
110
147
}
111
- let bitmap_char = get_bitmap ( c, FontWeight :: Regular , BitmapHeight :: Size14 ) . unwrap ( ) ;
112
- self . write_rendered_char ( bitmap_char) ;
148
+ self . write_rendered_char ( get_char_raster ( c) ) ;
113
149
}
114
150
}
115
151
}
116
152
117
- fn write_rendered_char ( & mut self , rendered_char : BitmapChar ) {
118
- for ( y, row) in rendered_char. bitmap ( ) . iter ( ) . enumerate ( ) {
153
+ /// Prints a rendered char into the framebuffer.
154
+ /// Updates `self.x_pos`.
155
+ fn write_rendered_char ( & mut self , rendered_char : RasterizedChar ) {
156
+ for ( y, row) in rendered_char. raster ( ) . iter ( ) . enumerate ( ) {
119
157
for ( x, byte) in row. iter ( ) . enumerate ( ) {
120
158
self . write_pixel ( self . x_pos + x, self . y_pos + y, * byte) ;
121
159
}
122
160
}
123
- self . x_pos += rendered_char. width ( ) ;
161
+ self . x_pos += rendered_char. width ( ) + LETTER_SPACING ;
124
162
}
125
163
126
164
fn write_pixel ( & mut self , x : usize , y : usize , intensity : u8 ) {
0 commit comments