Expand description
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][dessin_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.
Re-exports§
Modules§
- contrib
- Shapes made of basic shapes
- export
- Declarations to create an export format. Documentation to export a dessin in a specific format.
- font
- Everything related to fonts.
- macros
- DSL definition
- prelude
- Prelude module includes everyting you need to build a dessin. You can of courses cherry pick what you need by importing directly from other modules.
- shapes
- Building blocks of a dessin Basic building blocks of dessin
- style
- Styling of the building blocks