egui/egui/src/paint/fonts.rs

144 lines
4.2 KiB
Rust
Raw Normal View History

2019-01-12 23:55:56 +00:00
use std::{
collections::BTreeMap,
2019-01-17 17:03:39 +00:00
hash::{Hash, Hasher},
2020-04-17 21:30:01 +00:00
sync::Arc,
2019-01-12 23:55:56 +00:00
};
use parking_lot::Mutex;
2020-04-17 21:30:01 +00:00
use super::{
2019-01-16 23:09:12 +00:00
font::Font,
texture_atlas::{Texture, TextureAtlas},
};
2019-01-12 23:55:56 +00:00
2020-07-23 12:35:12 +00:00
// TODO: rename
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
2019-01-12 23:55:56 +00:00
pub enum TextStyle {
Body,
Button,
Heading,
2019-12-02 19:08:49 +00:00
Monospace,
2019-01-12 23:55:56 +00:00
}
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
// #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
2019-12-02 19:08:49 +00:00
pub enum FontFamily {
Monospace,
VariableWidth,
}
#[derive(Clone, Debug, PartialEq)]
pub struct FontDefinitions {
/// The dpi scale factor. Needed to get pixel perfect fonts.
pub pixels_per_point: f32,
pub fonts: BTreeMap<TextStyle, (FontFamily, f32)>,
}
impl Default for FontDefinitions {
fn default() -> Self {
Self::with_pixels_per_point(f32::NAN) // must be set later
}
}
impl FontDefinitions {
pub fn with_pixels_per_point(pixels_per_point: f32) -> Self {
let mut fonts = BTreeMap::new();
fonts.insert(TextStyle::Body, (FontFamily::VariableWidth, 14.0));
fonts.insert(TextStyle::Button, (FontFamily::VariableWidth, 16.0));
fonts.insert(TextStyle::Heading, (FontFamily::VariableWidth, 24.0));
fonts.insert(TextStyle::Monospace, (FontFamily::Monospace, 13.0));
Self {
pixels_per_point,
fonts,
}
}
2020-04-12 10:07:51 +00:00
}
/// Note: the `default()` fonts are invalid (missing `pixels_per_point`).
#[derive(Default)]
2019-01-12 23:55:56 +00:00
pub struct Fonts {
2019-12-02 19:08:49 +00:00
definitions: FontDefinitions,
2019-01-12 23:55:56 +00:00
fonts: BTreeMap<TextStyle, Font>,
2019-01-16 23:09:12 +00:00
texture: Texture,
2019-01-12 23:55:56 +00:00
}
impl Fonts {
pub fn from_definitions(definitions: FontDefinitions) -> Fonts {
let mut fonts = Self::default();
fonts.set_definitions(definitions);
2019-01-17 17:03:39 +00:00
fonts
}
2019-12-02 19:08:49 +00:00
pub fn definitions(&self) -> &FontDefinitions {
&self.definitions
2019-01-17 17:03:39 +00:00
}
pub fn set_definitions(&mut self, definitions: FontDefinitions) {
2019-12-02 19:08:49 +00:00
if self.definitions == definitions {
2019-01-17 17:03:39 +00:00
return;
}
let mut atlas = TextureAtlas::new(512, 8); // TODO: better default?
2019-01-12 23:55:56 +00:00
// Make the top left four pixels fully white:
let pos = atlas.allocate((2, 2));
assert_eq!(pos, (0, 0));
atlas.texture_mut()[(0, 0)] = 255;
atlas.texture_mut()[(0, 1)] = 255;
atlas.texture_mut()[(1, 0)] = 255;
atlas.texture_mut()[(1, 1)] = 255;
2019-01-12 23:55:56 +00:00
let atlas = Arc::new(Mutex::new(atlas));
2019-01-17 17:03:39 +00:00
// TODO: figure out a way to make the wasm smaller despite including a font. Zip it?
let monospae_typeface_data = include_bytes!("../../fonts/ProggyClean.ttf"); // Use 13 for this. NOTHING ELSE.
2019-12-02 19:08:49 +00:00
// let monospae_typeface_data = include_bytes!("../../fonts/Roboto-Regular.ttf");
2020-04-29 19:58:41 +00:00
let variable_typeface_data = include_bytes!("../../fonts/Comfortaa-Regular.ttf"); // Funny, hard to read
2020-04-29 19:58:41 +00:00
// let variable_typeface_data = include_bytes!("../../fonts/DejaVuSans.ttf"); // Basic, boring, takes up more space
2019-12-02 19:08:49 +00:00
self.definitions = definitions.clone();
let FontDefinitions {
pixels_per_point,
fonts,
} = definitions;
self.fonts = fonts
2019-01-17 17:03:39 +00:00
.into_iter()
2019-12-02 19:08:49 +00:00
.map(|(text_style, (family, size))| {
let typeface_data: &[u8] = match family {
FontFamily::Monospace => monospae_typeface_data,
FontFamily::VariableWidth => variable_typeface_data,
};
2019-01-19 16:10:28 +00:00
(
text_style,
Font::new(atlas.clone(), typeface_data, size, pixels_per_point),
2019-01-19 16:10:28 +00:00
)
})
2019-01-17 17:03:39 +00:00
.collect();
2020-04-17 21:30:01 +00:00
self.texture = atlas.lock().texture().clone();
2019-01-12 23:55:56 +00:00
let mut hasher = ahash::AHasher::default();
2019-01-17 17:03:39 +00:00
self.texture.pixels.hash(&mut hasher);
self.texture.version = hasher.finish();
2019-01-12 23:55:56 +00:00
}
2019-01-16 23:09:12 +00:00
pub fn texture(&self) -> &Texture {
&self.texture
2019-01-12 23:55:56 +00:00
}
}
impl std::ops::Index<TextStyle> for Fonts {
type Output = Font;
fn index(&self, text_style: TextStyle) -> &Font {
&self.fonts[&text_style]
}
}