use std::time::SystemTime;
use crate::scene::Grid;
use crate::scene::text::Measurer;
pub use crate::text::Arial;
static ARIAL: Arial = Arial;
static UTC: Utc = Utc;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum Routing {
#[default]
Auto,
Orthogonal,
Straight,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Monospace(u8);
impl Monospace {
pub const NONE: Monospace = Monospace(0);
pub const MEMBERS: Monospace = Monospace(1);
pub const ATTRIBUTES: Monospace = Monospace(1 << 1);
pub const FILES: Monospace = Monospace(1 << 2);
pub const MESSAGES: Monospace = Monospace(1 << 3);
pub const fn contains(self, other: Monospace) -> bool {
self.0 & other.0 == other.0
}
}
impl std::ops::BitOr for Monospace {
type Output = Monospace;
fn bitor(self, other: Monospace) -> Monospace {
Monospace(self.0 | other.0)
}
}
impl std::ops::BitOrAssign for Monospace {
fn bitor_assign(&mut self, other: Monospace) {
self.0 |= other.0;
}
}
pub trait TimeZone {
fn offset(&self, at: i64) -> i32;
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Utc;
impl TimeZone for Utc {
fn offset(&self, _: i64) -> i32 {
0
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct FixedOffset(pub i32);
impl TimeZone for FixedOffset {
fn offset(&self, _: i64) -> i32 {
self.0
}
}
#[derive(Clone, Copy)]
pub struct Options<'a> {
pub measurer: &'a dyn Measurer,
pub font_size: f64,
pub icons: Option<&'a dyn Fn(&str) -> bool>,
pub max_width: f64,
pub keep_direction: bool,
pub direction_breakpoint: f64,
pub links: bool,
pub images: bool,
pub link_schemes: &'a [&'a str],
pub image_schemes: &'a [&'a str],
pub padding: Option<f64>,
pub snap: Option<Grid>,
pub routing: Routing,
pub monospace: Monospace,
pub now: Option<SystemTime>,
pub time_zone: &'a dyn TimeZone,
}
impl Default for Options<'_> {
fn default() -> Self {
Options {
measurer: &ARIAL,
font_size: 16.0,
icons: None,
max_width: f64::INFINITY,
keep_direction: false,
direction_breakpoint: 640.0,
links: true,
images: true,
link_schemes: &["http", "https", "mailto", "tel"],
image_schemes: &["http", "https"],
padding: None,
snap: None,
routing: Routing::Auto,
monospace: Monospace::NONE,
now: None,
time_zone: &UTC,
}
}
}
impl Options<'_> {
pub(crate) fn pad(&self) -> f64 {
self.padding.unwrap_or(8.0)
}
pub(crate) fn schemes(&self) -> crate::url::Schemes<'_> {
crate::url::Schemes {
links: self.links,
images: self.images,
link_schemes: self.link_schemes,
image_schemes: self.image_schemes,
}
}
pub(crate) fn clock(&self) -> f64 {
let at = self.now.unwrap_or_else(SystemTime::now);
match at.duration_since(SystemTime::UNIX_EPOCH) {
Ok(d) => d.as_millis() as f64,
Err(e) => {
let d = e.duration();
let ms = d.as_millis() as f64;
if d.subsec_nanos() % 1_000_000 == 0 {
-ms
} else {
-ms - 1.0
}
}
}
}
pub(crate) fn has_icon(&self, name: &str) -> bool {
self.icons.is_some_and(|icons| icons(name))
}
}
impl std::fmt::Debug for Options<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Options")
.field("font_size", &self.font_size)
.field("icons", &self.icons.is_some())
.field("max_width", &self.max_width)
.field("keep_direction", &self.keep_direction)
.field("direction_breakpoint", &self.direction_breakpoint)
.field("links", &self.links)
.field("images", &self.images)
.field("link_schemes", &self.link_schemes)
.field("image_schemes", &self.image_schemes)
.field("padding", &self.padding)
.field("snap", &self.snap)
.field("routing", &self.routing)
.field("monospace", &self.monospace)
.field("now", &self.now)
.finish_non_exhaustive()
}
}