mod finalize;
pub mod partial;
use std::str;
use camino::Utf8PathBuf;
pub use self::partial::PartialMeme;
#[non_exhaustive]
#[derive(Clone, Debug)]
pub struct Meme {
pub base: MemeBase,
pub text: Vec<TextBox>,
}
#[non_exhaustive]
#[derive(Clone, Debug)]
pub enum MemeBase {
#[non_exhaustive]
Canvas {
color: Color,
size: (u32, u32),
},
Image(Utf8PathBuf),
}
#[non_exhaustive]
#[derive(Clone, Debug)]
pub struct TextBox {
pub text: String,
pub position: (f32, f32),
pub size: (f32, f32),
pub rotate: Option<f32>,
pub font: String,
pub caps: bool,
pub color: Color,
pub outline: Option<TextOutline>,
pub font_size: f32,
pub line_height: f32,
pub halign: HAlign,
pub valign: VAlign,
}
#[non_exhaustive]
#[derive(Copy, Clone, Debug)]
pub struct TextOutline {
pub color: Color,
pub width: f32,
}
impl TextOutline {
pub(crate) const DEFAULT_WIDTH: f32 = 0.075;
}
impl TextOutline {
pub(crate) fn width_for_font_size(&self, font_size: f32) -> f32 {
if self.width < 1.0 {
self.width * font_size
} else {
self.width
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct Color([f32; 4]);
#[allow(dead_code)]
impl Color {
const WHITE: Self = Color([1.0, 1.0, 1.0, 1.0]);
const BLACK: Self = Color([0.0, 0.0, 0.0, 1.0]);
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Color {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
csscolorparser::Color::deserialize(deserializer).map(|color| Self(color.to_array()))
}
}
#[cfg(feature = "render")]
impl From<Color> for tiny_skia::Color {
fn from(Color([r, g, b, a]): Color) -> Self {
tiny_skia::Color::from_rgba(r, g, b, a)
.expect("`Color` should only be able to be instanciated with valid values")
}
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum VAlign {
Top,
#[default]
Center,
Bottom,
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
pub enum HAlign {
Left,
#[default]
Center,
Right,
}
#[cfg(feature = "render")]
impl From<HAlign> for parley::Alignment {
fn from(align: HAlign) -> Self {
match align {
HAlign::Left => parley::Alignment::Left,
HAlign::Center => parley::Alignment::Middle,
HAlign::Right => parley::Alignment::Right,
}
}
}