dxf 0.2.0

A rust crate for reading and writing DXF and DXB CAD files.
Documentation
// Copyright (c) IxMilia.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

extern crate dxf;
use self::dxf::*;
use self::dxf::enums::*;

extern crate chrono;
use self::chrono::*;

mod test_helpers;
use test_helpers::helpers::*;

#[test]
fn empty_header() {
    let _file = parse_drawing(vec!["0", "SECTION", "2", "HEADER", "0", "ENDSEC", "0", "EOF"].join("\n").as_str());
}

#[test]
fn specific_header_values() {
    let file = from_section("HEADER", "
  9
$ACADMAINTVER
 70
16
  9
$ACADVER
  1
AC1012
  9
$ANGBASE
 50
5.5E1
  9
$ANGDIR
 70
1
  9
$ATTMODE
 70
1
  9
$AUNITS
 70
3
  9
$AUPREC
 70
7
  9
$CLAYER
  8
<current layer>
  9
$LUNITS
 70
6
  9
$LUPREC
 70
7".trim_left());
    assert_eq!(16, file.header.maintenance_version);
    assert_eq!(AcadVersion::R13, file.header.version);
    assert_eq!(55.0, file.header.angle_zero_direction);
    assert_eq!(AngleDirection::Clockwise, file.header.angle_direction);
    assert_eq!(AttributeVisibility::Normal, file.header.attribute_visibility);
    assert_eq!(AngleFormat::Radians, file.header.angle_unit_format);
    assert_eq!(7, file.header.angle_unit_precision);
    assert_eq!("<current layer>", file.header.current_layer);
    assert_eq!(UnitFormat::Architectural, file.header.unit_format);
    assert_eq!(7, file.header.unit_precision);
}

#[test]
fn read_alternate_version() {
    let file = from_section("HEADER", vec!["  9", "$ACADVER", "  1", "15.05"].join("\r\n").as_str());
    assert_eq!(AcadVersion::R2000, file.header.version);
}

#[test]
fn read_multi_value_variable() {
    let file = from_section("HEADER", vec!["9", "$EXTMIN", "10", "1.1", "20", "2.2", "30", "3.3"].join("\r\n").as_str());
    assert_eq!(Point::new(1.1, 2.2, 3.3), file.header.minimum_drawing_extents)
}

#[test]
fn write_multiple_value_variable() {
    let mut file = Drawing::default();
    file.header.minimum_drawing_extents = Point::new(1.1, 2.2, 3.3);
    assert!(to_test_string(&file).contains(vec!["9", "$EXTMIN", " 10", "1.1", " 20", "2.2", " 30", "3.3"].join("\r\n").as_str()));
}

#[test]
fn normalize_header() {
    let mut header = Header::default();
    header.default_text_height = -1.0; // $TEXTSIZE; normalized to 0.2
    header.trace_width = 0.0; // $TRACEWID; normalized to 0.05
    header.text_style = String::new(); // $TEXTSTYLE; normalized to "STANDARD"
    header.current_layer = String::new(); // $CLAYER; normalized to "0"
    header.current_entity_line_type = String::new(); // $CELTYPE; normalized to "BYLAYER"
    header.dimension_style_name = String::new(); // $DIMSTYLE; normalized to "STANDARD"
    header.file_name = String::new(); // $MENU; normalized to "."
    header.normalize();
    assert_eq!(0.2, header.default_text_height);
    assert_eq!(0.05, header.trace_width);
    assert_eq!("STANDARD", header.text_style);
    assert_eq!("0", header.current_layer);
    assert_eq!("BYLAYER", header.current_entity_line_type);
    assert_eq!("STANDARD", header.dimension_style_name);
    assert_eq!(".", header.file_name);
}

#[test]
fn read_header_flags() {
    let file = from_section("HEADER", vec!["9", "$OSMODE", "70", "12"].join("\r\n").as_str());
    assert!(!file.header.get_end_point_snap());
    assert!(!file.header.get_mid_point_snap());
    assert!(file.header.get_center_snap());
    assert!(file.header.get_node_snap());
    assert!(!file.header.get_quadrant_snap());
    assert!(!file.header.get_intersection_snap());
    assert!(!file.header.get_insertion_snap());
    assert!(!file.header.get_perpendicular_snap());
    assert!(!file.header.get_tangent_snap());
    assert!(!file.header.get_nearest_snap());
    assert!(!file.header.get_apparent_intersection_snap());
    assert!(!file.header.get_extension_snap());
    assert!(!file.header.get_parallel_snap());
}

#[test]
fn write_header_flags() {
    let mut file = Drawing::default();
    file.header.set_end_point_snap(false);
    file.header.set_mid_point_snap(false);
    file.header.set_center_snap(true);
    file.header.set_node_snap(true);
    file.header.set_quadrant_snap(false);
    file.header.set_intersection_snap(false);
    file.header.set_insertion_snap(false);
    file.header.set_perpendicular_snap(false);
    file.header.set_tangent_snap(false);
    file.header.set_nearest_snap(false);
    file.header.set_apparent_intersection_snap(false);
    file.header.set_extension_snap(false);
    file.header.set_parallel_snap(false);
    assert_contains(&file, vec!["  9", "$OSMODE", " 70", "    12"].join("\r\n"));
}

#[test]
fn read_variable_with_different_codes() {
    // read $CMLSTYLE as code 7
    let file = from_section("HEADER", vec!["  9", "$CMLSTYLE", "  7", "cml-style-7"].join("\r\n").as_str());
    assert_eq!("cml-style-7", file.header.current_multiline_style);

    // read $CMLSTYLE as code 2
    let file = from_section("HEADER", vec!["  9", "$CMLSTYLE", "  2", "cml-style-2"].join("\r\n").as_str());
    assert_eq!("cml-style-2", file.header.current_multiline_style);
}

#[test]
fn write_variable_with_different_codes() {
    // R13 writes $CMLSTYLE as a code 7
    let mut file = Drawing::default();
    file.header.version = AcadVersion::R13;
    file.header.current_multiline_style = String::from("cml-style-7");
    assert_contains(&file, vec!["  9", "$CMLSTYLE", "  7", "cml-style-7"].join("\r\n"));

    // R14+ writes $CMLSTYLE as a code 2
    let mut file = Drawing::default();
    file.header.version = AcadVersion::R14;
    file.header.current_multiline_style = String::from("cml-style-2");
    assert_contains(&file, vec!["  9", "$CMLSTYLE", "  2", "cml-style-2"].join("\r\n"));
}

#[test]
fn read_drawing_edit_duration() {
    let file = from_section("HEADER", vec!["  9", "$TDINDWG", " 40", "100.0"].join("\r\n").as_str());
    assert_eq!(Duration::seconds(100), file.header.time_in_drawing);
}