From 0f35cd092e8b9e667d8f17f7dab47e923f7b3d82 Mon Sep 17 00:00:00 2001 From: Jovansonlee Cesar Date: Thu, 13 Feb 2020 20:11:14 +0800 Subject: Pass Settings to the property, so behavior can be dependent on flags that is set in the settings --- svgbob/src/buffer/cell_buffer.rs | 2 +- svgbob/src/buffer/cell_buffer/span.rs | 115 ++++++++++++++------- svgbob/src/buffer/fragment_buffer/fragment/text.rs | 73 +++++++++---- svgbob/src/buffer/property_buffer.rs | 66 +++++++----- svgbob/src/buffer/property_buffer/property.rs | 58 ++++++++--- svgbob/src/map/ascii_map.rs | 58 +++++------ svgbob/src/map/circle_map.rs | 39 ++++--- 7 files changed, 266 insertions(+), 145 deletions(-) diff --git a/svgbob/src/buffer/cell_buffer.rs b/svgbob/src/buffer/cell_buffer.rs index f60a79b..aa20104 100644 --- a/svgbob/src/buffer/cell_buffer.rs +++ b/svgbob/src/buffer/cell_buffer.rs @@ -155,7 +155,7 @@ impl CellBuffer { let (vec_fragments, vec_contacts): (Vec>, Vec>) = self .group_adjacents() .into_iter() - .map(|span| span.endorse()) + .map(|span| span.endorse(settings)) .unzip(); // partition the vec_groups into groups that is alone and the group diff --git a/svgbob/src/buffer/cell_buffer/span.rs b/svgbob/src/buffer/cell_buffer/span.rs index e9dd29e..c4adfe5 100644 --- a/svgbob/src/buffer/cell_buffer/span.rs +++ b/svgbob/src/buffer/cell_buffer/span.rs @@ -7,7 +7,7 @@ use crate::{ fragment, fragment::{Circle, Marker}, map::{circle_map, UNICODE_FRAGMENTS}, - Cell, Fragment, + Cell, Fragment, Settings, }; use itertools::Itertools; use std::{ @@ -40,16 +40,20 @@ impl Span { } pub(super) fn is_adjacent(&self, cell: &Cell) -> bool { - self.iter().rev().any(|(ex_cell, _)| ex_cell.is_adjacent(cell)) + self.iter() + .rev() + .any(|(ex_cell, _)| ex_cell.is_adjacent(cell)) } /// if any cell of this span is adjacent to any cell of the other /// Use .rev() to check the last cell of this Span agains the first cell of the other Span /// They have a high change of matching faster pub(super) fn can_merge(&self, other: &Self) -> bool { - self.iter() - .rev() - .any(|(cell, _)| other.iter().any(|(other_cell, _)| cell.is_adjacent(other_cell))) + self.iter().rev().any(|(cell, _)| { + other + .iter() + .any(|(other_cell, _)| cell.is_adjacent(other_cell)) + }) } pub(super) fn merge(&mut self, other: &Self) { @@ -93,9 +97,9 @@ impl Span { /// Only elements on the same span are checked to see if they /// belong on the same group /// - pub(crate) fn get_contacts(self) -> Vec { + pub(crate) fn get_contacts(self, settings: &Settings) -> Vec { let localize_self = self.localize(); - let fb: FragmentBuffer = (&localize_self).into(); + let fb: FragmentBuffer = (&localize_self).into_fragment_buffer(settings); let mut groups: Vec = vec![]; let merged_fragments = fb.merge_fragments(); @@ -120,7 +124,11 @@ impl Span { let grouped = Self::second_pass_groupable(groups); // continue calling group recursive until the original len // has not decreased - if grouped.len() < original_len { Self::group_recursive(grouped) } else { grouped } + if grouped.len() < original_len { + Self::group_recursive(grouped) + } else { + grouped + } } fn second_pass_groupable(groups: Vec) -> Vec { @@ -192,9 +200,9 @@ impl Span { /// The second element of the tuple: `contacts` are fragments that are touching together /// but can not form a fragment shape. These will be grouped in the svg nodes /// to keep them go together, when dragged (editing) - pub(crate) fn endorse(self) -> (Vec, Vec) { + pub(crate) fn endorse(self, settings: &Settings) -> (Vec, Vec) { let (top_left, _) = self.bounds().expect("mut have bounds"); - let groups: Vec = self.get_contacts(); + let groups: Vec = self.get_contacts(settings); // 1st phase, successful_endorses fragments, unendorsed one) let (mut fragments, mut un_endorsed) = Self::endorse_rects(groups); // 2nd phase, try to endorse to circles and arcs from the rejects of the 1st phase @@ -202,8 +210,14 @@ impl Span { fragments.extend(circle_fragments); ( - fragments.iter().map(|frag| frag.absolute_position(top_left)).collect(), - un_endorsed.iter().map(|group| group.absolute_position(top_left)).collect(), + fragments + .iter() + .map(|frag| frag.absolute_position(top_left)) + .collect(), + un_endorsed + .iter() + .map(|group| group.absolute_position(top_left)) + .collect(), ) } @@ -224,7 +238,7 @@ impl<'p> Into> for &Span { let mut pb = PropertyBuffer::new(); for (cell, ch) in self.iter() { if let Some(property) = Property::from_char(*ch) { - pb.insert(*cell, property); + pb.as_mut().insert(*cell, property); } else { } } @@ -237,12 +251,12 @@ impl<'p> Into> for &Span { /// /// If a character has no property, try to see if has equivalent fragments from unicode_map /// otherwise add it to the fragment_buffer as a text fragment -impl Into for &Span { - fn into(self) -> FragmentBuffer { +impl Span { + fn into_fragment_buffer(&self, settings: &Settings) -> FragmentBuffer { let pb: PropertyBuffer = self.into(); - let mut fb: FragmentBuffer = (&pb).into(); + let mut fb: FragmentBuffer = pb.into_fragment_buffer(settings); for (cell, ch) in self.iter() { - if pb.get(cell).is_none() { + if pb.as_ref().get(cell).is_none() { if let Some(fragments) = UNICODE_FRAGMENTS.get(ch) { fb.add_fragments_to_cell(*cell, fragments.clone()); } else { @@ -254,7 +268,6 @@ impl Into for &Span { } } - impl fmt::Display for Span { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut buffer = StringBuffer::new(); @@ -281,8 +294,6 @@ mod tests { Point, }; - - #[test] fn test_bounds() { let art = r#" @@ -334,14 +345,18 @@ mod tests { let span = adjacents.remove(0); let (top_left, _) = span.bounds().unwrap(); assert_eq!(top_left, Cell::new(0, 1)); - let groups: Vec = span.get_contacts(); + let groups: Vec = span.get_contacts(&Settings::default()); for (i, group) in groups.iter().enumerate() { println!("group {} is: \n{}", i, group); } assert_eq!(groups.len(), 1); let rect = groups[0].endorse_rects().unwrap(); - let expected = - Fragment::Rect(Rect::new(Point::new(0.5, 1.0), Point::new(9.5, 5.0), false, false)); + let expected = Fragment::Rect(Rect::new( + Point::new(0.5, 1.0), + Point::new(9.5, 5.0), + false, + false, + )); assert_eq!(rect, expected); } @@ -369,8 +384,9 @@ mod tests { let (bound2, _) = span2.bounds().unwrap(); assert_eq!(bound1, Cell::new(0, 1)); assert_eq!(bound2, Cell::new(0, 5)); - let groups1: Vec = span1.get_contacts(); - let groups2: Vec = span2.get_contacts(); + let settings = &Settings::default(); + let groups1: Vec = span1.get_contacts(settings); + let groups2: Vec = span2.get_contacts(settings); assert_eq!(groups1.len(), 1); assert_eq!(groups2.len(), 1); @@ -378,11 +394,21 @@ mod tests { let rect2 = groups2[0].endorse_rects().unwrap(); assert_eq!( rect1, - Fragment::Rect(Rect::new(Point::new(0.5, 1.0), Point::new(9.5, 5.0), false, false)) + Fragment::Rect(Rect::new( + Point::new(0.5, 1.0), + Point::new(9.5, 5.0), + false, + false + )) ); assert_eq!( rect2, - Fragment::Rect(Rect::new(Point::new(0.5, 1.0), Point::new(9.5, 5.0), false, false)) + Fragment::Rect(Rect::new( + Point::new(0.5, 1.0), + Point::new(9.5, 5.0), + false, + false + )) ); } @@ -405,7 +431,7 @@ mod tests { let span1 = spans.remove(0); let (bound1, _) = span1.bounds().unwrap(); assert_eq!(bound1, Cell::new(0, 1)); - let groups: Vec = span1.get_contacts(); + let groups: Vec = span1.get_contacts(&Settings::default()); assert_eq!(groups.len(), 2); let rect1 = groups[0].endorse_rects().unwrap(); @@ -447,13 +473,16 @@ mod tests { let span = adjacents.remove(0); let (top_left, _) = span.bounds().unwrap(); assert_eq!(top_left, Cell::new(8, 1)); - let (mut fragments, _groups) = span.endorse(); + let (mut fragments, _groups) = span.endorse(&Settings::default()); for (i, frag) in fragments.iter().enumerate() { println!("frag {}:\n{}", i, frag); } assert_eq!(fragments.len(), 1); let circle = fragments.remove(0); - assert_eq!(circle, Fragment::Circle(Circle::new(Point::new(11.0, 5.0), 2.5, false))); + assert_eq!( + circle, + Fragment::Circle(Circle::new(Point::new(11.0, 5.0), 2.5, false)) + ); } #[test] @@ -475,19 +504,27 @@ mod tests { let span1 = adjacents.remove(0); let (top_left1, _) = span1.bounds().unwrap(); assert_eq!(top_left1, Cell::new(8, 1)); - let (mut fragments, _groups) = span1.endorse(); + let (mut fragments, _groups) = span1.endorse(&Settings::default()); assert_eq!(fragments.len(), 2); let rect = fragments.remove(0); assert!(rect.is_rect()); assert_eq!( rect, - Fragment::Rect(Rect::new(Point::new(9.5, 9.0), Point::new(19.5, 13.0), false, false)) + Fragment::Rect(Rect::new( + Point::new(9.5, 9.0), + Point::new(19.5, 13.0), + false, + false + )) ); let circle = fragments.remove(0); assert!(circle.is_circle()); - assert_eq!(circle, Fragment::Circle(Circle::new(Point::new(11.0, 5.0), 2.5, false))); + assert_eq!( + circle, + Fragment::Circle(Circle::new(Point::new(11.0, 5.0), 2.5, false)) + ); } #[test] @@ -515,13 +552,15 @@ mod tests { let span1 = adjacents.remove(0); let (top_left1, _) = span1.bounds().unwrap(); assert_eq!(top_left1, Cell::new(12, 3)); - let (mut fragments, _groups) = span1.endorse(); + let (mut fragments, _groups) = span1.endorse(&Settings::default()); assert_eq!(fragments.len(), 1); - let circle = fragments.remove(0); assert!(circle.is_circle()); - assert_eq!(circle, Fragment::Circle(Circle::new(Point::new(22.0, 17.0), 9.5, false))); + assert_eq!( + circle, + Fragment::Circle(Circle::new(Point::new(22.0, 17.0), 9.5, false)) + ); } #[test] @@ -549,7 +588,7 @@ mod tests { let span1 = adjacents.remove(0); let (top_left1, _) = span1.bounds().unwrap(); assert_eq!(top_left1, Cell::new(12, 3)); - let (fragments, groups) = span1.endorse(); + let (fragments, groups) = span1.endorse(&Settings::default()); assert_eq!(fragments.len(), 1); assert_eq!(groups.len(), 1); for (i, fragment) in groups.iter().enumerate() { @@ -580,7 +619,7 @@ mod tests { let (top_left1, _br) = span1.bounds().unwrap(); assert_eq!(top_left1, Cell::new(8, 5)); - let groups1 = span1.get_contacts(); + let groups1 = span1.get_contacts(&Settings::default()); let since = groups1[11].as_ref()[0].as_cell_text().unwrap(); assert_eq!(since.content, "since"); assert_eq!(since.start, Cell::new(20, 1)); diff --git a/svgbob/src/buffer/fragment_buffer/fragment/text.rs b/svgbob/src/buffer/fragment_buffer/fragment/text.rs index e8a9b20..b5ce261 100644 --- a/svgbob/src/buffer/fragment_buffer/fragment/text.rs +++ b/svgbob/src/buffer/fragment_buffer/fragment/text.rs @@ -35,12 +35,16 @@ impl CellText { } fn is_adjacent_cell(&self, other_cell: Cell) -> bool { - self.cells().into_iter().any(|cell| cell.y == other_cell.y && cell.is_adjacent(&other_cell)) + self.cells() + .into_iter() + .any(|cell| cell.y == other_cell.y && cell.is_adjacent(&other_cell)) } /// cell text is groupable when they are adjacent pub(crate) fn is_contacting(&self, other: &Self) -> bool { - self.cells().into_iter().any(|cell| other.is_adjacent_cell(cell)) + self.cells() + .into_iter() + .any(|cell| other.is_adjacent_cell(cell)) } /// text can merge if they are next to each other and at the same line @@ -53,9 +57,15 @@ impl CellText { pub(in crate) fn merge(&self, other: &Self) -> Option { if self.can_merge(other) { if self.start.x < other.start.x { - Some(CellText::new(self.start, format!("{}{}", self.content, other.content))) + Some(CellText::new( + self.start, + format!("{}{}", self.content, other.content), + )) } else { - Some(CellText::new(other.start, format!("{}{}", other.content, self.content))) + Some(CellText::new( + other.start, + format!("{}{}", other.content, self.content), + )) } } else { None @@ -63,13 +73,19 @@ impl CellText { } pub(in crate) fn absolute_position(&self, cell: Cell) -> Self { - CellText { start: Cell::new(self.start.x + cell.x, self.start.y + cell.y), ..self.clone() } + CellText { + start: Cell::new(self.start.x + cell.x, self.start.y + cell.y), + ..self.clone() + } } } impl Bounds for CellText { fn bounds(&self) -> (Point, Point) { - (self.start.top_left_most(), self.end_cell().bottom_right_most()) + ( + self.start.top_left_most(), + self.end_cell().bottom_right_most(), + ) } } @@ -110,11 +126,17 @@ impl Text { } pub(in crate) fn absolute_position(&self, cell: Cell) -> Self { - Text { start: cell.absolute_position(self.start), ..self.clone() } + Text { + start: cell.absolute_position(self.start), + ..self.clone() + } } pub(in crate) fn scale(&self, scale: f32) -> Self { - Text { start: self.start.scale(scale), ..self.clone() } + Text { + start: self.start.scale(scale), + ..self.clone() + } } } @@ -134,7 +156,6 @@ fn escape_html_text(s: &str) -> String { s.chars().map(|ch| replace_html_char(ch)).collect() } - impl fmt::Display for Text { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "T {} {}", self.start, self.text) @@ -143,15 +164,19 @@ impl fmt::Display for Text { impl Into> for Text { fn into(self) -> Node<()> { - svg::tags::text(vec![x(self.start.x), y(self.start.y)], vec![text(escape_html_text( - &self.text, - ))]) + svg::tags::text( + vec![x(self.start.x), y(self.start.y)], + vec![text(escape_html_text(&self.text))], + ) } } impl Bounds for Text { fn bounds(&self) -> (Point, Point) { - (self.start, Point::new(self.start.x + self.text_width(), self.start.y)) + ( + self.start, + Point::new(self.start.x + self.text_width(), self.start.y), + ) } } @@ -160,7 +185,9 @@ impl Eq for Text {} /// This is needed since this struct contains f32 which rust doesn't provide Eq implementation impl Ord for Text { fn cmp(&self, other: &Self) -> Ordering { - self.start.cmp(&other.start).then(self.text.cmp(&other.text)) + self.start + .cmp(&other.start) + .then(self.text.cmp(&other.text)) } } @@ -181,6 +208,7 @@ mod tests { use crate::{ buffer::{Cell, CellBuffer, Contacts, Span}, fragment::CellText, + Settings, }; #[test] @@ -216,7 +244,7 @@ mod tests { let mut spans: Vec = cell_buffer.group_adjacents(); assert_eq!(spans.len(), 1); let span1 = spans.remove(0); - let groups = span1.get_contacts(); + let groups = span1.get_contacts(&Settings::default()); for (i, group) in groups.iter().enumerate() { println!("group{}\n{}", i, group); } @@ -257,8 +285,9 @@ mod tests { let cell_buffer = CellBuffer::from(art); let mut spans: Vec = cell_buffer.group_adjacents(); assert_eq!(spans.len(), 2); - let groups2 = spans.remove(1).get_contacts(); - let groups1 = spans.remove(0).get_contacts(); + let settings = &Settings::default(); + let groups2 = spans.remove(1).get_contacts(settings); + let groups1 = spans.remove(0).get_contacts(settings); println!("span1 groups:"); for (i, group1) in groups1.iter().enumerate() { println!("\tgroup {} {}", i, group1); @@ -269,7 +298,13 @@ mod tests { } assert_eq!(groups1.len(), 15); assert_eq!(groups2.len(), 33); - assert_eq!(groups1[0].as_ref()[0].as_cell_text().unwrap().start, Cell::new(0, 0)); - assert_eq!(groups2[0].as_ref()[0].as_cell_text().unwrap().start, Cell::new(0, 0)); + assert_eq!( + groups1[0].as_ref()[0].as_cell_text().unwrap().start, + Cell::new(0, 0) + ); + assert_eq!( + groups2[0].as_ref()[0].as_cell_text().unwrap().start, + Cell::new(0, 0) + ); } } diff --git a/svgbob/src/buffer/property_buffer.rs b/svgbob/src/buffer/property_buffer.rs index b515e15..4642273 100644 --- a/svgbob/src/buffer/property_buffer.rs +++ b/svgbob/src/buffer/property_buffer.rs @@ -1,7 +1,7 @@ use crate::{ fragment, map::{ASCII_PROPERTIES, UNICODE_FRAGMENTS}, - Cell, Fragment, FragmentBuffer, + Cell, Fragment, FragmentBuffer, Settings, }; pub use property::{Property, Signal}; use std::{ @@ -31,27 +31,33 @@ impl<'p> PropertyBuffer<'p> { /// into the most fitting ascii / unicode character pub fn match_char_from_cell( &self, + settings: &Settings, cell: Cell, fragments: &Vec, try_unicode: bool, ) -> Option { // try the unicode first - let matched_unicode = if try_unicode { Fragment::match_unicode(fragments) } else { None }; + let matched_unicode = if try_unicode { + Fragment::match_unicode(fragments) + } else { + None + }; if let Some(matched_unicode) = matched_unicode { Some(matched_unicode) } else { let empty = &&Property::empty(); - let top_left = self.get(&cell.top_left()).unwrap_or(empty); - let top = self.get(&cell.top()).unwrap_or(empty); - let top_right = self.get(&cell.top_right()).unwrap_or(empty); - let left = self.get(&cell.left()).unwrap_or(empty); - let right = self.get(&cell.right()).unwrap_or(empty); - let bottom_left = self.get(&cell.bottom_left()).unwrap_or(empty); - let bottom = self.get(&cell.bottom()).unwrap_or(empty); - let bottom_right = self.get(&cell.bottom_right()).unwrap_or(empty); + let top_left = self.as_ref().get(&cell.top_left()).unwrap_or(empty); + let top = self.as_ref().get(&cell.top()).unwrap_or(empty); + let top_right = self.as_ref().get(&cell.top_right()).unwrap_or(empty); + let left = self.as_ref().get(&cell.left()).unwrap_or(empty); + let right = self.as_ref().get(&cell.right()).unwrap_or(empty); + let bottom_left = self.as_ref().get(&cell.bottom_left()).unwrap_or(empty); + let bottom = self.as_ref().get(&cell.bottom()).unwrap_or(empty); + let bottom_right = self.as_ref().get(&cell.bottom_right()).unwrap_or(empty); Self::match_char_with_surrounding_properties( + settings, &fragments, top_left, top, @@ -68,6 +74,7 @@ impl<'p> PropertyBuffer<'p> { /// if the fragments match to the return fragments /// of the property behavior, then it is a match pub fn match_char_with_surrounding_properties( + settings: &Settings, fragments: &Vec, top_left: &Property, top: &Property, @@ -91,6 +98,7 @@ impl<'p> PropertyBuffer<'p> { } else { ASCII_PROPERTIES.iter().find_map(|(ch, property)| { let mut behavioral_fragments = property.fragments( + settings, top_left, top, top_right, @@ -117,34 +125,33 @@ impl<'p> PropertyBuffer<'p> { } } -impl<'p> Deref for PropertyBuffer<'p> { - type Target = HashMap; - - fn deref(&self) -> &Self::Target { +impl<'p> AsRef> for PropertyBuffer<'p> { + fn as_ref(&self) -> &HashMap { &self.0 } } -impl<'p> DerefMut for PropertyBuffer<'p> { - fn deref_mut(&mut self) -> &mut Self::Target { +impl<'p> AsMut> for PropertyBuffer<'p> { + fn as_mut(&mut self) -> &mut HashMap { &mut self.0 } } /// convert property buffer to fragment buffer -impl<'p> Into for &PropertyBuffer<'p> { - fn into(self) -> FragmentBuffer { +impl<'p> PropertyBuffer<'p> { + pub(crate) fn into_fragment_buffer(&self, settings: &Settings) -> FragmentBuffer { let mut fb = FragmentBuffer::new(); - for (cell, property) in self.deref() { + for (cell, property) in self.as_ref() { let empty = &&Property::empty(); - let top_left = self.get(&cell.top_left()).unwrap_or(empty); - let top = self.get(&cell.top()).unwrap_or(empty); - let top_right = self.get(&cell.top_right()).unwrap_or(empty); - let left = self.get(&cell.left()).unwrap_or(empty); - let right = self.get(&cell.right()).unwrap_or(empty); - let bottom_left = self.get(&cell.bottom_left()).unwrap_or(empty); - let bottom = self.get(&cell.bottom()).unwrap_or(empty); - let bottom_right = self.get(&cell.bottom_right()).unwrap_or(empty); + let top_left = self.as_ref().get(&cell.top_left()).unwrap_or(empty); + let top = self.as_ref().get(&cell.top()).unwrap_or(empty); + let top_right = self.as_ref().get(&cell.top_right()).unwrap_or(empty); + let left = self.as_ref().get(&cell.left()).unwrap_or(empty); + let right = self.as_ref().get(&cell.right()).unwrap_or(empty); + let bottom_left = self.as_ref().get(&cell.bottom_left()).unwrap_or(empty); + let bottom = self.as_ref().get(&cell.bottom()).unwrap_or(empty); + let bottom_right = self.as_ref().get(&cell.bottom_right()).unwrap_or(empty); let cell_fragments = property.fragments( + settings, top_left, top, top_right, @@ -194,6 +201,7 @@ mod tests { let bottom = &Property::empty(); let bottom_right = &Property::empty(); let ch = PropertyBuffer::match_char_with_surrounding_properties( + &Settings::default(), &fragments, top_left, top, @@ -230,6 +238,7 @@ mod tests { let bottom = &Property::empty(); let bottom_right = &Property::empty(); let ch = PropertyBuffer::match_char_with_surrounding_properties( + &Settings::default(), &fragments, top_left, top, @@ -267,6 +276,7 @@ mod tests { let bottom = &Property::from_char('|').unwrap(); let bottom_right = &Property::empty(); let ch = PropertyBuffer::match_char_with_surrounding_properties( + &Settings::default(), &fragments, top_left, top, @@ -299,6 +309,7 @@ mod tests { let bottom = &Property::empty(); let bottom_right = &Property::empty(); let ch = PropertyBuffer::match_char_with_surrounding_properties( + &Settings::default(), &fragments, top_left, top, @@ -331,6 +342,7 @@ mod tests { let bottom = &Property::empty(); let bottom_right = &Property::empty(); let ch = PropertyBuffer::match_char_with_surrounding_properties( + &Settings::default(), &fragments, top_left, top, diff --git a/svgbob/src/buffer/property_buffer/property.rs b/svgbob/src/buffer/property_buffer/property.rs index 19c1939..0e5066d 100644 --- a/svgbob/src/buffer/property_buffer/property.rs +++ b/svgbob/src/buffer/property_buffer/property.rs @@ -1,7 +1,7 @@ use self::Signal::Strong; use crate::{ map::{ASCII_PROPERTIES, UNICODE_PROPERTIES}, - Fragment, Point, + Fragment, Point, Settings, }; use std::{cmp, fmt, sync::Arc}; @@ -58,6 +58,7 @@ pub struct Property { /// depending on flag that is meet when checked agains the surrounding characters pub behavior: Arc< dyn Fn( + &Settings, &Property, &Property, &Property, @@ -74,7 +75,12 @@ pub struct Property { impl fmt::Debug for Property { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - writeln!(f, "{{ char: {}, has {} signature }}", self.ch, self.signature.len()) + writeln!( + f, + "{{ char: {}, has {} signature }}", + self.ch, + self.signature.len() + ) } } @@ -84,6 +90,7 @@ impl Property { signature: Vec<(Signal, Vec)>, behavior: Arc< dyn Fn( + &Settings, &Property, &Property, &Property, @@ -97,7 +104,11 @@ impl Property { + Send, >, ) -> Self { - Property { ch, signature, behavior } + Property { + ch, + signature, + behavior, + } } /// get the matching property of this char @@ -113,7 +124,11 @@ impl Property { /// empty property serves as a substitue for None property for simplicity in /// the behavior code, never have to deal with Option pub fn empty() -> Self { - Property { ch: ' ', signature: vec![], behavior: Arc::new(|_, _, _, _, _, _, _, _| vec![]) } + Property { + ch: ' ', + signature: vec![], + behavior: Arc::new(|_, _, _, _, _, _, _, _, _| vec![]), + } } /// derive a strong property with a strong signal @@ -122,7 +137,7 @@ impl Property { ch, signature: vec![(Signal::Strong, fragments)], //TODO find a way to move the fragments here - behavior: Arc::new(|_, _, _, _, _, _, _, _| vec![(true, vec![])]), + behavior: Arc::new(|_, _, _, _, _, _, _, _, _| vec![(true, vec![])]), } } @@ -130,7 +145,13 @@ impl Property { let mut fragments: Vec = self .signature .iter() - .filter_map(|(sig, fragments)| if *sig == signal { Some(fragments) } else { None }) + .filter_map(|(sig, fragments)| { + if *sig == signal { + Some(fragments) + } else { + None + } + }) .flatten() .map(Clone::clone) .collect(); @@ -183,9 +204,12 @@ impl Property { /// Check to see if any fragment that is generated in this character /// can overlap (completely covered) line a b fn line_overlap_with_signal(&self, a: Point, b: Point, required_signal: Signal) -> bool { - self.signature.iter().filter(|(signal, _signature)| *signal >= required_signal).any( - |(_signal, signature)| signature.iter().any(|fragment| fragment.line_overlap(a, b)), - ) + self.signature + .iter() + .filter(|(signal, _signature)| *signal >= required_signal) + .any(|(_signal, signature)| { + signature.iter().any(|fragment| fragment.line_overlap(a, b)) + }) } /// Check to see if any fragment that is generated in this character @@ -199,6 +223,7 @@ impl Property { /// the fragments of this property when the surrounding properties is supplied pub(in crate) fn fragments( &self, + settings: &Settings, top_left: &Property, top: &Property, top_right: &Property, @@ -209,6 +234,7 @@ impl Property { bottom_right: &Property, ) -> Vec { let bool_fragments = self.behavior.as_ref()( + settings, top_left, top, top_right, @@ -219,12 +245,14 @@ impl Property { bottom_right, ); let cell_fragments: Vec = - bool_fragments.into_iter().fold(vec![], |mut acc, (passed, fragments)| { - if passed { - acc.extend(fragments); - }; - acc - }); + bool_fragments + .into_iter() + .fold(vec![], |mut acc, (passed, fragments)| { + if passed { + acc.extend(fragments); + }; + acc + }); cell_fragments } } diff --git a/svgbob/src/map/ascii_map.rs b/svgbob/src/map/ascii_map.rs index 6576ce4..fad9d56 100644 --- a/svgbob/src/map/ascii_map.rs +++ b/svgbob/src/map/ascii_map.rs @@ -4,7 +4,7 @@ use crate::{ ArrowBottom, ArrowBottomLeft, ArrowBottomRight, ArrowLeft, ArrowRight, ArrowTop, ArrowTopLeft, ArrowTopRight, DiamondBullet, }, - Cell, CellGrid, + Cell, CellGrid, Settings, }, fragment::{arc, broken_line, circle, line, polygon, rect}, Fragment, Property, @@ -98,7 +98,7 @@ lazy_static! { let map: Vec<( char, Vec<(Signal, Vec)>, - Arc Vec<(bool, Vec)> + Sync + Send >, + Arc Vec<(bool, Vec)> + Sync + Send >, )> = vec![ /////////////// // dash - @@ -109,7 +109,7 @@ lazy_static! { (Strong, vec![line(k, o)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ (true, vec![line(k, o)]), ] @@ -125,7 +125,7 @@ lazy_static! { (Strong, vec![broken_line(k, o)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ (true, vec![broken_line(k, o)]), ] @@ -141,7 +141,7 @@ lazy_static! { (Strong, vec![line(c,w)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ (!bottom_left.is('/') && !bottom_right.is('\\') && !top_left.is('\\') && !top_right.is('/'), vec![line(c,w)]), // _ @@ -180,7 +180,7 @@ lazy_static! { (Strong, vec![broken_line(c,w)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ (top.line_strongly_overlap(r,w) || bottom.line_strongly_overlap(c,h), vec![broken_line(c,w)]), ] @@ -196,7 +196,7 @@ lazy_static! { (Strong, vec![broken_line(c,w)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ (top.line_strongly_overlap(r,w) || bottom.line_strongly_overlap(c,h), vec![broken_line(c,w)]), ] @@ -213,7 +213,7 @@ lazy_static! { (Weak, vec![line(a,y), line(u,e)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // | // + @@ -256,7 +256,7 @@ lazy_static! { (Strong, vec![line(a,y), line(u,e)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // \ X // X \ @@ -279,7 +279,7 @@ lazy_static! { (Weak, vec![line(a,y), line(u,e)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ (true, vec![circle(m,unit2, true)]), ] @@ -298,7 +298,7 @@ lazy_static! { (Weak, vec![line(a,y), line(u,e)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ (top.line_overlap(r,w) || bottom.line_overlap(c,h) || left.line_overlap(n,o) || right.line_overlap(k,l), @@ -323,7 +323,7 @@ lazy_static! { (Weak, vec![line(a,y), line(u,e)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // must have at least one connection // \|/ @@ -350,7 +350,7 @@ lazy_static! { (Weak, vec![line(a,y), line(u,e)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // must have at least one connection // \|/ @@ -373,7 +373,7 @@ lazy_static! { (Strong, vec![line(u, y)]) ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ (true, vec![line(u,y)]), // /_ @@ -395,7 +395,7 @@ lazy_static! { (Weak, vec![line(m,o)]), // connects right ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // . // | @@ -482,7 +482,7 @@ lazy_static! { (Weak, vec![line(m,o)]), // connects right ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // ,- // | @@ -507,7 +507,7 @@ lazy_static! { (Weak, vec![line(m,o)]), // connects right ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // | // ' @@ -576,7 +576,7 @@ lazy_static! { (Weak, vec![line(m,o)]), // connects right ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // | // ’- @@ -633,7 +633,7 @@ lazy_static! { (Weak, vec![line(m,o)]), // connects right ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // | // `- @@ -668,7 +668,7 @@ lazy_static! { (Strong, vec![line(u,e)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ (true, vec![line(u,e)]), ]} @@ -683,7 +683,7 @@ lazy_static! { (Strong, vec![line(a,y)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ (!bottom.is('|'), vec![line(a,y)]), /* @@ -708,7 +708,7 @@ lazy_static! { (Medium, vec![arc(e,y, unit8)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ (true, vec![arc(e,y,unit8)]), ] @@ -723,7 +723,7 @@ lazy_static! { (Medium, vec![arc(u,a, unit8)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ (!top.is('|') && !bottom.is('|'), vec![arc(u,a,unit8)]), // | @@ -746,7 +746,7 @@ lazy_static! { (Weak, vec![line(m,w)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // | // V @@ -779,7 +779,7 @@ lazy_static! { (Medium, vec![polygon(vec![f,j,w], true, vec![ArrowBottom])]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // | // v @@ -811,7 +811,7 @@ lazy_static! { (Medium, vec![polygon(vec![p,c,t], true, vec![ArrowTop])]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // ^ // | @@ -840,7 +840,7 @@ lazy_static! { (Medium, vec![polygon(vec![f,o,p], true, vec![ArrowRight])]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // ---> (left.line_overlap(n,o), vec![polygon(vec![f,o,p], true, vec![ArrowRight])]), @@ -865,7 +865,7 @@ lazy_static! { (Medium, vec![polygon(vec![j,k,t], true, vec![ArrowLeft])]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ // <-- (right.line_overlap(k,l), vec![polygon(vec![j,k,t], true, vec![ArrowLeft])]), @@ -890,7 +890,7 @@ lazy_static! { (Medium, vec![line(_03, _43), line(_05, _45)]), ], Arc::new( - move|top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { + move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ (true, vec![line(_03, _43), line(_05, _45)]), ] diff --git a/svgbob/src/map/circle_map.rs b/svgbob/src/map/circle_map.rs index 8b4a8c6..d1e7329 100644 --- a/svgbob/src/map/circle_map.rs +++ b/svgbob/src/map/circle_map.rs @@ -2,7 +2,7 @@ use crate::{ buffer::{CellBuffer, Contacts, Span}, fragment, fragment::Circle, - Cell, Point, + Cell, Point, Settings, }; use lazy_static::lazy_static; use std::{collections::BTreeMap, iter::FromIterator}; @@ -253,7 +253,7 @@ lazy_static! { /// Calculate the span and get the group fragments pub static ref FRAGMENTS_CIRCLE: Vec<(Vec,Circle)> = Vec::from_iter( CIRCLE_MAP.iter().map(|(art, center_cell, center, radius)|{ - (circle_art_to_group(art), Circle::new(*center, *radius, false)) + (circle_art_to_group(art, &Settings::default()), Circle::new(*center, *radius, false)) }) ); @@ -364,31 +364,40 @@ lazy_static! { let arc4_span = span.extract(arc4_top_left, arc4_bottom_right); let arc4 = fragment::Arc::new(Point::new(arc4_center.x, arc4_center.y + radius), Point::new(arc4_center.x + radius, arc4_center.y), *radius); + let settings = &Settings::default(); + vec![ - (arc1_span.get_contacts(), arc1), - (arc2_span.get_contacts(), arc2), - (arc3_span.get_contacts(), arc3), - (arc4_span.get_contacts(), arc4), + (arc1_span.get_contacts(settings), arc1), + (arc2_span.get_contacts(settings), arc2), + (arc3_span.get_contacts(settings), arc3), + (arc4_span.get_contacts(settings), arc4), ] }) ); } -fn circle_art_to_group(art: &str) -> Vec { +fn circle_art_to_group(art: &str, settings: &Settings) -> Vec { let cell_buffer = CellBuffer::from(art); let mut spans: Vec = cell_buffer.group_adjacents(); assert_eq!(spans.len(), 1); let span1 = spans.remove(0); - span1.get_contacts() + span1.get_contacts(settings) } /// [X](Done) TODO: search only the subset of contacts that matches the circle. /// if it is a subset then the circle is matched and the non-matching ones are returned pub fn endorse_circle(search: &Vec) -> Option<(&Circle, Vec)> { - FRAGMENTS_CIRCLE.iter().rev().find_map(|(contacts, circle)| { - let (matched, unmatched) = is_subset_of(contacts, search); - if matched { Some((circle, unmatched)) } else { None } - }) + FRAGMENTS_CIRCLE + .iter() + .rev() + .find_map(|(contacts, circle)| { + let (matched, unmatched) = is_subset_of(contacts, search); + if matched { + Some((circle, unmatched)) + } else { + None + } + }) } /// returns true if all the contacts in subset is in big_set @@ -422,8 +431,6 @@ pub fn endorse_arc(search: &Vec) -> Option<&fragment::Arc> { .find_map(|(contacts, arc)| if contacts == search { Some(arc) } else { None }) } - - #[cfg(test)] mod tests { use super::*; @@ -446,7 +453,7 @@ mod tests { let mut spans: Vec = cell_buffer.group_adjacents(); assert_eq!(spans.len(), 1); let span1 = spans.remove(0); - let groups = span1.get_contacts(); + let groups = span1.get_contacts(&Settings::default()); for (i, group) in groups.iter().enumerate() { println!("group{}\n{}", i, group); } @@ -464,7 +471,7 @@ mod tests { let mut spans: Vec = cell_buffer.group_adjacents(); assert_eq!(spans.len(), 1); let span1 = spans.remove(0); - let groups = span1.get_contacts(); + let groups = span1.get_contacts(&Settings::default()); for (i, group) in groups.iter().enumerate() { println!("group{}\n{}", i, group); } -- cgit v1.2.3