barg/
lib.rs

1//! A GUI toolkit & 3D graphics renderer.
2//!
3//! ## Naming
4//! The name is a combination of "bar" as in "foo bar baz qux" and "g" as in "graphics".  It is also fun to yell because "BARG!!!" sounds like "ARGH!!!!".
5//!
6//!
7
8extern crate fonterator;
9
10use fonterator::footile;
11
12pub mod icons;
13mod gui;
14mod window;
15
16pub use crate::gui::Gui;
17pub use crate::window::*;
18
19pub use fonterator::{
20    FontGroup, PathOp,
21    PathOp::*,
22    PathOp::{Line, Move, Quad},
23};
24
25use footile::PixFmt;
26
27/// Size of an image (width, height).
28#[derive(Copy, Clone)]
29pub struct Size(pub u16, pub u16);
30
31/// Texture Coordinates (Mapped to a `PathOp`).
32#[derive(Copy, Clone)]
33pub struct TexCoord(pub f32, pub f32);
34
35/// An Image
36pub struct Image {
37    plotter: footile::Plotter,
38    raster: footile::RasterB<footile::Rgba8>,
39}
40
41impl Image {
42    /// Create new Image.
43    pub fn new(size: Size) -> Self {
44        let (w, h) = (u32::from(size.0), u32::from(size.1));
45
46        Image {
47            plotter: footile::Plotter::new(w, h),
48            raster: footile::RasterB::new(w, h),
49        }
50    }
51
52    /// Get the size of the image.
53    pub fn size(&self) -> Size {
54        Size(self.raster.width() as u16, self.raster.height() as u16)
55    }
56
57    /// Clear the Image.
58    pub unsafe fn clear_ptr(&mut self, pixels: *mut u8) {
59        let len =
60            self.raster.width() as usize * self.raster.height() as usize * 4;
61        self.clear(std::slice::from_raw_parts_mut(pixels, len))
62    }
63
64    /// Clear the Image.
65    pub fn clear(&mut self, pixels: &mut [u8]) {
66        self.raster.clear(footile::Rgba8::as_slice_mut(pixels));
67    }
68
69    /// Draw a path a solid color (sRGBA).
70    pub unsafe fn fill_ptr<'b, T>(&mut self, color: [u8; 4], path: T, pixels: *mut u8)
71    where
72        T: IntoIterator<Item = &'b PathOp>,
73    {
74        let len =
75            self.raster.width() as usize * self.raster.height() as usize * 4;
76        self.fill(color, path,
77            std::slice::from_raw_parts_mut(pixels, len)
78        )
79    }
80
81    /// Draw a path a solid color (sRGBA).
82    pub unsafe fn stroke_ptr<'b, T>(
83        &mut self,
84        color: [u8; 4],
85        path: T,
86        pixels: *mut u8,
87    ) where
88        T: IntoIterator<Item = &'b PathOp>,
89    {
90        let len =
91            self.raster.width() as usize * self.raster.height() as usize * 4;
92        self.stroke(color, path,            std::slice::from_raw_parts_mut(pixels, len))
93    }
94
95    /// Draw a path a solid color (sRGBA).
96    pub fn fill<'b, T>(&mut self, color: [u8; 4], path: T, pixels: &mut [u8])
97    where
98        T: IntoIterator<Item = &'b PathOp>,
99    {
100        let iter = path.into_iter();
101        let color = footile::Rgba8::new(color[0], color[1], color[2], color[3]);
102
103        self.raster.over(
104            self.plotter.fill(iter, footile::FillRule::NonZero),
105            color,
106            footile::Rgba8::as_slice_mut(pixels),
107        );
108    }
109
110    /// Draw a path a solid color (sRGBA).
111    pub fn stroke<'b, T>(&mut self, color: [u8; 4], path: T, pixels: &mut [u8])
112    where
113        T: IntoIterator<Item = &'b PathOp>,
114    {
115        let iter = path.into_iter();
116        let color = footile::Rgba8::new(color[0], color[1], color[2], color[3]);
117
118        self.raster.over(
119            self.plotter.stroke(iter),
120            color,
121            footile::Rgba8::as_slice_mut(pixels),
122        );
123    }
124
125    /// Draw text.
126    pub unsafe fn text_ptr(
127        &mut self,
128        color: [u8; 4],
129        xysize: (f32, f32, f32),
130        font: &FontGroup,
131        text: &str,
132        pixels: *mut u8,
133    ) -> (f32, f32) {
134        let len =
135            self.raster.width() as usize * self.raster.height() as usize * 4;
136        self.text(color, xysize, font, text,
137            std::slice::from_raw_parts_mut(pixels, len)
138        )
139    }
140
141    /// Draw text.
142    pub fn text(
143        &mut self,
144        color: [u8; 4],
145        xysize: (f32, f32, f32),
146        font: &FontGroup,
147        text: &str,
148        pixels: &mut [u8],
149    ) -> (f32, f32) {
150        let color = footile::Rgba8::new(color[0], color[1], color[2], color[3]);
151
152        // Render the text
153        let mut path = font.render(
154            text,                 /*text*/
155            (xysize.0, xysize.1), /*position*/
156            (xysize.2, xysize.2), /*size*/
157        );
158
159        self.raster.over(
160            self.plotter.fill(&mut path, footile::FillRule::NonZero),
161            color,
162            footile::Rgba8::as_slice_mut(pixels),
163        );
164
165        let (cx, cy) = path.xy();
166
167        (cx, cy)
168    }
169}
170
171#[cfg(test)]
172mod tests {
173    #[test]
174    fn it_works() {
175        assert_eq!(2 + 2, 4);
176    }
177}
178
179// Initialize graphic shader.
180pub fn init_toolbar(window: &mut Window) -> (Shader, Shape) {
181    let mut gui = window.shader_new(shader!("gui"));
182
183    // Define vertices.
184    #[rustfmt::skip]
185    let vertices = [
186        -1.0, -1.0,  0.0, 1.0,
187         1.0, -1.0,  1.0, 1.0,
188         1.0,  1.0,  1.0, 0.0,
189
190        -1.0,  1.0,  0.0, 0.0,
191        -1.0, -1.0,  0.0, 1.0,
192         1.0,  1.0,  1.0, 0.0,
193    ];
194
195    // Build cube Shape
196    let mut rect = window.shape_new(ShapeBuilder::new(&mut gui).vert(&vertices).face(Transform::new()));
197    window.instances(&mut rect, &[Transform::new()]);
198    window.build(&mut gui);
199
200    (gui, rect)
201}