]> git.nega.tv - josh/narcissus/commitdiff
core: Add svg debug output helper
authorJoshua Simmons <josh@nega.tv>
Thu, 20 Apr 2023 20:28:24 +0000 (22:28 +0200)
committerJoshua Simmons <josh@nega.tv>
Mon, 29 May 2023 07:13:43 +0000 (09:13 +0200)
libs/narcissus-core/src/lib.rs
libs/narcissus-core/src/svg.rs [new file with mode: 0644]

index 29a194c1be37909733a14f8e14f5b362aa2f967c..1c0393357297f9c95dd451f7b7ab07d3d023116e 100644 (file)
@@ -11,6 +11,7 @@ pub mod rand;
 pub mod raw_window;
 mod ref_count;
 pub mod slice;
+pub mod svg;
 mod uuid;
 mod virtual_mem;
 mod virtual_vec;
diff --git a/libs/narcissus-core/src/svg.rs b/libs/narcissus-core/src/svg.rs
new file mode 100644 (file)
index 0000000..6fdba40
--- /dev/null
@@ -0,0 +1,379 @@
+use std::fmt;
+
+pub const fn rgb(r: u8, g: u8, b: u8) -> Color {
+    Color::Rgb(Rgb { r, g, b })
+}
+
+pub const fn hsl(h: u32, s: u32, l: u32) -> Color {
+    Color::Hsl(Hsl { h, s, l })
+}
+
+pub const fn black() -> Color {
+    rgb(0, 0, 0)
+}
+
+pub const fn white() -> Color {
+    rgb(255, 255, 255)
+}
+
+pub const fn red() -> Color {
+    rgb(255, 0, 0)
+}
+
+pub const fn green() -> Color {
+    rgb(0, 255, 0)
+}
+
+pub const fn blue() -> Color {
+    rgb(0, 0, 255)
+}
+
+pub const fn fill(color: Color, alpha: f32) -> Fill {
+    Fill::Color(color, alpha)
+}
+
+pub const fn stroke(color: Color, width: f32, alpha: f32) -> Stroke {
+    Stroke::Color(color, width, alpha)
+}
+
+pub fn svg_begin(w: f32, h: f32) -> SvgBegin {
+    SvgBegin { w, h }
+}
+
+pub fn svg_end() -> SvgEnd {
+    SvgEnd
+}
+
+pub fn rect(x: f32, y: f32, w: f32, h: f32) -> Rect {
+    Rect {
+        x,
+        y,
+        w,
+        h,
+        style: Default::default(),
+        border_radius: 0.0,
+    }
+}
+
+pub fn circle(x: f32, y: f32, r: f32) -> Circle {
+    Circle {
+        x,
+        y,
+        r,
+        style: Default::default(),
+    }
+}
+
+pub fn path_begin() -> PathBegin {
+    PathBegin {
+        style: Default::default(),
+    }
+}
+
+pub fn path_end() -> PathEnd {
+    PathEnd
+}
+
+pub fn path_move_to(x: f32, y: f32) -> PathOp {
+    PathOp::MoveTo { x, y }
+}
+
+pub fn path_line_to(x: f32, y: f32) -> PathOp {
+    PathOp::MoveTo { x, y }
+}
+
+pub fn path_quadratic(x1: f32, y1: f32, x: f32, y: f32) -> PathOp {
+    PathOp::QuadraticTo { x1, y1, x, y }
+}
+
+pub fn path_cubic(x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) -> PathOp {
+    PathOp::CubicTo {
+        x1,
+        y1,
+        x2,
+        y2,
+        x,
+        y,
+    }
+}
+
+pub fn path_close() -> PathOp {
+    PathOp::Close
+}
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub struct Rgb {
+    pub r: u8,
+    pub g: u8,
+    pub b: u8,
+}
+
+impl fmt::Display for Rgb {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "rgb({}, {}, {})", self.r, self.g, self.b)
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub struct Hsl {
+    pub h: u32,
+    pub s: u32,
+    pub l: u32,
+}
+
+impl fmt::Display for Hsl {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let h = self.h % 360;
+        let s = self.s.min(100);
+        let l = self.s.min(100);
+        write!(f, "hsl({h}, {s}%, {l}%)")
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub enum Color {
+    Hsl(Hsl),
+    Rgb(Rgb),
+}
+
+impl fmt::Display for Color {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Color::Hsl(hsl) => write!(f, "{hsl}"),
+            Color::Rgb(rgb) => write!(f, "{rgb}"),
+        }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum Fill {
+    None,
+    Color(Color, f32),
+}
+
+impl fmt::Display for Fill {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Fill::None => write!(f, "fill:none;"),
+            Fill::Color(color, opacity) => write!(f, "fill:{color};fill-opacity:{opacity};"),
+        }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum Stroke {
+    None,
+    Color(Color, f32, f32),
+}
+
+impl fmt::Display for Stroke {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Stroke::None => write!(f, "stroke:none"),
+            Stroke::Color(color, opacity, width) => write!(
+                f,
+                "stroke:{color};stroke-opacity:{opacity};stroke-width:{width}"
+            ),
+        }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub struct Style {
+    fill: Fill,
+    stroke: Stroke,
+}
+
+impl Default for Style {
+    fn default() -> Self {
+        Self {
+            fill: fill(black(), 1.0),
+            stroke: Stroke::None,
+        }
+    }
+}
+
+impl fmt::Display for Style {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}{}", self.fill, self.stroke)
+    }
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub struct Rect {
+    pub x: f32,
+    pub y: f32,
+    pub w: f32,
+    pub h: f32,
+    pub style: Style,
+    pub border_radius: f32,
+}
+
+impl Rect {
+    pub fn style(mut self, style: Style) -> Self {
+        self.style = style;
+        self
+    }
+
+    pub fn border_radius(mut self, border_radius: f32) -> Self {
+        self.border_radius = border_radius;
+        self
+    }
+}
+
+impl fmt::Display for Rect {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            r#"<rect x="{}" y="{}" width="{}" height="{}" ry="{}" style="{}" />""#,
+            self.x, self.y, self.w, self.h, self.border_radius, self.style
+        )
+    }
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub struct Circle {
+    pub x: f32,
+    pub y: f32,
+    pub r: f32,
+    pub style: Style,
+}
+
+impl Circle {
+    pub fn style(mut self, style: Style) -> Self {
+        self.style = style;
+        self
+    }
+}
+
+impl fmt::Display for Circle {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            r#"<circle cx="{}" cy="{}" r="{}" style="{}" />""#,
+            self.x, self.y, self.r, self.style,
+        )
+    }
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub struct PathBegin {
+    style: Style,
+}
+
+impl PathBegin {
+    pub fn style(mut self, style: Style) -> Self {
+        self.style = style;
+        self
+    }
+}
+
+impl fmt::Display for PathBegin {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, r#"<path style="{}" d=""#, self.style)
+    }
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum PathOp {
+    MoveTo {
+        x: f32,
+        y: f32,
+    },
+    LineTo {
+        x: f32,
+        y: f32,
+    },
+    QuadraticTo {
+        x1: f32,
+        y1: f32,
+        x: f32,
+        y: f32,
+    },
+    CubicTo {
+        x1: f32,
+        y1: f32,
+        x2: f32,
+        y2: f32,
+        x: f32,
+        y: f32,
+    },
+    Close,
+}
+
+impl fmt::Display for PathOp {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            PathOp::MoveTo { x, y } => write!(f, "M {x} {y} "),
+            PathOp::LineTo { x, y } => write!(f, "L {x} {y} "),
+            PathOp::QuadraticTo { x1, y1, x, y } => write!(f, "Q {x1} {y1} {x} {y} "),
+            PathOp::CubicTo {
+                x1,
+                y1,
+                x2,
+                y2,
+                x,
+                y,
+            } => write!(f, "C {x1} {y1} {x2} {y2} {x} {y} "),
+            PathOp::Close => write!(f, "Z "),
+        }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub struct PathEnd;
+
+impl fmt::Display for PathEnd {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, r#"" />"#)
+    }
+}
+
+pub struct Text<'a, T>
+where
+    T: fmt::Display,
+{
+    pub x: f32,
+    pub y: f32,
+    pub size: f32,
+    pub style: Style,
+    pub text: &'a T,
+}
+
+impl<'a, T> fmt::Display for Text<'a, T>
+where
+    T: fmt::Display,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            r#"<text x="{}" y="{}" style="font-size:{};{}">{}</text>"#,
+            self.x, self.y, self.size, self.style, self.text
+        )
+    }
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub struct SvgBegin {
+    pub w: f32,
+    pub h: f32,
+}
+
+impl fmt::Display for SvgBegin {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            r#"<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {} {}">"#,
+            self.w, self.h,
+        )
+    }
+}
+
+#[derive(Copy, Clone)]
+pub struct SvgEnd;
+
+impl fmt::Display for SvgEnd {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "</svg>")
+    }
+}