summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJovansonlee Cesar <ivanceras@gmail.com>2018-07-29 02:48:05 +0800
committerJovansonlee Cesar <ivanceras@gmail.com>2018-07-29 02:48:05 +0800
commitd70b9bfb5b4f0770fabd01b0617c2a67e9e759f9 (patch)
tree1097d2fe7a9a2742c20b04d36a4a0415c4685fdd
parentbba6ac50113845dc5739dcf80da9d1182b9c60e1 (diff)
A good improvement on reducing the lines
-rw-r--r--svgbob/src/fragments.rs9
-rw-r--r--svgbob/src/lib.rs187
-rw-r--r--svgbob/src/optimizer.rs208
-rw-r--r--svgbob/src/patterns.rs62
-rw-r--r--svgbob/src/properties.rs34
5 files changed, 294 insertions, 206 deletions
diff --git a/svgbob/src/fragments.rs b/svgbob/src/fragments.rs
index 2a3b153..c5c71fd 100644
--- a/svgbob/src/fragments.rs
+++ b/svgbob/src/fragments.rs
@@ -1,11 +1,12 @@
use self::Fragment::{Arc, ArrowLine, Line, OpenCircle, SolidCircle, StartArrowLine};
use properties::PointBlock;
+use std::cmp::Ordering;
/// exact location of point
/// relative to the Character Block
/// The block is divided in to 5x5 small blocks
-#[derive(PartialEq, Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, PartialOrd, PartialEq, Ord, Eq)]
pub enum Block {
A,
B,
@@ -37,7 +38,8 @@ pub enum Block {
/// These are non-final drawing elements
/// Lines most likely fall on the collinear line
/// arc most likely be changed
-#[derive(Debug, Clone)]
+
+#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)]
pub enum Fragment {
Line(PointBlock, PointBlock),
ArrowLine(PointBlock, PointBlock),
@@ -71,7 +73,8 @@ pub fn solid_circle(c: &PointBlock, r: i32) -> Fragment {
/// \|/
/// -+-
/// /|\
-#[derive(PartialEq, Debug, Clone)]
+
+#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)]
pub enum Direction {
Top,
Bottom,
diff --git a/svgbob/src/lib.rs b/svgbob/src/lib.rs
index 8f951c5..6b8f597 100644
--- a/svgbob/src/lib.rs
+++ b/svgbob/src/lib.rs
@@ -29,7 +29,7 @@
//! </svg>
//!
//!
-#![deny(warnings)]
+//#![deny(warnings)]
extern crate pom;
#[cfg(test)]
#[macro_use]
@@ -42,7 +42,6 @@ use pom::TextInput;
use self::Feature::Arrow;
use self::Feature::Circle;
-use self::Feature::Nothing;
use self::Stroke::Dashed;
use self::Stroke::Solid;
use fragments::Direction::{Bottom, BottomLeft, BottomRight, Left, Right, Top, TopLeft, TopRight};
@@ -61,6 +60,7 @@ use svg::node::element::SVG;
use svg::Node;
use unicode_width::UnicodeWidthChar;
use unicode_width::UnicodeWidthStr;
+use std::cmp::Ordering;
use ArcFlag::{Major, Minor};
@@ -204,24 +204,35 @@ impl std::fmt::Debug for SvgElement {
}
}
-#[derive(PartialEq, Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)]
pub enum Stroke {
Solid,
Dashed,
}
-#[derive(PartialEq, Debug, Clone)]
+
+#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)]
pub enum Feature {
Arrow, //end
Circle, //start
- Nothing,
}
-#[derive(PartialEq, Debug, Clone)]
+#[derive(Debug, PartialOrd, PartialEq, Clone)]
pub struct Point {
x: f32,
y: f32,
}
+impl Ord for Point{
+ fn cmp(&self, other:&Point) -> Ordering{
+ if let Some(order) = self.partial_cmp(other){
+ return order
+ }
+ Ordering::Less
+ }
+}
+impl Eq for Point{
+}
+
impl Point {
fn new(x: f32, y: f32) -> Point {
Point { x: x, y: y }
@@ -232,12 +243,21 @@ impl Point {
}
}
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq)]
pub struct Loc {
pub x: i32,
pub y: i32,
}
+impl Ord for Loc{
+ fn cmp(&self, other:&Loc) -> Ordering{
+ if let Some(order) = self.partial_cmp(other){
+ return order
+ }
+ Ordering::Less
+ }
+}
+
impl Loc {
pub fn new(x: i32, y: i32) -> Loc {
Loc { x: x, y: y }
@@ -341,23 +361,23 @@ impl Loc {
}
}
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum ArcFlag {
Major,
Minor,
}
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, PartialOrd )]
pub enum Element {
Circle(Point, f32, String),
- Line(Point, Point, Stroke, Feature),
- Arc(Point, Point, f32, ArcFlag, bool, Stroke, Feature),
+ Line(Point, Point, Stroke, Vec<Feature>),
+ Arc(Point, Point, f32, ArcFlag, bool, Stroke, Vec<Feature>),
Text(Loc, String),
Path(Point, Point, String, Stroke),
}
pub fn line(a: &Point, b: &Point) -> Element {
- Element::Line(a.clone(), b.clone(), Solid, Nothing)
+ Element::Line(a.clone(), b.clone(), Solid, vec![])
}
pub fn solid_circle(c: &Point, r: f32) -> Element {
@@ -365,19 +385,19 @@ pub fn solid_circle(c: &Point, r: f32) -> Element {
}
pub fn arrow_arc(a: &Point, b: &Point, r: f32) -> Element {
- Element::Arc(a.clone(), b.clone(), r, Minor, false, Solid, Arrow)
+ Element::Arc(a.clone(), b.clone(), r, Minor, false, Solid, vec![Arrow])
}
pub fn arrow_sweep_arc(a: &Point, b: &Point, r: f32) -> Element {
- Element::Arc(a.clone(), b.clone(), r.clone(), Minor, true, Solid, Arrow)
+ Element::Arc(a.clone(), b.clone(), r.clone(), Minor, true, Solid, vec![Arrow])
}
pub fn arc(a: &Point, b: &Point, r: f32) -> Element {
- Element::Arc(a.clone(), b.clone(), r, Minor, false, Solid, Nothing)
+ Element::Arc(a.clone(), b.clone(), r, Minor, false, Solid, vec![])
}
pub fn arc_major(a: &Point, b: &Point, r: f32) -> Element {
- Element::Arc(a.clone(), b.clone(), r, Major, false, Solid, Nothing)
+ Element::Arc(a.clone(), b.clone(), r, Major, false, Solid, vec![])
}
pub fn open_circle(c: &Point, r: f32) -> Element {
@@ -385,7 +405,7 @@ pub fn open_circle(c: &Point, r: f32) -> Element {
}
pub fn arrow_line(s: &Point, e: &Point) -> Element {
- Element::Line(s.clone(), e.clone(), Solid, Arrow)
+ Element::Line(s.clone(), e.clone(), Solid, vec![Arrow])
}
pub fn text(loc: &Loc, txt: &str) -> Element {
@@ -406,20 +426,82 @@ impl Element {
match *other {
Element::Line(ref s2, ref e2, ref stroke2, ref feature2) => {
// note: dual 3 point check for trully collinear lines
- if collinear(s, e, s2) && collinear(s, e, e2) && e == s2
- && stroke == stroke2 && *feature == Nothing
- && *feature2 != Circle
- {
- let reduced = Some(Element::Line(
- s.clone(),
- e2.clone(),
- stroke.clone(),
- feature2.clone(),
- ));
- reduced
- } else {
- None
+ if collinear(s, e, s2)
+ && collinear(s, e, e2)
+ && stroke == stroke2{
+ // line1 line2
+ // s-----e s2-----e2
+ // s----------------e2
+ if e == s2 {
+ // -----
+ // o----
+ let cond1 = feature.is_empty() || feature.contains(&Circle);
+ // ------
+ // ------>
+ let cond2 = feature2.is_empty() || feature2.contains(&Arrow) ;
+ if cond1 && cond2{
+ return Some(Element::Line(
+ s.clone(),
+ e2.clone(),
+ stroke.clone(),
+ feature2.clone()
+ ));
+ }
+ }
+ // line1 line2
+ // s------e e2-------s2
+ // s-------------------s2
+ if e == e2{
+ // ------- --------
+ // o------ ---------
+ if (feature.is_empty() || feature.contains(&Circle) )
+ && feature2.is_empty(){
+ return Some(Element::Line(
+ s.clone(),
+ s2.clone(),
+ stroke.clone(),
+ feature2.clone()
+ ));
+ }
+ }
+ // line1 line2
+ // e------s s2------e2
+ // s------------------e2
+ if s == s2{
+ // ------- -------
+ // ------- ------->
+ if feature.is_empty()
+ && (feature2.is_empty() || feature2.contains(&Arrow)){
+ return Some(Element::Line(
+ e.clone(),
+ e2.clone(),
+ stroke.clone(),
+ feature2.clone()
+ ));
+ }
+ }
+ // line1 line2
+ // e------s e2------s2
+ // e---------------------s2
+ //
+ if s == e2{
+ // ----- -----
+ // ----- ----o
+ // <---- -----
+ // <---- ----o
+ let cond1 = feature.is_empty() || feature.contains(&Arrow);
+ let cond2 = feature2.is_empty() || feature2.contains(&Circle);
+ if cond1 && cond2{
+ return Some(Element::Line(
+ s2.clone(),
+ e.clone(),
+ stroke.clone(),
+ feature.clone(),
+ ));
+ }
+ }
}
+ return None;
}
_ => None,
}
@@ -456,22 +538,22 @@ impl Element {
SvgElement::Circle(svg_circle)
}
- Element::Line(ref s, ref e, ref stroke, ref feature) => {
+ Element::Line(ref s, ref e, ref stroke, ref features) => {
let mut svg_line = SvgLine::new()
.set("x1", s.x)
.set("y1", s.y)
.set("x2", e.x)
.set("y2", e.y);
-
- match *feature {
- Arrow => {
- svg_line.assign("marker-end", "url(#triangle)");
- }
- Circle => {
- svg_line.assign("marker-start", "url(#circle)");
- }
- Nothing => (),
- };
+ for feature in features{
+ match *feature {
+ Arrow => {
+ svg_line.assign("marker-end", "url(#triangle)");
+ }
+ Circle => {
+ svg_line.assign("marker-start", "url(#circle)");
+ }
+ };
+ }
match *stroke {
Solid => (),
Dashed => {
@@ -482,7 +564,7 @@ impl Element {
SvgElement::Line(svg_line)
}
- Element::Arc(ref s, ref e, radius, ref arc_flag, sweep, _, ref feature) => {
+ Element::Arc(ref s, ref e, radius, ref arc_flag, sweep, _, ref features) => {
let sweept = if sweep { "1" } else { "0" };
let arc_flag = match *arc_flag {
Major => "1",
@@ -493,15 +575,16 @@ impl Element {
s.x, s.y, radius, radius, arc_flag, sweept, e.x, e.y
);
let mut svg_arc = SvgPath::new().set("d", d).set("fill", "none");
- match *feature {
- Arrow => {
- svg_arc.assign("marker-end", "url(#triangle)");
- }
- Circle => {
- svg_arc.assign("marker-start", "url(#circle)");
- }
- Nothing => (),
- };
+ for feature in features{
+ match *feature {
+ Arrow => {
+ svg_arc.assign("marker-end", "url(#triangle)");
+ }
+ Circle => {
+ svg_arc.assign("marker-start", "url(#circle)");
+ }
+ };
+ }
SvgElement::Path(svg_arc)
}
Element::Text(ref loc, ref string) => {
@@ -810,7 +893,7 @@ impl Grid {
let text_elm = self.get_escaped_text_elements();
elements.push(vec![text_elm]);
let input = if self.settings.optimize {
- let optimizer = Optimizer::new(elements, consumed_loc);
+ let mut optimizer = Optimizer::new(elements, consumed_loc);
let optimized_elements = optimizer.optimize(&self.settings);
optimized_elements
} else {
diff --git a/svgbob/src/optimizer.rs b/svgbob/src/optimizer.rs
index 004fd2e..12c1926 100644
--- a/svgbob/src/optimizer.rs
+++ b/svgbob/src/optimizer.rs
@@ -8,6 +8,7 @@ use ArcFlag;
pub struct Optimizer {
elements: Vec<Vec<Vec<Element>>>,
+ /// TODO: consumed location should also include the consumed element index of that location.
consumed_loc: Vec<Loc>,
}
@@ -19,9 +20,6 @@ impl Optimizer {
}
}
- fn in_consumed_loc(&self, loc: &Loc) -> bool {
- self.consumed_loc.contains(loc)
- }
fn get(&self, loc: &Loc) -> Option<&Vec<Element>> {
match self.elements.get(loc.y as usize) {
@@ -30,88 +28,96 @@ impl Optimizer {
}
}
- // return the first element only
- // there is only one element in the component
- fn first_element_only(&self, loc: &Loc) -> Option<&Element> {
- match self.get(loc) {
- Some(elements) => {
- if elements.len() == 1 {
- elements.get(0)
- } else {
- None
+
+
+ // return the reduced element and the index of the matching element on this location
+ fn reduce(&self, elm1: &Element, loc2: &Loc) -> Option<(Vec<Element>, usize)> {
+ // try all the elments of this location
+ if let Some(elements2) = self.get(loc2){
+ if elements2.len() > 0 {
+ for (i,elm2) in elements2.iter().enumerate(){
+ // use the element that can be reduced with
+ if let Some(reduced) = elm1.reduce(&elm2){
+ let mut new_reduced = vec![];
+ new_reduced.push(reduced);
+ return Some((new_reduced, i));
+ }
}
}
- None => None,
}
+ None
+
}
-
- // if the path on this location can be eated
- // from the left, from the top
- fn is_edible(&self, loc: &Loc) -> bool {
- self.can_loc_reduce(&loc.top(), loc) || self.can_loc_reduce(&loc.left(), loc)
- || self.can_loc_reduce(&loc.top_left(), loc)
- || self.can_loc_reduce(&loc.bottom_left(), loc)
- || self.can_loc_reduce(&loc.left().left(), loc) //full width character CJK can reduce 2 cells apart
- }
- // determine if element in location1
- // can reduce the element in location2
- fn can_loc_reduce(&self, loc1: &Loc, loc2: &Loc) -> bool {
- match self.first_element_only(loc1) {
- Some(elm1) => self.reduce(elm1, loc2).is_some(),
- None => false,
+ fn trace_elements(&self, element: &Element, loc: &Loc) -> (Vec<Element>, Vec<(Loc, usize)>) {
+ //trace to the right first
+ let right = loc.right();
+ let bottom = loc.bottom();
+ let bottom_right = loc.bottom_right();
+ let bottom_left = loc.bottom_left();
+ if let Some((all_reduced, elm_index)) = self.reduce(element, &right){
+ let mut all_consumed:Vec<(Loc, usize)> = vec![];
+ let mut only_reduced = vec![];
+ for reduced_elm in all_reduced{
+ let (reduced, consumed) = self.trace_elements(&reduced_elm, &right);
+ all_consumed.push((right.clone(), elm_index));
+ all_consumed.extend(consumed);
+ only_reduced = reduced;
+ }
+ (only_reduced, all_consumed)
}
- }
-
- fn reduce(&self, elm1: &Element, loc2: &Loc) -> Option<Element> {
- let elm2 = self.first_element_only(loc2);
- match elm2 {
- Some(elm2) => elm1.reduce(elm2),
- None => None,
+ else if let Some((all_reduced, elm_index)) = self.reduce(element, &bottom){
+ let mut all_consumed = vec![];
+ let mut only_reduced = vec![];
+ for reduced_elm in all_reduced{
+ let (reduced, consumed) = self.trace_elements(&reduced_elm, &bottom);
+ all_consumed.push((bottom.clone(), elm_index));
+ all_consumed.extend(consumed);
+ only_reduced = reduced;
+ }
+ (only_reduced, all_consumed)
}
- }
- fn trace_elements(&self, element: &Element, loc: &Loc) -> Element {
- match self.reduce(element, &loc.right()) {
- Some(reduced) => self.trace_elements(&reduced, &loc.right()),
- None => {
- match self.reduce(element, &loc.bottom()) {
- Some(reduced) => self.trace_elements(&reduced, &loc.bottom()),
- None => {
- match self.reduce(element, &loc.bottom_right()) {
- Some(reduced) => self.trace_elements(&reduced, &loc.bottom_right()),
- None => {
- match self.reduce(element, &loc.top_right()) {
- Some(reduced) => {
- self.trace_elements(&reduced, &loc.top_right())
- }
- None => {
- //full width character CJK can reduce 2 cells apart
- match self.reduce(element, &loc.right().right()) {
- Some(reduced) => {
- self.trace_elements(&reduced, &loc.right().right())
- }
- None => element.clone(),
- }
- }
- }
- }
- }
- }
- }
+ else if let Some((all_reduced, elm_index)) = self.reduce(element, &bottom_right){
+ let mut all_consumed = vec![];
+ let mut only_reduced = vec![];
+ for reduced_elm in all_reduced{
+ let (reduced, consumed) = self.trace_elements(&reduced_elm, &bottom_right);
+ all_consumed.push((bottom_right.clone(), elm_index));
+ all_consumed.extend(consumed);
+ only_reduced = reduced;
+ }
+ (only_reduced, all_consumed)
+ }
+ else if let Some((all_reduced, elm_index)) = self.reduce(element, &bottom_left){
+ let mut all_consumed = vec![];
+ let mut only_reduced = vec![];
+ for reduced_elm in all_reduced{
+ let (reduced, consumed) = self.trace_elements(&reduced_elm, &bottom_left);
+ all_consumed.push((bottom_left.clone(),elm_index));
+ all_consumed.extend(consumed);
+ only_reduced = reduced;
}
+ (only_reduced, all_consumed)
+ }
+ else{
+ (vec![element.to_owned()], vec![])
}
}
// TODO: order the elements in such a way that
// the start -> end -> start chains nicely
pub fn optimize(&self, settings: &Settings) -> Vec<Element> {
+ let completely_consumed_locs:Vec<Loc> = self.consumed_loc.clone();
+ let mut tracing_consumed_locs: Vec<(Loc,usize)> = vec![];
let mut optimized = vec![];
for (y, line) in self.elements.iter().enumerate() {
for (x, cell) in line.iter().enumerate() {
let loc = &Loc::new(x as i32, y as i32);
- for elm in cell {
- if !self.is_edible(loc) && !self.in_consumed_loc(loc) {
- let traced = self.trace_elements(elm, loc);
- optimized.push(traced);
+ for (elm_index, elm) in cell.iter().enumerate() {
+ if !completely_consumed_locs.contains(loc)
+ && !tracing_consumed_locs.contains(&(loc.clone(),elm_index)){
+ let (traced, consumed) = self.trace_elements(elm, loc);
+ optimized.extend(traced);
+ tracing_consumed_locs.extend(consumed);
}
}
}
@@ -126,8 +132,10 @@ impl Optimizer {
// the text in separated
fn merge_paths(&self, elements: Vec<Element>) -> Vec<Element> {
let mut merged = vec![];
- let mut solid_paths = vec![];
- let mut dashed_paths = vec![];
+ let mut solid_lines = vec![];
+ let mut dashed_lines = vec![];
+ let mut solid_arcs = vec![];
+ let mut dashed_arcs = vec![];
let mut arrows = vec![];
let mut text = vec![];
let mut circles = vec![];
@@ -136,37 +144,47 @@ impl Optimizer {
Element::Circle(_, _, _) => {
circles.push(elm.clone());
}
- Element::Line(_, _, ref stroke, ref feature) => match *feature {
- Feature::Arrow => {
- arrows.push(elm.clone());
- }
- Feature::Circle => {
- arrows.push(elm.clone());
+ Element::Line(_, _, ref stroke, ref features) => {
+ for feature in features{
+ match *feature {
+ Feature::Arrow => {
+ arrows.push(elm.clone());
+ }
+ // circle at the end rather than arrow
+ Feature::Circle => {
+ arrows.push(elm.clone());
+ }
+ }
}
- Feature::Nothing => match *stroke {
+ match *stroke {
Stroke::Solid => {
- solid_paths.push(elm.clone());
+ solid_lines.push(elm.clone());
}
Stroke::Dashed => {
- dashed_paths.push(elm.clone());
+ dashed_lines.push(elm.clone());
}
- },
- },
- Element::Arc(_, _, _, _, _, ref stroke, ref feature) => match *feature {
- Feature::Arrow => {
- arrows.push(elm.clone());
}
- Feature::Circle => {
- arrows.push(elm.clone());
+ },
+ Element::Arc(_, _, _, _, _, ref stroke, ref features) => {
+ for feature in features{
+ match *feature {
+ Feature::Arrow => {
+ arrows.push(elm.clone());
+ }
+ Feature::Circle => {
+ arrows.push(elm.clone());
+ }
+ }
}
- Feature::Nothing => match *stroke {
+
+ match *stroke {
Stroke::Solid => {
- solid_paths.push(elm.clone());
+ solid_arcs.push(elm.clone());
}
Stroke::Dashed => {
- dashed_paths.push(elm.clone());
+ dashed_arcs.push(elm.clone());
}
- },
+ }
},
Element::Text(_, _) => text.push(elm.clone()),
Element::Path(_, _, _, _) => {
@@ -174,8 +192,12 @@ impl Optimizer {
}
}
}
- merged.push(unify(solid_paths, Stroke::Solid));
- merged.push(unify(dashed_paths, Stroke::Dashed));
+ //merged.push(unify(solid_paths, Stroke::Solid));
+ //merged.push(unify(dashed_paths, Stroke::Dashed));
+ merged.extend(solid_lines);
+ merged.extend(dashed_lines);
+ merged.extend(solid_arcs);
+ merged.extend(dashed_arcs);
merged.extend(arrows);
merged.extend(text);
merged.extend(circles);
@@ -184,7 +206,7 @@ impl Optimizer {
}
/// cramp all paths that can be connected here
-fn unify(elements: Vec<Element>, stroke: Stroke) -> Element {
+fn _unify(elements: Vec<Element>, stroke: Stroke) -> Element {
let mut paths = String::new();
let mut last_loc = None;
let mut start = None;
diff --git a/svgbob/src/patterns.rs b/svgbob/src/patterns.rs
index c1d2bff..32cd456 100644
--- a/svgbob/src/patterns.rs
+++ b/svgbob/src/patterns.rs
@@ -245,7 +245,7 @@ impl LocBlock {
Y => lb.y(),
};
let unit = self.unit_x();
- p.adjust(pb.adjust.0 * unit, pb.adjust.1 * unit);
+ p.adjust(pb.adjust_x * unit, pb.adjust_y * unit);
p
}
}
@@ -461,59 +461,20 @@ impl<'g> FocusChar<'g> {
let mut consumed: Vec<Location> = vec![];
let mut matched_intended = false;
- let mut matched_enhance = false;
- let mut matched_circles = false;
- let enable_round_circles = true;
- let enable_enhancements = true;
let enable_intended_behavior = true;
let enable_default_properties = true;
- // spaces has no character
- // that's why enhance circle didn't work out well
- // Issue#1 circle: The circle is matched by testing from the center
- // however, each elements along the circle would also be
- // threated as some other characters that has some other behaviors
- // causing multiple artifacts as a result of multiple usage of the elements
- // emitting fragments and merge all together when the circle is also matched.
- // To solve the issue, checking of circle should be done first
- // and then the consumed elements are skipped and checked
- if enable_round_circles {
- let (circles, circles_consumed, along_arc) = self.round();
- if !circles.is_empty() && !self.used_as_text() {
- elm.extend(circles);
- consumed.extend(circles_consumed);
- // if circle is matched, and element is along the arc
- // skip processing of other,
- // otherwise, even if circle is matched and the element is NOT along arc
- // do process other enhancement, behaviors
- matched_circles = along_arc;
- }
- }
if let Some(character) = character {
- // enhancements
- if enable_enhancements {
- if !matched_circles {
- let (enhanced, enhance_consumed) = self.enhance();
- if !enhanced.is_empty() && !self.used_as_text() {
- elm.extend(enhanced);
- consumed.extend(enhance_consumed);
- matched_enhance = true;
- }
- }
- }
-
// intended behaviors when signals are strong
// after applying the intensifiers
// do only when enhancements is not matched
if enable_intended_behavior {
- if !matched_enhance && !matched_circles {
- for &(ref blocks, ref fragments) in &character.intended_behavior {
- let meet = blocks.iter().all(|ref b| self.can_be_strong_block(&b));
- if meet && !self.used_as_text() {
- elm.extend(fragments.clone());
- matched_intended = true;
- }
+ for &(ref blocks, ref fragments) in &character.intended_behavior {
+ let meet = blocks.iter().all(|ref b| self.can_be_strong_block(&b));
+ if meet && !self.used_as_text() {
+ elm.extend(fragments.clone());
+ matched_intended = true;
}
}
}
@@ -523,7 +484,7 @@ impl<'g> FocusChar<'g> {
// or the signal has been intensified to strong
let mut matched = false;
if enable_default_properties {
- if !matched_enhance && !matched_circles && !matched_intended {
+ if !matched_intended {
for &(ref block, ref _signal, ref fragments) in &character.properties {
// draw when used as text but intensified
if self.is_intensified(&block) && !self.used_as_text() {
@@ -538,19 +499,22 @@ impl<'g> FocusChar<'g> {
}
}
}
- if !matched && !matched_intended && !matched_enhance && !matched_circles
+ if !matched && !matched_intended
&& !self.is_blank()
{
elm.push(Text(self.text()));
}
- (elm, consumed)
} else {
if !self.is_blank() {
// This is to disconnect words
elm.push(Text(self.text()));
}
- (elm, consumed)
}
+ elm.sort();
+ elm.dedup();
+ consumed.sort();
+ consumed.dedup();
+ (elm, consumed)
}
fn get_settings(&self) -> Settings {
diff --git a/svgbob/src/properties.rs b/svgbob/src/properties.rs
index 8dc8d2f..92157be 100644
--- a/svgbob/src/properties.rs
+++ b/svgbob/src/properties.rs
@@ -11,6 +11,7 @@ use box_drawing;
use fragments::Direction::{Bottom, BottomLeft, BottomRight, Left, Right, Top, TopLeft, TopRight};
use self::Can::{ConnectTo, Is, IsStrongAll};
+use std::cmp::{Ordering,Ord};
/// the strength of signal
/// whether or not connects to the direction
@@ -26,7 +27,8 @@ use self::Can::{ConnectTo, Is, IsStrongAll};
/// Strong + Weak connects
/// Silent signals, are there but are not in used
/// They are just potential and are reluctant
-#[derive(PartialEq, Debug, Clone)]
+
+#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)]
pub enum Signal {
Weak,
Medium,
@@ -38,7 +40,7 @@ pub enum Signal {
/// a location in the grid
/// relative to the focused char
/// go to direction and how many steps to get there
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)]
pub struct Location(pub Vec<(Direction, usize)>);
impl Location {
@@ -171,18 +173,29 @@ impl Location {
PointBlock {
location: Some(self.clone()),
block: block,
- adjust: (0.0, 0.0),
+ adjust_x: 0.0,
+ adjust_y: 0.0
}
}
}
/// An exact point in the grid
/// relative to the focused char
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct PointBlock {
pub location: Option<Location>,
pub block: Block,
- pub adjust: (f32, f32),
+ pub adjust_x: f32,
+ pub adjust_y: f32,
+}
+
+impl Ord for PointBlock{
+ fn cmp(&self, other: &PointBlock) -> Ordering{
+ self.location.cmp(&other.location)
+ }
+}
+
+impl Eq for PointBlock{
}
impl PointBlock {
@@ -190,7 +203,8 @@ impl PointBlock {
PointBlock {
location: None,
block: block,
- adjust: (0.0, 0.0),
+ adjust_x: 0.0,
+ adjust_y: 0.0,
}
}
@@ -198,13 +212,15 @@ impl PointBlock {
PointBlock {
location: Some(Location::jump(direction, step)),
block: block,
- adjust: (0.0, 0.0),
+ adjust_x: 0.0,
+ adjust_y: 0.0,
}
}
pub fn adjust(&self, x: f32, y: f32) -> Self {
let mut pb = self.clone();
- pb.adjust = (pb.adjust.0 + x, pb.adjust.1 + y);
+ pb.adjust_x = pb.adjust_x + x;
+ pb.adjust_y = pb.adjust_y + y;
pb
}
}
@@ -341,6 +357,7 @@ impl Properties for char {
/////////////////////////////////
if self.is('|') {
Some(Characteristic {
+ properties: vec![(C, Strong, vec![line(c, w)]), (W, Strong, vec![line(c, w)])],
intensify: vec![
// |
// \
@@ -393,7 +410,6 @@ impl Properties for char {
// |
(vec![A], vec![line(w, m), line(m, a)]),
],
- properties: vec![(C, Strong, vec![line(c, w)]), (W, Strong, vec![line(c, w)])],
})
}
//////////////////////////////