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

Download history 9/week @ 2024-11-20 22/week @ 2024-11-27 190/week @ 2024-12-04 125/week @ 2024-12-11 26/week @ 2024-12-18 92/week @ 2025-01-01 45/week @ 2025-01-08 32/week @ 2025-01-15 32/week @ 2025-01-22 129/week @ 2025-01-29 16/week @ 2025-02-05 51/week @ 2025-02-12 23/week @ 2025-02-19 316/week @ 2025-02-26 18/week @ 2025-03-05

412 downloads per month
Used in 5 crates

MIT license

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