60 releases
0.8.22 | Feb 26, 2025 |
---|---|
0.8.21-pre | Jul 10, 2024 |
0.8.20-pre | Mar 8, 2024 |
0.8.16-pre | Oct 23, 2023 |
0.4.11 | Jul 30, 2021 |
#18 in Rendering
412 downloads per month
Used in 5 crates
160KB
3.5K
SLoC
dessin
dessin is library aimed at building complex drawings, combine them, move them and export them as PDF or SVG.
Details about the macro.
Example
use dessin::prelude::*;
use palette::{named, Srgb};
#[derive(Default, Shape)]
struct MyShape {
text: String,
}
impl MyShape {
fn say_this(&mut self, what: &str) {
self.text = format!("{} And check this out: `{what}`", self.text);
}
}
impl From<MyShape> for Shape {
fn from(MyShape { text }: MyShape) -> Self {
dessin!(*Text(fill = Srgb::<f32>::from_format(named::RED).into_linear(), { text })).into()
}
}
fn main() {
let dessin = dessin!(for x in 0..10 {
let radius = x as f32 * 10.;
dessin!([
*Circle(
fill = Srgb::<f32>::from_format(named::RED).into_linear(),
{ radius },
translate = [x as f32 * 5., 10.],
),
*Text(fill = Srgb::<f32>::from_format(named::BLACK).into_linear(), font_size = 10., text = "Hi !",),
])
});
let dessin = dessin!([
{ dessin }(scale = [2., 2.]),
MyShape(say_this = "Hello world"),
]);
}
Components
Base components are defined in the shapes
module.
Components using base ones are defined in the contrib
module.
In dessin
, a component is just a struct/enum that can be converted to a Shape,
and implements the Default trait.
This means that a component can be as simple as:
use dessin::prelude::*;
#[derive(Default)]
struct MyComponent {}
impl From<MyComponent> for Shape {
fn from(my_component: MyComponent) -> Shape {
dessin!(
// Implementation...
)
}
}
Since the dessin! macro is only syntactic sugar for creating a Shape,
all parameters are simply rust function with the following signature: fn (&mut self, argument_value: ArgumentType) {...}
.
It can be tedious to create these function for all parameters, so the derive macro Shape is here to do exactly that.
So
#[derive(Default, Shape)]
struct MyComponent {
// This auto implements ShapeOp for MyComponent using `my_local_transform` as the storage.
#[local_transform]
my_local_transform: Transform2<f32>,
// Generate a function for u32
value: u32,
// Does not generate a function for this field
#[shape(skip)]
skip_value: u32,
// Generates a function for Into<u32>
#[shape(into)]
into_value: u32,
// Generates a function that does not take any arguments, but set `my_bool` to true
#[shape(bool)]
my_bool: bool,
}
becomes
#[derive(Default)]
struct MyComponent {
my_local_transform: Transform2<f32>,
value: u32,
skip_value: u32,
into_value: u32,
my_bool: bool,
}
impl ShapeOp for MyComponent { /* skip impl */ }
impl MyComponent {
pub fn value(&mut self, value: u32) -> &mut Self {
/* skip impl */
}
pub fn into_value<T: Into<u32>>(&mut self, value: T) -> &mut Self {
/* skip impl */
}
pub fn my_bool(&mut self) -> &mut Self {
/* skip impl */
}
}
To be precise, all functions generated by this derive macro, return &mut Self
to chain function together.
Generated functions have the same name as their corresponding field.
This derive macro also generate corresponding with_xxxx
, taking self
instead of &mut self
and returning Self
.
One still does need to implement From<MyComponent> for Shape { ... }
manually.
Implement own export format.
Documentation can be found in the export
module.
License: MIT
Dependencies
~12MB
~202K SLoC