use eframe::egui::{Align, Color32, FontFamily, FontId, Stroke, TextFormat};
use odox_core::{Color, Position, TextProperties};
use crate::fonts::{Variant, family_of};
pub const DEFAULT_SIZE: f32 = 12.0;
const SCRIPT_SCALE: f32 = 0.58;
#[derive(Debug, Clone, Copy)]
pub struct Palette {
pub paper: Color32,
pub ink: Color32,
pub link: Color32,
}
impl Default for Palette {
fn default() -> Self {
Self {
paper: Color32::from_rgb(0xff, 0xff, 0xff),
ink: Color32::from_rgb(0x00, 0x00, 0x00),
link: Color32::from_rgb(0x1a, 0x5f, 0xb4),
}
}
}
pub fn text_format(
properties: &TextProperties,
inherited: f32,
zoom: f32,
palette: Palette,
) -> TextFormat {
let size = match properties.size {
Some(measure) => measure.resolve(inherited),
None => inherited,
};
let variant = Variant {
bold: properties.bold.unwrap_or(false),
italic: properties.italic.unwrap_or(false),
};
let family = match &properties.font_family {
Some(name) if !name.is_empty() => family_of(name, variant),
_ => FontFamily::Proportional,
};
let (scale, valign) = match properties.position {
Some(Position::Super) => (SCRIPT_SCALE, Align::TOP),
Some(Position::Sub) => (SCRIPT_SCALE, Align::BOTTOM),
_ => (1.0, Align::BOTTOM),
};
let color = properties.color.map_or(palette.ink, color32);
let line = Stroke::new((size * zoom * 0.06).max(1.0), color);
TextFormat {
font_id: FontId::new(size * zoom * scale, family),
color,
background: properties.background.map_or(Color32::TRANSPARENT, color32),
underline: if properties.underline.unwrap_or(false) {
line
} else {
Stroke::NONE
},
strikethrough: if properties.strike.unwrap_or(false) {
line
} else {
Stroke::NONE
},
valign,
italics: false,
..TextFormat::default()
}
}
pub fn link_format(
properties: &TextProperties,
inherited: f32,
zoom: f32,
palette: Palette,
) -> TextFormat {
let mut format = text_format(properties, inherited, zoom, palette);
if properties.color.is_none() {
format.color = palette.link;
if format.underline == Stroke::NONE {
format.underline = Stroke::new(1.0, format.color);
}
}
format
}
pub fn size_of(properties: &TextProperties, inherited: f32) -> f32 {
properties
.size
.map_or(inherited, |measure| measure.resolve(inherited))
}
pub fn color32(color: Color) -> Color32 {
Color32::from_rgb(color.r, color.g, color.b)
}