@@ -4,7 +4,10 @@ use core::{
44 fmt:: { self , Write } ,
55 ptr,
66} ;
7- use noto_sans_mono_bitmap:: { get_bitmap, get_bitmap_width, BitmapChar , BitmapHeight , FontWeight } ;
7+ use font_constants:: BACKUP_CHAR ;
8+ use noto_sans_mono_bitmap:: {
9+ get_raster, get_raster_width, FontWeight , RasterHeight , RasterizedChar ,
10+ } ;
811use spinning_top:: Spinlock ;
912
1013/// The global logger instance used for the `log` crate.
@@ -14,9 +17,42 @@ pub static LOGGER: OnceCell<LockedLogger> = OnceCell::uninit();
1417pub struct LockedLogger ( Spinlock < Logger > ) ;
1518
1619/// 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+ }
2056
2157impl LockedLogger {
2258 /// Create a new instance that logs to the given framebuffer.
@@ -39,8 +75,7 @@ impl log::Log for LockedLogger {
3975
4076 fn log ( & self , record : & log:: Record ) {
4177 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 ( ) ;
4479 }
4580
4681 fn flush ( & self ) { }
@@ -68,22 +103,18 @@ impl Logger {
68103 }
69104
70105 fn newline ( & mut self ) {
71- self . y_pos += 14 + LINE_SPACING ;
106+ self . y_pos += font_constants :: CHAR_RASTER_HEIGHT . val ( ) + LINE_SPACING ;
72107 self . carriage_return ( )
73108 }
74109
75- fn add_vspace ( & mut self , space : usize ) {
76- self . y_pos += space;
77- }
78-
79110 fn carriage_return ( & mut self ) {
80- self . x_pos = 0 ;
111+ self . x_pos = BORDER_PADDING ;
81112 }
82113
83- /// Erases all text on the screen.
114+ /// Erases all text on the screen. Resets `self.x_pos` and `self.y_pos`.
84115 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 ;
87118 self . framebuffer . fill ( 0 ) ;
88119 }
89120
@@ -95,30 +126,36 @@ impl Logger {
95126 self . info . height
96127 }
97128
129+ /// Writes a single char to the framebuffer. Takes care of special control characters, such as
130+ /// newlines and carriage returns.
98131 fn write_char ( & mut self , c : char ) {
99132 match c {
100133 '\n' => self . newline ( ) ,
101134 '\r' => self . carriage_return ( ) ,
102135 c => {
103- let bitmap_char = get_bitmap ( c , FontWeight :: Regular , BitmapHeight :: Size14 ) . unwrap ( ) ;
104- if self . x_pos + bitmap_char . width ( ) > self . width ( ) {
136+ let new_xpos = self . x_pos + font_constants :: CHAR_RASTER_WIDTH ;
137+ if new_xpos >= self . width ( ) {
105138 self . newline ( ) ;
106139 }
107- if self . y_pos + bitmap_char. height ( ) > self . height ( ) {
140+ let new_ypos =
141+ self . y_pos + font_constants:: CHAR_RASTER_HEIGHT . val ( ) + BORDER_PADDING ;
142+ if new_ypos >= self . height ( ) {
108143 self . clear ( ) ;
109144 }
110- self . write_rendered_char ( bitmap_char ) ;
145+ self . write_rendered_char ( get_char_raster ( c ) ) ;
111146 }
112147 }
113148 }
114149
115- fn write_rendered_char ( & mut self , rendered_char : BitmapChar ) {
116- 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 ( ) {
117154 for ( x, byte) in row. iter ( ) . enumerate ( ) {
118155 self . write_pixel ( self . x_pos + x, self . y_pos + y, * byte) ;
119156 }
120157 }
121- self . x_pos += rendered_char. width ( ) ;
158+ self . x_pos += rendered_char. width ( ) + LETTER_SPACING ;
122159 }
123160
124161 fn write_pixel ( & mut self , x : usize , y : usize , intensity : u8 ) {
0 commit comments