mod layout;
mod node;
mod reconcile;
pub use layout::measure_image;
pub use node::ImageNode;
pub use reconcile::reconcile_image;
use std::sync::Arc;
use crate::core::element::{Element, ElementKind};
use crate::style::{Length, Style};
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum ImageSource {
Path(Arc<str>),
Bytes(Arc<[u8]>),
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum ImageFit {
#[default]
Contain,
Crop,
Scale,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum ImageProtocol {
#[default]
Auto,
Kitty,
Iterm2,
Sixel,
Halfblocks,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum ImagePlayback {
#[default]
Playing,
Paused,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum ImageRepeat {
#[default]
Loop,
Once,
}
#[derive(Clone)]
pub struct Image {
pub source: ImageSource,
pub style: Style,
pub width: Length,
pub height: Length,
pub fit: ImageFit,
pub protocol: ImageProtocol,
pub alt: Option<Arc<str>>,
pub playback: ImagePlayback,
pub repeat: ImageRepeat,
pub speed_percent: u16,
}
impl Image {
pub fn new(src: impl Into<Arc<str>>) -> Self {
Self {
source: ImageSource::Path(src.into()),
style: Style::default(),
width: Length::Auto,
height: Length::Auto,
fit: ImageFit::default(),
protocol: ImageProtocol::default(),
alt: None,
playback: ImagePlayback::default(),
repeat: ImageRepeat::default(),
speed_percent: 100,
}
}
pub fn from_bytes(bytes: impl Into<Arc<[u8]>>) -> Self {
Self {
source: ImageSource::Bytes(bytes.into()),
style: Style::default(),
width: Length::Auto,
height: Length::Auto,
fit: ImageFit::default(),
protocol: ImageProtocol::default(),
alt: None,
playback: ImagePlayback::default(),
repeat: ImageRepeat::default(),
speed_percent: 100,
}
}
pub fn src(mut self, src: impl Into<Arc<str>>) -> Self {
self.source = ImageSource::Path(src.into());
self
}
pub fn bytes(mut self, bytes: impl Into<Arc<[u8]>>) -> Self {
self.source = ImageSource::Bytes(bytes.into());
self
}
pub fn style(mut self, style: Style) -> Self {
self.style = style;
self
}
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
pub fn height(mut self, height: Length) -> Self {
self.height = height;
self
}
pub fn fit(mut self, fit: ImageFit) -> Self {
self.fit = fit;
self
}
pub fn protocol(mut self, protocol: ImageProtocol) -> Self {
self.protocol = protocol;
self
}
pub fn alt(mut self, alt: impl Into<Arc<str>>) -> Self {
self.alt = Some(alt.into());
self
}
pub fn playback(mut self, playback: ImagePlayback) -> Self {
self.playback = playback;
self
}
pub fn paused(mut self, paused: bool) -> Self {
self.playback = if paused {
ImagePlayback::Paused
} else {
ImagePlayback::Playing
};
self
}
pub fn repeat(mut self, repeat: ImageRepeat) -> Self {
self.repeat = repeat;
self
}
pub fn looping(mut self, looping: bool) -> Self {
self.repeat = if looping {
ImageRepeat::Loop
} else {
ImageRepeat::Once
};
self
}
pub fn speed_percent(mut self, speed_percent: u16) -> Self {
self.speed_percent = speed_percent.max(1);
self
}
}
impl From<Image> for Element {
fn from(value: Image) -> Self {
Element::new(ElementKind::Image(value))
}
}
impl crate::layout::hash::LayoutHash for Image {
fn layout_hash(
&self,
hasher: &mut impl std::hash::Hasher,
_recurse: &dyn Fn(&crate::core::element::Element) -> Option<u64>,
) -> Option<()> {
use std::hash::Hash;
self.width.hash(hasher);
self.height.hash(hasher);
self.fit.hash(hasher);
self.protocol.hash(hasher);
self.playback.hash(hasher);
self.repeat.hash(hasher);
self.speed_percent.hash(hasher);
self.source.hash(hasher);
self.alt.hash(hasher);
Some(())
}
}