Added Subpaths to bezier-rs (#730)

* Added Subpath constructor, iterator and length

* Asserted that subpaths of len < 2 cannot be closed. Added len() and comments

* Added subpath to_svg(), made structs public, made quadratic use either in_handle or out_handle

* add bezier handles

* Added basic interactivity and index traits

* Added SubPath interactivity

* Added svg styling

* Broke subpath impl across multiple files. More sylistic changes per review

* Fixed format error

* Added closed subpath to documentation page

* Modified subpath to_svg to use functional style

* Stylistic changes per review

* Fixed build errors

* More sylistic changes per review

* Moved svg commands to constants

* Moved formatting for svg arguments to ToSVGOptions

* Renamed files in git

* Even more stylistic changes per review
This commit is contained in:
Rob Nadal
2022-07-27 17:30:08 -04:00
committed by GitHub
parent 8c888e39c7
commit aeb9e85726
17 changed files with 634 additions and 36 deletions
+39 -11
View File
@@ -1,9 +1,11 @@
//! Bezier-rs: A Bezier Math Library for Rust
mod consts;
pub mod subpath;
mod utils;
use consts::*;
pub use subpath::*;
use glam::{DMat2, DVec2};
@@ -164,23 +166,49 @@ impl Bezier {
Bezier::from_cubic_dvec2(start, handle_start, handle_end, end)
}
/// Convert to SVG.
pub fn to_svg(&self) -> String {
// TODO: Allow modifying the viewport, width and height
let m_path = format!("M {} {}", self.start.x, self.start.y);
let handles_path = match self.handles {
BezierHandles::Linear => "L".to_string(),
/// Return the string argument used to create a curve in an SVG `path`, excluding the start point.
pub(crate) fn svg_curve_argument(&self) -> String {
let handle_args = match self.handles {
BezierHandles::Linear => SVG_ARG_LINEAR.to_string(),
BezierHandles::Quadratic { handle } => {
format!("Q {} {},", handle.x, handle.y)
format!("{SVG_ARG_QUADRATIC}{} {}", handle.x, handle.y)
}
BezierHandles::Cubic { handle_start, handle_end } => {
format!("C {} {}, {} {},", handle_start.x, handle_start.y, handle_end.x, handle_end.y)
format!("{SVG_ARG_CUBIC}{} {} {} {}", handle_start.x, handle_start.y, handle_end.x, handle_end.y)
}
};
let curve_path = format!("{} {} {}", handles_path, self.end.x, self.end.y);
format!("{handle_args} {} {}", self.end.x, self.end.y)
}
/// Return the string argument used to create the lines connecting handles to endpoints in an SVG `path`
pub(crate) fn svg_handle_line_argument(&self) -> Option<String> {
match self.handles {
BezierHandles::Linear => None,
BezierHandles::Quadratic { handle } => {
let handle_line = format!("{SVG_ARG_LINEAR}{} {}", handle.x, handle.y);
Some(format!(
"{SVG_ARG_MOVE}{} {} {handle_line} {SVG_ARG_MOVE}{} {} {handle_line}",
self.start.x, self.start.y, self.end.x, self.end.y
))
}
BezierHandles::Cubic { handle_start, handle_end } => {
let handle_start_line = format!("{SVG_ARG_LINEAR}{} {}", handle_start.x, handle_start.y);
let handle_end_line = format!("{SVG_ARG_LINEAR}{} {}", handle_end.x, handle_end.y);
Some(format!(
"{SVG_ARG_MOVE}{} {} {handle_start_line} {SVG_ARG_MOVE}{} {} {handle_end_line}",
self.start.x, self.start.y, self.end.x, self.end.y
))
}
}
}
/// Convert `Bezier` to SVG `path`.
pub fn to_svg(&self) -> String {
format!(
r#"<svg xmlns="http://www.w3.org/2000/svg" viewBox="{} {} {} {}" width="{}px" height="{}px"><path d="{} {} {}" stroke="black" fill="transparent"/></svg>"#,
0, 0, 100, 100, 100, 100, "\n", m_path, curve_path
r#"<path d="{SVG_ARG_MOVE}{} {} {}" stroke="black" fill="none"/>"#,
self.start.x,
self.start.y,
self.svg_curve_argument()
)
}