Crate dessin

Source
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§

pub use ::image;
pub use ::nalgebra;
pub use ::palette;

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