Skip to main content

img_gen_spec/validators/layers/
mod.rs

1mod background;
2mod colors;
3mod ellipse;
4mod icon;
5mod polygon;
6mod rectangle;
7mod size_offset;
8mod typography;
9
10#[cfg(feature = "pyo3")]
11use pyo3::prelude::*;
12
13use serde::{Deserialize, Serialize};
14
15use std::{fmt, num::NonZeroU32};
16
17pub use background::Background;
18pub use colors::{
19    ColorGradient, ColorKind, ConicalGradient, LinearGradient, Presets, RadialGradient, SolidColor,
20    Spread, TRANSPARENT,
21};
22pub use ellipse::{Arc, Ellipse};
23pub use icon::Icon;
24pub use polygon::{IrregularPolygonSides, Polygon, PolygonSides, RegularPolygonSides};
25pub use rectangle::{Corners, Rectangle};
26pub use size_offset::{HEIGHT, LayerOffset, Size, WIDTH};
27pub use typography::{Font, Line, LineHeight, Typography, TypographyAlign, Weight};
28
29/// A property to describe an attributes [`Border`].
30///
31/// See [`Polygon`], [`Rectangle`], [`Ellipse`], and [`Typography`].
32#[cfg_attr(
33    feature = "pyo3",
34    pyclass(module = "img_gen", set_all, get_all, from_py_object)
35)]
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct Border {
38    /// The width (in pixels) used to draw the border.
39    pub width: NonZeroU32,
40    /// The color used to draw the border.
41    pub color: ColorKind,
42}
43
44/// The default border width in pixels.
45pub const BORDER_WIDTH: NonZeroU32 = NonZeroU32::new(1).unwrap();
46
47impl Default for Border {
48    fn default() -> Self {
49        Self {
50            width: BORDER_WIDTH,
51            color: ColorKind::default(),
52        }
53    }
54}
55
56/// An enum to describe the how to preserve an image's dimensions when portrayed in
57/// an [`Icon`] or [`Background`] attribute.
58#[cfg_attr(
59    feature = "pyo3",
60    pyclass(eq, eq_int, module = "img_gen", from_py_object)
61)]
62#[derive(Debug, PartialEq, Clone, Copy, Default, Serialize, Deserialize)]
63#[serde(rename_all = "lowercase")]
64pub enum PreserveAspect {
65    /// Preserve the original image's aspect ratio with respect to both width and height.
66    #[serde(alias = "true")]
67    #[default]
68    On,
69    /// Ignore the original image's aspect ratio.
70    /// Instead the image will be stretched to the layer's `Size`.
71    #[serde(alias = "false")]
72    Off,
73    /// Preserve the original image's aspect ratio with respect to width.
74    Width,
75    /// Preserve the original image's aspect ratio with respect to height.
76    Height,
77}
78
79impl PreserveAspect {
80    /// Instantiate a [`PreserveAspect`] object from a string.
81    ///
82    /// Possible values include `"true"`, `"false"`, `"width"`, or `"height"`.
83    /// If a given `value` does not match those values (case insensitive), then
84    /// [`PreserveAspect::On`] is returned.
85    pub fn from_string(value: &str) -> PreserveAspect {
86        match value.to_lowercase().as_str() {
87            "false" => PreserveAspect::Off,
88            "width" => PreserveAspect::Width,
89            "height" => PreserveAspect::Height,
90            _ => PreserveAspect::On,
91        }
92    }
93}
94
95impl fmt::Display for PreserveAspect {
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        match self {
98            PreserveAspect::On => write!(f, "true"),
99            PreserveAspect::Off => write!(f, "false"),
100            PreserveAspect::Width => write!(f, "width"),
101            PreserveAspect::Height => write!(f, "height"),
102        }
103    }
104}
105
106#[cfg(test)]
107mod test {
108    use super::PreserveAspect;
109
110    #[test]
111    fn test_str() {
112        let str_values = ["true", "false", "width", "height"];
113        for str_val in str_values {
114            let val = PreserveAspect::from_string(str_val).to_string();
115            assert_eq!(val, str_val);
116        }
117        assert_eq!(PreserveAspect::from_string("val").to_string(), "true");
118    }
119}