diff --git a/svg2polylines-ffi/example.c b/svg2polylines-ffi/example.c index b755706..d664ef6 100644 --- a/svg2polylines-ffi/example.c +++ b/svg2polylines-ffi/example.c @@ -25,7 +25,7 @@ typedef struct Polyline { size_t len; } Polyline; -uint8_t svg_str_to_polylines(char* svg, Polyline** polylines, size_t* polylines_len); +uint8_t svg_str_to_polylines(char* svg, double tol, Polyline** polylines, size_t* polylines_len); void free_polylines(Polyline* polylines, size_t polylines_len); @@ -53,7 +53,7 @@ int main() { size_t polylines_len = 0; // Process data - uint8_t err = svg_str_to_polylines(input, &polylines, &polylines_len); + uint8_t err = svg_str_to_polylines(input, 0.15, &polylines, &polylines_len); // Error handling if (err > 0) { diff --git a/svg2polylines-ffi/example.py b/svg2polylines-ffi/example.py index f12c4ba..7460abd 100644 --- a/svg2polylines-ffi/example.py +++ b/svg2polylines-ffi/example.py @@ -14,7 +14,7 @@ size_t len; } Polyline; -uint8_t svg_str_to_polylines(char* svg, Polyline** polylines, size_t* polylines_len); +uint8_t svg_str_to_polylines(char* svg, double tol, Polyline** polylines, size_t* polylines_len); void free_polylines(Polyline* polylines, size_t polylines_len); ''') @@ -47,7 +47,7 @@ def print_polyline(p): polylines = ffi.new('Polyline**') polylines_len = ffi.new('size_t*') -lib.svg_str_to_polylines(svg_input, polylines, polylines_len) +lib.svg_str_to_polylines(svg_input, 0.15, polylines, polylines_len) print('Found %d polylines!' % polylines_len[0]) diff --git a/svg2polylines-ffi/src/lib.rs b/svg2polylines-ffi/src/lib.rs index c1f2202..890b44b 100644 --- a/svg2polylines-ffi/src/lib.rs +++ b/svg2polylines-ffi/src/lib.rs @@ -3,7 +3,7 @@ use std::ffi::CStr; use std::mem; -use libc::{c_char, size_t}; +use libc::{c_char, c_double, size_t}; use svg2polylines::{parse, CoordinatePair}; /// Structure that contains a pointer to the coordinate pairs as well as the @@ -37,6 +37,7 @@ pub struct Polyline { #[no_mangle] pub unsafe extern "C" fn svg_str_to_polylines( svg: *const c_char, + tol: c_double, polylines: *mut *mut Polyline, polylines_len: *mut size_t, ) -> u8 { @@ -48,7 +49,7 @@ pub unsafe extern "C" fn svg_str_to_polylines( let r_str = c_str.to_str().unwrap(); // Process - match parse(r_str) { + match parse(r_str, tol) { Ok(vec) => { // Convert `Vec>` to `Vec` let mut tmp_vec: Vec = vec diff --git a/svg2polylines/examples/basic.rs b/svg2polylines/examples/basic.rs index 3c2462f..0109efa 100644 --- a/svg2polylines/examples/basic.rs +++ b/svg2polylines/examples/basic.rs @@ -25,7 +25,7 @@ fn main() { file.read_to_string(&mut s).unwrap(); // Parse data - let polylines: Vec = svg2polylines::parse(&s).unwrap_or_else(|e| { + let polylines: Vec = svg2polylines::parse(&s, 0.15).unwrap_or_else(|e| { println!("Error: {}", e); exit(2); }); diff --git a/svg2polylines/examples/preview.rs b/svg2polylines/examples/preview.rs index e2da481..8143490 100644 --- a/svg2polylines/examples/preview.rs +++ b/svg2polylines/examples/preview.rs @@ -30,7 +30,7 @@ fn main() { file.read_to_string(&mut s).unwrap(); // Parse data - let polylines: Vec = svg2polylines::parse(&s).unwrap_or_else(|e| { + let polylines: Vec = svg2polylines::parse(&s, 0.15).unwrap_or_else(|e| { println!("Error: {}", e); exit(2); }); diff --git a/svg2polylines/src/lib.rs b/svg2polylines/src/lib.rs index df41d9a..315a1f8 100644 --- a/svg2polylines/src/lib.rs +++ b/svg2polylines/src/lib.rs @@ -37,8 +37,6 @@ use svgtypes::{PathParser, PathSegment}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -const FLATTENING_TOLERANCE: f64 = 0.15; - /// A `CoordinatePair` consists of an x and y coordinate. #[derive(Debug, PartialEq, Copy, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -200,7 +198,7 @@ fn parse_xml(svg: &str) -> Result, String> { Ok(paths) } -fn parse_path(expr: &str) -> Result, String> { +fn parse_path(expr: &str, tol: f64) -> Result, String> { trace!("parse_path"); let mut lines = Vec::new(); let mut line = CurrentLine::new(); @@ -211,7 +209,7 @@ fn parse_path(expr: &str) -> Result, String> { let current_segment = segment.map_err(|e| format!("Could not parse path segment: {}", e))?; let prev_segment = prev_segment_store.replace(current_segment); - parse_path_segment(¤t_segment, prev_segment, &mut line, &mut lines)?; + parse_path_segment(¤t_segment, prev_segment, &mut line, tol, &mut lines)?; } // Path parsing is done, add previously parsing line if valid @@ -226,6 +224,7 @@ fn parse_path(expr: &str) -> Result, String> { #[allow(clippy::too_many_arguments)] fn _handle_cubic_curve( current_line: &mut CurrentLine, + tol: f64, abs: bool, x1: f64, y1: f64, @@ -252,7 +251,7 @@ fn _handle_cubic_curve( to: Point2D::new(current.x + x, current.y + y), } }; - for point in curve.flattened(FLATTENING_TOLERANCE) { + for point in curve.flattened(tol) { current_line.add_absolute(CoordinatePair::new(point.x, point.y)); } Ok(()) @@ -263,6 +262,7 @@ fn parse_path_segment( segment: &PathSegment, prev_segment: Option, current_line: &mut CurrentLine, + tol: f64, lines: &mut Vec, ) -> Result<(), String> { trace!("parse_path_segment"); @@ -308,7 +308,7 @@ fn parse_path_segment( y, } => { trace!("parse_path_segment: CurveTo"); - _handle_cubic_curve(current_line, abs, x1, y1, x2, y2, x, y)?; + _handle_cubic_curve(current_line, tol, abs, x1, y1, x2, y2, x, y)?; } &PathSegment::SmoothCurveTo { abs, x2, y2, x, y } => { trace!("parse_path_segment: SmoothCurveTo"); @@ -344,7 +344,7 @@ fn parse_path_segment( } else { (dx, dy) }; - _handle_cubic_curve(current_line, abs, x1, y1, x2, y2, x, y)?; + _handle_cubic_curve(current_line, tol, abs, x1, y1, x2, y2, x, y)?; } Some(_) | None => { // The previous segment was not a curve. Use the current @@ -353,7 +353,7 @@ fn parse_path_segment( Some(pair) => { let x1 = pair.x; let y1 = pair.y; - _handle_cubic_curve(current_line, abs, x1, y1, x2, y2, x, y)?; + _handle_cubic_curve(current_line, tol, abs, x1, y1, x2, y2, x, y)?; } None => { return Err( @@ -382,7 +382,7 @@ fn parse_path_segment( to: Point2D::new(current.x + x, current.y + y), } }; - for point in curve.flattened(FLATTENING_TOLERANCE) { + for point in curve.flattened(tol) { current_line.add_absolute(CoordinatePair::new(point.x, point.y)); } } @@ -400,7 +400,7 @@ fn parse_path_segment( } /// Parse an SVG string into a vector of polylines. -pub fn parse(svg: &str) -> Result, String> { +pub fn parse(svg: &str, tol: f64) -> Result, String> { trace!("parse"); // Parse the XML string into a list of path expressions @@ -412,7 +412,7 @@ pub fn parse(svg: &str) -> Result, String> { // Process path expressions for expr in path_exprs { - polylines.extend(parse_path(&expr)?); + polylines.extend(parse_path(&expr, tol)?); } trace!("parse: This results in {} polylines", polylines.len()); @@ -424,6 +424,8 @@ pub fn parse(svg: &str) -> Result, String> { mod tests { use super::*; + const FLATTENING_TOLERANCE: f64 = 0.15; + #[test] fn test_current_line() { let mut line = CurrentLine::new(); @@ -478,6 +480,7 @@ mod tests { }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -489,6 +492,7 @@ mod tests { }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -500,6 +504,7 @@ mod tests { }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -525,6 +530,7 @@ mod tests { }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -532,6 +538,7 @@ mod tests { &PathSegment::HorizontalLineTo { abs: true, x: 3.0 }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -539,6 +546,7 @@ mod tests { &PathSegment::VerticalLineTo { abs: true, y: -1.0 }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -563,6 +571,7 @@ mod tests { }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -574,6 +583,7 @@ mod tests { }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ); assert!(result.is_err()); @@ -596,6 +606,7 @@ mod tests { }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -607,6 +618,7 @@ mod tests { }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -618,6 +630,7 @@ mod tests { }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -629,6 +642,7 @@ mod tests { }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -640,6 +654,7 @@ mod tests { }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -651,6 +666,7 @@ mod tests { }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -662,6 +678,7 @@ mod tests { }, None, &mut current_line, + FLATTENING_TOLERANCE, &mut lines, ) .unwrap(); @@ -680,7 +697,7 @@ mod tests { "#; - let result = parse(&input).unwrap(); + let result = parse(&input, FLATTENING_TOLERANCE).unwrap(); assert_eq!(result.len(), 1); assert_eq!(result[0].len(), 4); assert_eq!(result[0][0], (113., 35.).into()); @@ -698,7 +715,7 @@ mod tests { "#; - let result = parse(&input).unwrap(); + let result = parse(&input, FLATTENING_TOLERANCE).unwrap(); assert_eq!(result.len(), 1); assert_eq!(result[0].len(), 4); assert_eq!(result[0][0], (10., 10.).into()); @@ -724,7 +741,7 @@ mod tests { "#; - let result = parse(&input).unwrap(); + let result = parse(&input, FLATTENING_TOLERANCE).unwrap(); assert_eq!(result.len(), 2); assert_eq!(result[0].len(), 4); @@ -747,7 +764,7 @@ mod tests { "#; - let result = parse(&input).unwrap(); + let result = parse(&input, FLATTENING_TOLERANCE).unwrap(); // 2 Polylines assert_eq!(result.len(), 2); @@ -776,7 +793,7 @@ mod tests { "#; - let result = parse(&input).unwrap(); + let result = parse(&input, FLATTENING_TOLERANCE).unwrap(); assert_eq!(result.len(), 4); assert_eq!(result[0], result[1]); assert_eq!(result[0], result[2]); @@ -860,7 +877,7 @@ mod tests { "#; - let result = parse(&input).unwrap(); + let result = parse(&input, FLATTENING_TOLERANCE).unwrap(); assert_eq!(result.len(), 1); assert_eq!(result[0].len(), 11); assert_eq!( @@ -927,7 +944,7 @@ mod tests { "#; - let result = parse(&input).unwrap(); + let result = parse(&input, FLATTENING_TOLERANCE).unwrap(); assert_eq!(result.len(), 1); assert_eq!(result[0].len(), 31); assert_eq!(