123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- use std::{
- fmt::Debug,
- fs::File,
- io::{Cursor, Read, Write},
- path::PathBuf,
- };
- use binrw::{BinRead, BinWrite, BinWriterExt};
- use diff::Diff;
- use modular_bitfield::{
- bitfield,
- specifiers::{B1, B14},
- };
- use crate::{
- field_of::FieldOf,
- types::{Coordinate, Field, ObjectType, WString, F64, U16, U32},
- };
- use self::{
- circle::Circle, ellipse::Ellipse, hatch::Hatch, line::Lines, polygon::Polygon,
- rectangle::Rectangle,
- };
- pub mod circle;
- pub mod ellipse;
- pub mod hatch;
- pub mod line;
- pub mod polygon;
- pub mod rectangle;
- pub trait Translate {
- /// Move origin of object to point
- fn move_absolute(&mut self, origin: Option<Coordinate>, z: Option<f64>);
- fn move_relative(&mut self, delta: Option<Coordinate>, z: Option<f64>);
- }
- #[bitfield(bits = 16)]
- #[derive(BinRead, BinWrite, Copy, Clone, Debug, Default, Diff, PartialEq)]
- #[diff(attr(
- #[derive(Debug, PartialEq)]
- ))]
- #[br(map = Self::from_bytes)]
- #[bw(map = |&x| Self::into_bytes(x))]
- pub struct ObjectFlags {
- pub disabled: B1,
- pub aspect_ratio_unlocked: B1,
- #[skip]
- __: B14,
- }
- /// Core properties defined for all object types
- #[cfg_attr(feature = "default-debug", derive(Debug))]
- #[derive(BinRead, BinWrite, Clone, Diff, PartialEq)]
- #[diff(attr(
- #[derive(Debug, PartialEq)]
- ))]
- #[brw(magic(17u32))]
- pub struct ObjectCore {
- pub pen: U32,
- pub obj_type: FieldOf<ObjectType>,
- pub flags: FieldOf<ObjectFlags>,
- pub name: WString,
- pub count: U32,
- pub _unknown_1: Field,
- pub io_control_enable_mask: U16,
- pub io_control_disable_mask: U16,
- pub _unknown_2: [Field; 5],
- pub origin: FieldOf<Coordinate>,
- pub z: F64,
- pub a: F64,
- pub index: U32, // Increments for each hatch fill line (types 1/2) or 0xFFFF_FFFF (types 3/4/5/7/8)
- }
- // Custom Debug implementation to only print known fields
- #[cfg(not(feature = "default-debug"))]
- impl Debug for ObjectCore {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("ObjectCore")
- .field("pen", &self.pen)
- .field("obj_type", &self.obj_type)
- .field("flags", &self.flags)
- .field("name", &self.name)
- .field("count", &self.count)
- .field("io_control_enable_mask", &self.io_control_enable_mask)
- .field("io_control_disable_mask", &self.io_control_disable_mask)
- .field("origin", &self.origin)
- .field("z", &self.z)
- .field("a", &self.a)
- .field("index", &self.index)
- .finish()
- }
- }
- impl Translate for ObjectCore {
- fn move_absolute(&mut self, origin: Option<Coordinate>, z: Option<f64>) {
- origin.map(|origin| *self.origin = origin);
- z.map(|z| self.z = z.into());
- }
- fn move_relative(&mut self, delta: Option<Coordinate>, z: Option<f64>) {
- delta.map(|delta| *self.origin += delta);
- z.map(|z| *self.z += z);
- }
- }
- impl ObjectCore {
- pub fn default(obj_type: ObjectType) -> Self {
- Self {
- pen: 0.into(),
- obj_type: obj_type.into(),
- flags: ObjectFlags::new()
- .with_disabled(0)
- .with_aspect_ratio_unlocked(0)
- .into(),
- name: "\0".to_string().into(),
- count: 1.into(),
- _unknown_1: vec![0, 0].into(), // 0_u16
- io_control_enable_mask: Default::default(),
- io_control_disable_mask: Default::default(),
- _unknown_2: [
- vec![0, 0].into(), // 0_u16
- vec![1, 0, 0, 0].into(), // 1_u32
- vec![1, 0, 0, 0].into(), // 1_u32
- vec![0, 0, 0, 0, 0, 0, 36, 64].into(), // 10.0_f64
- vec![0, 0, 0, 0, 0, 0, 36, 64].into(), // 10.0_f64
- ]
- .into(),
- origin: Coordinate { x: 0.0, y: 0.0 }.into(),
- z: 0.0.into(),
- a: 0.0.into(),
- index: 0.into(),
- }
- }
- }
- #[derive(BinRead, BinWrite, Clone, Debug, Diff, PartialEq, strum::Display)]
- #[diff(attr(
- #[derive(Debug, PartialEq)]
- ))]
- pub enum Object {
- #[brw(magic = 1u32)]
- Curve(Lines),
- #[brw(magic = 2u32)]
- Point(Lines),
- #[brw(magic = 3u32)]
- Rectangle(Rectangle),
- #[brw(magic = 4u32)]
- Circle(Circle),
- #[brw(magic = 5u32)]
- Ellipse(Ellipse),
- #[brw(magic = 6u32)]
- Polygon(Polygon),
- #[brw(magic = 32u32)]
- Hatch(Hatch),
- }
- impl Translate for Object {
- fn move_absolute(&mut self, origin: Option<Coordinate>, z: Option<f64>) {
- match self {
- Object::Curve(x) => x.move_absolute(origin, z),
- Object::Point(x) => x.move_absolute(origin, z),
- Object::Rectangle(x) => x.move_absolute(origin, z),
- Object::Circle(x) => x.move_absolute(origin, z),
- Object::Ellipse(x) => x.move_absolute(origin, z),
- Object::Polygon(x) => x.move_absolute(origin, z),
- Object::Hatch(x) => x.move_absolute(origin, z),
- }
- }
- fn move_relative(&mut self, delta: Option<Coordinate>, z: Option<f64>) {
- match self {
- Object::Curve(x) => x.move_relative(delta, z),
- Object::Point(x) => x.move_relative(delta, z),
- Object::Rectangle(x) => x.move_relative(delta, z),
- Object::Circle(x) => x.move_relative(delta, z),
- Object::Ellipse(x) => x.move_relative(delta, z),
- Object::Polygon(x) => x.move_relative(delta, z),
- Object::Hatch(x) => x.move_relative(delta, z),
- }
- }
- }
- impl Object {
- pub fn read_from_file(path: &PathBuf) -> Self {
- let mut input: File = File::open(path).expect("Failed to open input file");
- let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]);
- input
- .read_to_end(buffer.get_mut())
- .expect("Failed to read input file");
- Object::read_le(&mut buffer).expect("Failed to deserialize input as object")
- }
- pub fn write_to_file(&self, path: &PathBuf) {
- let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]);
- buffer.write_le(self).expect("Failed to serialize object");
- let mut output: File = File::create(path).expect("Failed to open output file");
- output
- .write_all(buffer.into_inner().as_slice())
- .expect("Failed to write to output file");
- }
- pub fn set_pen(&mut self, pen: u32) {
- match self {
- Object::Curve(x) => x.core.pen = pen.into(),
- Object::Point(x) => x.core.pen = pen.into(),
- Object::Rectangle(x) => x.core.pen = pen.into(),
- Object::Circle(x) => x.core.pen = pen.into(),
- Object::Ellipse(x) => x.core.pen = pen.into(),
- Object::Polygon(x) => x.core.pen = pen.into(),
- Object::Hatch(x) => {
- x.core.pen = pen.into();
- x.hatch_settings.iter_mut().for_each(|y| y.pen = pen.into());
- x.legacy_setting.hatch_0_pen = pen.into();
- x.legacy_setting.hatch_1_pen = pen.into();
- x.legacy_setting.hatch_2_pen = pen.into();
- }
- }
- }
- pub fn core(&mut self) -> &mut ObjectCore {
- match self {
- Object::Curve(x) => &mut x.core,
- Object::Point(x) => &mut x.core,
- Object::Rectangle(x) => &mut x.core,
- Object::Circle(x) => &mut x.core,
- Object::Ellipse(x) => &mut x.core,
- Object::Polygon(x) => &mut x.core,
- Object::Hatch(x) => &mut x.core,
- }
- }
- }
- #[derive(BinRead, BinWrite, Clone, Debug, Diff, PartialEq)]
- #[diff(attr(
- #[derive(Debug, PartialEq)]
- ))]
- pub struct ObjectModified {
- pub default: U32, // 0 if values are default, 255 otherwise
- pub changes: FieldOf<ScaleValues>,
- }
- impl Default for ObjectModified {
- fn default() -> Self {
- Self {
- default: 0.into(),
- changes: ScaleValues::default().into(),
- }
- }
- }
- #[derive(BinRead, BinWrite, Clone, Diff, PartialEq)]
- #[diff(attr(
- #[derive(Debug, PartialEq)]
- ))]
- pub struct ScaleValues {
- pub width_scale: f64,
- #[br(assert(_unknown_1 == 0.0))]
- _unknown_1: f64,
- #[br(assert(_unknown_2 == 0.0))]
- _unknown_2: f64,
- #[br(assert(_unknown_3 == 0.0))]
- _unknown_3: f64,
- pub height_scale: f64,
- #[br(assert(_unknown_4 == 0.0))]
- _unknown_4: f64,
- pub origin_x_delta: f64,
- pub origin_y_delta: f64,
- #[br(assert(_unknown_5 == 1.0))]
- _unknown_5: f64,
- }
- impl Default for ScaleValues {
- fn default() -> Self {
- Self {
- width_scale: 1.0.into(),
- _unknown_1: 0.0.into(),
- _unknown_2: 0.0.into(),
- _unknown_3: 0.0.into(),
- height_scale: 1.0.into(),
- _unknown_4: 0.0.into(),
- origin_x_delta: 0.0.into(),
- origin_y_delta: 0.0.into(),
- _unknown_5: 1.0.into(),
- }
- }
- }
- // Custom Debug implementation to only print known fields
- impl Debug for ScaleValues {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("ScaleValues")
- .field("width_scale", &self.width_scale)
- .field("height_scale", &self.height_scale)
- .field("origin_x_delta", &self.origin_x_delta)
- .field("origin_y_delta", &self.origin_y_delta)
- .finish()
- }
- }
|