diff options
Diffstat (limited to 'svgbob/src/element.rs')
-rw-r--r-- | svgbob/src/element.rs | 360 |
1 files changed, 0 insertions, 360 deletions
diff --git a/svgbob/src/element.rs b/svgbob/src/element.rs deleted file mode 100644 index 5b9b177..0000000 --- a/svgbob/src/element.rs +++ /dev/null @@ -1,360 +0,0 @@ -use grid::svg_escape; -use point::collinear; -use settings::Settings; -use std::cmp::Ordering; -use svg::node::element::{Circle as SvgCircle, Line as SvgLine, Path as SvgPath, Text as SvgText}; -use svg::Node; -use svg_element::SvgElement; - -use element::{ - ArcFlag::{Major, Minor}, - Feature::{Arrow, BigOpenCircle, Circle, ClearArrow, Nothing, OpenCircle, Square}, - Stroke::{Dashed, Solid}, -}; -use loc::Loc; -use point::Point; -use unicode_width::UnicodeWidthStr; -//use point; -use svg; - -#[derive(Debug, Clone, PartialEq, PartialOrd)] -pub enum Element { - Circle(Point, f32), - // start, end, stroke , start_feature, end feature - Line(Point, Point, Stroke, Feature, Feature), - // start, end, radius, sweep, stroke, start_feat, end_feat - Arc(Point, Point, f32, ArcFlag, bool, Stroke, Feature, Feature), - Text(Loc, String), -} - -#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)] -pub enum Stroke { - Solid, - Dashed, -} - -//TODO: rename to marker -#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)] -pub enum Feature { - Arrow, //end - ClearArrow, - Circle, //start - Square, //start - OpenCircle, //start - BigOpenCircle, //start - Nothing, -} - -impl Feature { - fn get_marker(&self) -> Option<&str> { - match *self { - Nothing => None, - Arrow => Some("url(#triangle)"), - ClearArrow => Some("url(#clear_triangle)"), - Circle => Some("url(#circle)"), - Square => Some("url(#square)"), - OpenCircle => Some("url(#open_circle)"), - BigOpenCircle => Some("url(#big_open_circle)"), - } - } -} - -#[derive(Debug, Clone, PartialEq, PartialOrd)] -pub enum ArcFlag { - Major, - Minor, -} - -impl Ord for Element { - fn cmp(&self, other: &Self) -> Ordering { - if let Some(order) = self.partial_cmp(&other) { - return order; - } - Ordering::Less - } -} -impl Eq for Element {} - -pub fn line(a: &Point, b: &Point) -> Element { - Element::Line(a.clone(), b.clone(), Solid, Nothing, Nothing) -} - -pub fn dashed_line(a: &Point, b: &Point) -> Element { - Element::Line(a.clone(), b.clone(), Dashed, Nothing, Nothing) -} - -pub fn circle_start_line(a: &Point, b: &Point) -> Element { - Element::Line(a.clone(), b.clone(), Solid, Circle, Nothing) -} -pub fn square_start_line(a: &Point, b: &Point) -> Element { - Element::Line(a.clone(), b.clone(), Solid, Square, Nothing) -} - -pub fn circle_open_line(a: &Point, b: &Point) -> Element { - Element::Line(a.clone(), b.clone(), Solid, OpenCircle, Nothing) -} - -pub fn big_circle_open_line(a: &Point, b: &Point) -> Element { - Element::Line(a.clone(), b.clone(), Solid, BigOpenCircle, Nothing) -} - -pub fn arc(a: &Point, b: &Point, r: f32) -> Element { - Element::Arc( - a.clone(), - b.clone(), - r, - Minor, - false, - Solid, - Nothing, - Nothing, - ) -} - -pub fn open_circle(c: &Point, r: f32) -> Element { - Element::Circle(c.clone(), r.clone()) -} - -pub fn arrow_line(s: &Point, e: &Point) -> Element { - Element::Line(s.clone(), e.clone(), Solid, Nothing, Arrow) -} - -pub fn clear_arrow_line(s: &Point, e: &Point) -> Element { - Element::Line(s.clone(), e.clone(), Solid, Nothing, ClearArrow) -} - -pub fn start_arrow_line(s: &Point, e: &Point) -> Element { - Element::Line(s.clone(), e.clone(), Solid, Arrow, Nothing) -} - -pub fn text(loc: &Loc, txt: &str) -> Element { - Element::Text(loc.clone(), svg_escape(txt)) -} - -impl Element { - pub fn shares_endpoints(&self, other: &Element) -> bool { - match *self { - Element::Line(ref s, ref e, _, _, _) => match *other { - Element::Line(ref s2, ref e2, _, _, _) => s == s2 || e == e2 || s == e2 || s2 == e, - Element::Arc(ref s2, ref e2, _, _, _, _, _, _) => { - s == s2 || e == e2 || s == e2 || s2 == e - } - _ => false, - }, - Element::Arc(ref s, ref e, _, _, _, _, _, _) => match *other { - Element::Line(ref s2, ref e2, _, _, _) => s == s2 || e == e2 || s == e2 || s2 == e, - Element::Arc(ref s2, ref e2, _, _, _, _, _, _) => { - s == s2 || e == e2 || s == e2 || s2 == e - } - _ => false, - }, - _ => false, - } - } - // if this element can reduce the other, return the new reduced element - // for line it has to be collinear and in can connect start->end->start - // for text, the other text should apear on the right side of this text - pub fn reduce(&self, other: &Element) -> Option<Element> { - // if same then return one - if self == other { - return Some(other.clone()); - } - match *self { - Element::Line(ref s, ref e, ref stroke, ref start_feature, ref end_feature) => { - match *other { - Element::Line( - ref s2, - ref e2, - ref stroke2, - ref start_feature2, - ref end_feature2, - ) => { - // note: dual 3 point check for trully collinear lines - if collinear(s, e, s2) && collinear(s, e, e2) && stroke == stroke2 { - // same length line - if s == s2 - && e == e2 - && start_feature == start_feature2 - && end_feature == end_feature2 - { - return Some(other.clone()); - } - // extend 1 with 2 - // line1 line2 - // s-----e s2-----e2 - // s----------------e2 - else if e == s2 { - // ----- - // o---- - // ------ - // ------> - if *end_feature == Nothing && *start_feature2 == Nothing { - return Some(Element::Line( - s.clone(), - e2.clone(), - stroke.clone(), - start_feature.clone(), - end_feature2.clone(), - )); - } - } - // extend 1 with flip 2 - // line1 line2 - // s------e e2-------s2 - // s-------------------s2 - else if e == e2 { - // ------- -------- - // o------ --------- - if *end_feature == Nothing && *end_feature2 == Nothing { - return Some(Element::Line( - s.clone(), - s2.clone(), - stroke.clone(), - start_feature.clone(), - start_feature2.clone(), - )); - } - } - // flip1 extend 2 - // line1 line2 - // e------s s2------e2 - // s------------------e2 - else if s == s2 { - // ------- ------- - // ------- -------> - // except for line 1 has arrow at the end - if *start_feature == Nothing - && *start_feature2 == Nothing - && *end_feature != Arrow - { - return Some(Element::Line( - e.clone(), - e2.clone(), - stroke.clone(), - end_feature.clone(), - end_feature2.clone(), - )); - } - } - // extend 2 with 1 - // line1 line2 - // e------s e2------s2 - // e---------------------s2 - // - else if s == e2 { - // ----- ----- - // ----- ----o - // <---- ----- - // <---- ----o - if *start_feature == Nothing && *end_feature2 == Nothing { - return Some(Element::Line( - s2.clone(), - e.clone(), - stroke.clone(), - start_feature2.clone(), - end_feature.clone(), - )); - } - } - } - return None; - } - _ => None, - } - } - Element::Text(ref loc, ref text) => { - match *other { - Element::Text(ref loc2, ref text2) => { - // reduce if other is next to it - let uwidth = text.width() as i32; - if loc.y == loc2.y && loc.x + uwidth == loc2.x { - let merged_text = text.clone() + text2; - let reduced = Some(Element::Text(loc.clone(), merged_text)); - reduced - } else { - None - } - } - _ => None, - } - } - _ => None, - } - } - - /// convert drawing element to SVG element - pub fn to_svg(&self, settings: &Settings) -> SvgElement { - match *self { - Element::Circle(ref c, r) => { - let svg_circle = SvgCircle::new() - .set("class", "fg_stroke no_fill") - .set("cx", c.x) - .set("cy", c.y) - .set("r", r); - - SvgElement::Circle(svg_circle) - } - Element::Line(ref s, ref e, ref stroke, ref start_feature, ref end_feature) => { - let mut svg_line = SvgLine::new() - .set("class", "fg_stroke") - .set("x1", s.x) - .set("y1", s.y) - .set("x2", e.x) - .set("y2", e.y); - - if let Some(marker) = start_feature.get_marker() { - svg_line.assign("marker-start", marker); - } - if let Some(marker) = end_feature.get_marker() { - svg_line.assign("marker-end", marker); - } - match *stroke { - Solid => (), - Dashed => { - svg_line.assign("class", "fg_stroke dashed"); - } - }; - SvgElement::Line(svg_line) - } - Element::Arc( - ref s, - ref e, - radius, - ref arc_flag, - sweep, - _, - ref start_feature, - ref end_feature, - ) => { - let sweept = if sweep { "1" } else { "0" }; - let arc_flag = match *arc_flag { - Major => "1", - Minor => "0", - }; - let d = format!( - "M {} {} A {} {} 0 {} {} {} {}", - s.x, s.y, radius, radius, arc_flag, sweept, e.x, e.y - ); - let mut svg_arc = SvgPath::new().set("class", "fg_stroke no_fill").set("d", d); - if let Some(marker) = start_feature.get_marker() { - svg_arc.assign("marker-start", marker); - } - if let Some(marker) = end_feature.get_marker() { - svg_arc.assign("marker-end", marker); - } - SvgElement::Path(svg_arc) - } - Element::Text(ref loc, ref string) => { - let sx = loc.x as f32 * settings.text_width + settings.text_width / 8.0; - let sy = loc.y as f32 * settings.text_height + settings.text_height * 3.0 / 4.0; - let mut svg_text = SvgText::new() - .set("class", "fg_fill") - .set("x", sx) - .set("y", sy); - let text_node = svg::node::Text::new(string.to_string()); - svg_text.append(text_node); - SvgElement::Text(svg_text) - } - } - } -} |