noto_sans_mono_bitmap/lib.rs
1//! Provides pre-rasterized characters from the "Noto Sans Mono" font in different sizes and font
2//! weights for multiple unicode ranges. This crate is `no_std` and needs no allocations or floating
3//! point operations. Useful in kernels and bootloaders when only "soft-float" is available. Strictly
4//! speaking, this crate is more than a basic bitmap font, because it encodes each pixel as a byte
5//! and not as a bit, which results in a much nicer result on the screen.
6//!
7//! * Original font files taken from: <https://fonts.google.com/noto/specimen/Noto+Sans+Mono>
8//! * License: SIL Open Font License (OFL) <https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL>
9//!
10//! ## TL;DR
11//! * ✅ `no_std`, zero allocations, no floating point operations
12//! * ✅ most important symbols, numbers, and letters as pre-rasterized constant. Unicode-ranges are selectable.
13//! * ✅ Noto Sans Mono font as base
14//! * ✅ different sizes and font weights (light, normal, bold)
15//! * ✅ nice anti-aliasing/smoothing and better looking than legacy bitmap fonts
16//! * ✅ every pixel is encoded in a byte (0-255) and not a bit, which results in a much nicer result on the screen.
17//! * ✅ relevant font sizes, such as 14, 18, 22, and 32px (as optional build time features)
18//! * ✅ zero dependencies
19//! * ✅ All characters are aligned in their box/raster. If they are printed next to each other, the result looks nice.
20//!
21//! Please check [README.md](https://github.com/phip1611/noto-sans-mono-bitmap-rs/blob/main/README.md)
22//! for more details.
23
24// # THIS FILE IS AUTO GENERATED BY THE PROJECT IN "../codegen" (see repository!)
25
26#![no_std]
27#![deny(
28 clippy::all,
29 clippy::cargo,
30 clippy::nursery,
31 // clippy::restriction,
32 // clippy::pedantic
33)]
34// now allow a few rules which are denied by the above statement
35// --> they are ridiculous and not necessary
36#![allow(
37 clippy::suboptimal_flops,
38 clippy::redundant_pub_crate,
39 clippy::fallible_impl_from,
40 clippy::large_stack_frames
41)]
42#![deny(missing_debug_implementations)]
43#![deny(rustdoc::all)]
44
45// # THIS FILE IS AUTO GENERATED BY THE PROJECT IN "../codegen" (see repository!)
46
47mod bold;
48mod light;
49mod regular;
50
51/// Describes the relevant information for a rendered char of the font.
52#[derive(Debug)]
53pub struct RasterizedChar {
54 /// The actual font data that is `height` * `width` bytes in size.
55 /// Each byte describes the intensity of a pixel from 0 to 255.
56 raster: &'static [&'static [u8]],
57 /// Height of the raster box. The actual font size is slightly smaller.
58 height: usize,
59 /// The width of the rasterized char. It is guaranteed, that all chars
60 /// of the same font weight and raster height also have the same width
61 /// (as you would expect from a mono font.)
62 width: usize,
63}
64
65impl RasterizedChar {
66 /// The actual font data that is `height` * `width` bytes in size.
67 /// Each byte describes the intensity of a pixel from 0 to 255.
68 #[inline]
69 pub const fn raster(&self) -> &'static [&'static [u8]] {
70 self.raster
71 }
72
73 /// Height of the raster box. The actual font size is slightly smaller.
74 #[inline]
75 pub const fn height(&self) -> usize {
76 self.height
77 }
78
79 /// The width of the raster char. It is guaranteed, that all chars
80 /// of the same font weight and raster height also have the same width
81 /// (as you would expect from a mono font).
82 #[inline]
83 pub const fn width(&self) -> usize {
84 self.width
85 }
86}
87
88/// Supported font weights.
89///
90/// The available variants depend on the selected Cargo build features.
91#[derive(Debug, Copy, Clone)]
92#[repr(usize)]
93pub enum FontWeight {
94 #[cfg(feature = "light")]
95 Light,
96 #[cfg(feature = "regular")]
97 Regular,
98 #[cfg(feature = "bold")]
99 Bold,
100}
101
102impl FontWeight {
103 /// Returns the numeric value of the enum variant.
104 #[inline]
105 pub const fn val(self) -> usize {
106 self as _
107 }
108}
109
110/// The height of the pre-rasterized font.
111///
112/// The font size will be a few percent less, because each letter contains
113/// vertical padding for proper alignment of chars (i.e. ÄyA). The width of
114/// each character will be also less than the height, because there is no
115/// horizontal padding included.
116///
117/// The available variants depend on the selected Cargo build features.
118#[derive(Debug, Clone, Copy)]
119#[repr(usize)]
120pub enum RasterHeight {
121 #[cfg(feature = "size_16")]
122 Size16 = 16,
123 #[cfg(feature = "size_20")]
124 Size20 = 20,
125 #[cfg(feature = "size_24")]
126 Size24 = 24,
127 #[cfg(feature = "size_32")]
128 Size32 = 32,
129}
130
131impl RasterHeight {
132 /// Returns the numeric value of the variant.
133 #[inline]
134 pub const fn val(self) -> usize {
135 self as _
136 }
137}
138
139/// Returns a [`RasterizedChar`] for the given char, [`FontWeight`], and [`RasterHeight`].
140///
141/// Returns None, if the given char is not known by the font. In this case,
142/// you could fall back to `get_raster(' ', ...)`.
143#[inline]
144pub fn get_raster(c: char, style: FontWeight, size: RasterHeight) -> Option<RasterizedChar> {
145 let raster = match style {
146 #[cfg(feature = "light")]
147 FontWeight::Light => match size {
148 #[cfg(feature = "size_16")]
149 RasterHeight::Size16 => crate::light::size_16::get_char(c),
150 #[cfg(feature = "size_20")]
151 RasterHeight::Size20 => crate::light::size_20::get_char(c),
152 #[cfg(feature = "size_24")]
153 RasterHeight::Size24 => crate::light::size_24::get_char(c),
154 #[cfg(feature = "size_32")]
155 RasterHeight::Size32 => crate::light::size_32::get_char(c),
156 },
157 #[cfg(feature = "regular")]
158 FontWeight::Regular => match size {
159 #[cfg(feature = "size_16")]
160 RasterHeight::Size16 => crate::regular::size_16::get_char(c),
161 #[cfg(feature = "size_20")]
162 RasterHeight::Size20 => crate::regular::size_20::get_char(c),
163 #[cfg(feature = "size_24")]
164 RasterHeight::Size24 => crate::regular::size_24::get_char(c),
165 #[cfg(feature = "size_32")]
166 RasterHeight::Size32 => crate::regular::size_32::get_char(c),
167 },
168 #[cfg(feature = "bold")]
169 FontWeight::Bold => match size {
170 #[cfg(feature = "size_16")]
171 RasterHeight::Size16 => crate::bold::size_16::get_char(c),
172 #[cfg(feature = "size_20")]
173 RasterHeight::Size20 => crate::bold::size_20::get_char(c),
174 #[cfg(feature = "size_24")]
175 RasterHeight::Size24 => crate::bold::size_24::get_char(c),
176 #[cfg(feature = "size_32")]
177 RasterHeight::Size32 => crate::bold::size_32::get_char(c),
178 },
179 };
180
181 raster.map(|raster| RasterizedChar {
182 raster,
183 height: size.val(),
184 width: get_raster_width(style, size),
185 })
186}
187
188/// Returns the width in pixels a char will occupy on the screen.
189///
190/// The width is constant for all characters regarding the same combination
191/// of [`FontWeight`] and [`RasterHeight`]. The width is a few percent smaller
192/// than the height of each char
193#[inline]
194pub const fn get_raster_width(style: FontWeight, size: RasterHeight) -> usize {
195 match style {
196 #[cfg(feature = "light")]
197 FontWeight::Light => match size {
198 #[cfg(feature = "size_16")]
199 RasterHeight::Size16 => crate::light::size_16::RASTER_WIDTH,
200 #[cfg(feature = "size_20")]
201 RasterHeight::Size20 => crate::light::size_20::RASTER_WIDTH,
202 #[cfg(feature = "size_24")]
203 RasterHeight::Size24 => crate::light::size_24::RASTER_WIDTH,
204 #[cfg(feature = "size_32")]
205 RasterHeight::Size32 => crate::light::size_32::RASTER_WIDTH,
206 },
207 #[cfg(feature = "regular")]
208 FontWeight::Regular => match size {
209 #[cfg(feature = "size_16")]
210 RasterHeight::Size16 => crate::regular::size_16::RASTER_WIDTH,
211 #[cfg(feature = "size_20")]
212 RasterHeight::Size20 => crate::regular::size_20::RASTER_WIDTH,
213 #[cfg(feature = "size_24")]
214 RasterHeight::Size24 => crate::regular::size_24::RASTER_WIDTH,
215 #[cfg(feature = "size_32")]
216 RasterHeight::Size32 => crate::regular::size_32::RASTER_WIDTH,
217 },
218 #[cfg(feature = "bold")]
219 FontWeight::Bold => match size {
220 #[cfg(feature = "size_16")]
221 RasterHeight::Size16 => crate::bold::size_16::RASTER_WIDTH,
222 #[cfg(feature = "size_20")]
223 RasterHeight::Size20 => crate::bold::size_20::RASTER_WIDTH,
224 #[cfg(feature = "size_24")]
225 RasterHeight::Size24 => crate::bold::size_24::RASTER_WIDTH,
226 #[cfg(feature = "size_32")]
227 RasterHeight::Size32 => crate::bold::size_32::RASTER_WIDTH,
228 },
229 }
230}
231
232// # THIS FILE IS AUTO GENERATED BY THE PROJECT IN "../codegen" (see repository!)