1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
//! `draw` is a simple 2D vector drawing library. //! //! - `Canvas` is a container that defines the size and top-level components of your drawing. //! - `Drawing` defines the position, style, and sub-components of a drawing. //! - `Shape` defines the geometry of an individual shape such as a `Circle` or `Line`. //! - `Style` defines the fill and stroke of a drawing. //! //! The general flow for creating a piece of art is: //! //! 1. Create a `Canvas` //! 2. Create `Drawing` objects and add them to the Canvas `display_list`. //! 3. Position and style the drawings //! 4. Render and save the `Canvas` to whatever output format you want. (SVG, PNG, etc...) //! //! ## Basic Example //! //! ```rust //! use draw::{Canvas, Drawing, Shape, Style, Fill, Stroke, RGB}; //! use draw::render::{self, svg::SvgRenderer}; //! //! // create a canvas to draw on //! let mut canvas = Canvas::new(100, 100); //! //! // create a rectangle //! let mut rect = Drawing::new(Shape::Rectangle { //! width: 50, //! height: 50, //! }); //! //! // move it around //! rect.position.x = 25.0; //! rect.position.y = 25.0; //! //! // give it a cool style //! rect.style = Style { //! fill: Some(Fill { //! color: RGB::new(0, 0, 0), //! }), //! stroke: Some(Stroke { //! width: 2, //! color: RGB::new(255, 0, 0), //! }), //! }; //! //! // add it to the canvas //! canvas.display_list.add(rect); //! //! // save the canvas as an svg //! render::save( //! &canvas, //! "tests/svg/basic_end_to_end.svg", //! SvgRenderer::new(), //! ) //! .expect("Failed to save"); //! ``` //! use cgmath::EuclideanSpace; use cgmath::Point2; use rgb; pub mod canvas; pub mod render; pub mod shape; pub mod style; pub use crate::canvas::Canvas; pub use crate::render::svg::SvgRenderer; pub use crate::shape::{LineBuilder, Shape}; pub use crate::style::Color; pub use crate::style::{Fill, Stroke, Style}; /// Drawings are stored in a vector; this `usize` is a handle to access the child pub type DrawingId = usize; /// An alias for float positioning. Note that SVGs look crisper when objects are positioned /// on integer bounds, so you may just want to stick to whole numbers. A more advanced version /// of this library would just directly use `Point2<T>`, but I decided to prioritze readability. /// We may want to revist that at some point. /// todo: I disagree with myself. Let consumers handle this. pub type Position = Point2<f32>; /// An alias for RGB<u8> pub type RGB = rgb::RGB<u8>; /// A drawing composes a `Shape`, a `DisplayList`, a `Position`, and a `Style`. It's a complete /// sub-tree of an overall piece of art. pub struct Drawing { /// The actual background shape for the drawing pub shape: Shape, // todo: Should this be an Option? /// The drawing's children, layered from bottom to top pub display_list: DisplayList, /// The top left location for the drawing pub position: Position, /// Fill and stroke information for the drawing pub style: Style, } impl Drawing { /// Create a new drawing with default values. pub fn new(shape: Shape) -> Drawing { Drawing { shape, style: Style::default(), display_list: DisplayList::new(), position: Position::origin(), } } } /// A sorted Vec of Drawings, ordered from bottom to top. pub struct DisplayList { drawings: Vec<Drawing>, } impl DisplayList { /// Create a new empty display list fn new() -> DisplayList { DisplayList { drawings: vec![] } } /// Adds a drawing to the top of the display list. /// Returns a DrawingId handle that can be used to refer to the drawing in the future. pub fn add(&mut self, drawing: Drawing) -> DrawingId { let child_id = self.drawings.len(); self.drawings.push(drawing); child_id } /// Remove a drawing from the display list /// todo: Implement pub fn remove(&mut self, _drawing_id: DrawingId) { unimplemented!() } }