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