use std::fmt;
use crossfont::Size as FontSize;
use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
use crate::config::ui_config::Delta;
#[derive(ConfigDeserialize, Serialize, Debug, Clone, PartialEq, Eq)]
pub struct Font {
pub offset: Delta<i8>,
pub glyph_offset: Delta<i8>,
#[config(removed = "set the AppleFontSmoothing user default instead")]
pub use_thin_strokes: bool,
normal: FontDescription,
bold: SecondaryFontDescription,
italic: SecondaryFontDescription,
bold_italic: SecondaryFontDescription,
size: Size,
pub builtin_box_drawing: bool,
}
impl Font {
pub fn with_size(self, size: FontSize) -> Font {
Font { size: Size(size), ..self }
}
#[inline]
pub fn size(&self) -> FontSize {
self.size.0
}
pub fn normal(&self) -> &FontDescription {
&self.normal
}
pub fn bold(&self) -> FontDescription {
self.bold.desc(&self.normal)
}
pub fn italic(&self) -> FontDescription {
self.italic.desc(&self.normal)
}
pub fn bold_italic(&self) -> FontDescription {
self.bold_italic.desc(&self.normal)
}
}
impl Default for Font {
fn default() -> Font {
Self {
builtin_box_drawing: true,
glyph_offset: Default::default(),
use_thin_strokes: Default::default(),
bold_italic: Default::default(),
italic: Default::default(),
offset: Default::default(),
normal: Default::default(),
bold: Default::default(),
size: Default::default(),
}
}
}
#[derive(ConfigDeserialize, Serialize, Debug, Clone, PartialEq, Eq)]
pub struct FontDescription {
pub family: String,
pub style: Option<String>,
}
impl Default for FontDescription {
fn default() -> FontDescription {
FontDescription {
#[cfg(not(any(target_os = "macos", windows)))]
family: "monospace".into(),
#[cfg(target_os = "macos")]
family: "Menlo".into(),
#[cfg(windows)]
family: "Consolas".into(),
style: None,
}
}
}
#[derive(ConfigDeserialize, Serialize, Debug, Default, Clone, PartialEq, Eq)]
pub struct SecondaryFontDescription {
family: Option<String>,
style: Option<String>,
}
impl SecondaryFontDescription {
pub fn desc(&self, fallback: &FontDescription) -> FontDescription {
FontDescription {
family: self.family.clone().unwrap_or_else(|| fallback.family.clone()),
style: self.style.clone(),
}
}
}
#[derive(SerdeReplace, Debug, Clone, PartialEq, Eq)]
struct Size(FontSize);
impl Default for Size {
fn default() -> Self {
Self(FontSize::new(11.25))
}
}
impl<'de> Deserialize<'de> for Size {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct NumVisitor;
impl Visitor<'_> for NumVisitor {
type Value = Size;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("f64 or i64")
}
fn visit_f64<E: de::Error>(self, value: f64) -> Result<Self::Value, E> {
Ok(Size(FontSize::new(value as f32)))
}
fn visit_i64<E: de::Error>(self, value: i64) -> Result<Self::Value, E> {
Ok(Size(FontSize::new(value as f32)))
}
}
deserializer.deserialize_any(NumVisitor)
}
}
impl Serialize for Size {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_f32(self.0.as_pt())
}
}