Skip to content

Commit 94abbab

Browse files
committed
Starting with VP3
1 parent 620bf40 commit 94abbab

13 files changed

Lines changed: 684 additions & 1 deletion

File tree

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ members = [
1212
"formats/hus",
1313
"formats/jef",
1414
"formats/svg",
15+
"formats/vf3",
16+
"formats/vp3",
1517
"formats/vp4",
1618
]
1719

@@ -26,4 +28,5 @@ embroidery-fmt-hus = { path = "./formats/hus" }
2628
embroidery-fmt-jef = { path = "./formats/jef" }
2729
embroidery-fmt-svg = { path = "./formats/svg" }
2830
embroidery-fmt-vf3 = { path = "./formats/vf3" }
31+
embroidery-fmt-vp3 = { path = "./formats/vp3" }
2932
embroidery-fmt-vp4 = { path = "./formats/vp4" }

formats/hus/tests/hus.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use embroidery_fmt_hus::HusVipPatternReader;
55

66
use std::collections::BTreeMap;
77
use std::io::Cursor;
8+
use std::collections::BTreeMap;
89

910
#[test]
1011
fn test_hus_file_load() {

formats/vp3/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "embroidery-fmt-vp3"
3+
version = "0.1.0"
4+
authors = ["Opal <code@opal.codes>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
byteorder = "1"
9+
embroidery-lib = { path = "../../embroidery-lib" }

formats/vp3/src/lib.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
mod read;
2+
// mod write;
3+
4+
use embroidery_lib::format::{PatternFormat, PatternReader, PatternWriter};
5+
6+
pub use self::read::Vp3PatternReader;
7+
// pub use self::write::Vp3PatternWriter;
8+
9+
const NAME: &'static str = "vp3";
10+
const EXTENSIONS: [&'static str; 1] = ["vp3"];
11+
12+
#[derive(Default)]
13+
pub struct Vp3PatternFormat {}
14+
15+
impl PatternFormat for Vp3PatternFormat {
16+
fn name<'a>(&self) -> &'a str {
17+
NAME
18+
}
19+
fn extensions<'a, 'b>(&self) -> &'a [&'b str] {
20+
&EXTENSIONS
21+
}
22+
fn reader(&self) -> Option<Box<dyn PatternReader>> {
23+
Some(Box::from(Vp3PatternReader::default()))
24+
}
25+
fn writer(&self) -> Option<Box<dyn PatternWriter>> {
26+
None
27+
}
28+
}

formats/vp3/src/read.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use embroidery_lib::format::PatternReader;
2+
use embroidery_lib::maybe_read_with_context;
3+
use embroidery_lib::prelude::*;
4+
5+
use std::io::Read;
6+
7+
mod header;
8+
mod thread;
9+
mod util;
10+
11+
#[derive(Default)]
12+
pub struct Vp3PatternReader {}
13+
14+
impl PatternReader for Vp3PatternReader {
15+
fn is_loadable(&self, reader: &mut dyn Read) -> Result<bool, ReadError> {
16+
header::read_header(reader)?;
17+
Ok(false)
18+
}
19+
fn read_pattern(&self, ub_reader: &mut dyn Read) -> Result<Pattern, ReadError> {
20+
let (header, mut reader) = header::read_header(ub_reader)?;
21+
22+
for i in 0..header.number_of_threads {
23+
let thread_header = maybe_read_with_context!(
24+
thread::read_thread_header(&mut reader),
25+
"Reading thread {} of {}",
26+
i,
27+
header.number_of_threads,
28+
)?;
29+
eprintln!("TH: {:?}", thread_header);
30+
let stitches = maybe_read_with_context!(
31+
thread::read_stitches(&mut reader, &thread_header),
32+
"Reading thread {} of {}",
33+
i,
34+
header.number_of_threads,
35+
)?;
36+
eprintln!("ST Done: {}", stitches.len())
37+
}
38+
39+
eprintln!("{:?}", header);
40+
unimplemented!();
41+
}
42+
}

formats/vp3/src/read/header.rs

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
use byteorder::BigEndian;
2+
3+
use embroidery_lib::prelude::*;
4+
use embroidery_lib::{read_exact_magic, read_int};
5+
6+
use std::convert::TryInto;
7+
use std::io::Read;
8+
9+
use super::util::read_wide_string_field;
10+
11+
#[derive(Debug, PartialEq)]
12+
pub struct Vp3Header {
13+
pub software_vendor_string: String,
14+
pub bytes_remaining: u32,
15+
pub file_comment_string: String,
16+
pub hoop: Vp3Hoop,
17+
pub another_software_vendor_string: String,
18+
pub number_of_threads: usize,
19+
}
20+
#[derive(Debug, PartialEq)]
21+
pub struct Vp3Hoop {
22+
pub right: i32,
23+
pub bottom: i32,
24+
pub left: i32,
25+
pub top: i32,
26+
pub unknown_a: u32,
27+
pub unknown_b: u16,
28+
pub bytes_remaining: usize,
29+
pub x_offset: i32,
30+
pub y_offset: i32,
31+
32+
/* Centered hoop dimensions */
33+
pub right2: i32,
34+
pub left2: i32,
35+
pub bottom2: i32,
36+
pub top2: i32,
37+
38+
pub width: i32,
39+
pub height: i32,
40+
}
41+
42+
pub fn read_header<'a>(ub_reader: &'a mut dyn Read) -> Result<(Vp3Header, std::io::Take<&'a mut dyn Read>), ReadError> {
43+
let mut magics = [0_u8; 6];
44+
ub_reader.read_exact(&mut magics)?;
45+
if &magics != b"%vsm%\0" {
46+
return Err(ReadError::invalid_format(format!("Incorrect magic bytes {:?}", magics)));
47+
}
48+
49+
let software_vendor_string = read_wide_string_field(ub_reader, "software_vendor_string")?;
50+
read_exact_magic!(ub_reader, [0x00, 0x02, 0x00])?;
51+
let bytes_remaining = read_int!(ub_reader, u32, BigEndian)?;
52+
53+
let mut reader = ub_reader.take(bytes_remaining.into());
54+
let file_comment_string = read_wide_string_field(&mut reader, "file_comment_string")?;
55+
56+
let hoop = read_hoop(&mut reader)?;
57+
eprintln!("{:?}", hoop);
58+
59+
read_exact_magic!(
60+
reader,
61+
[
62+
0x00, 0x00, 0x64, 0x64, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63+
0x10, 0x00
64+
]
65+
)?;
66+
67+
// This is noted as [0x78, 0x78, 0x55, 0x55, 0x01, 0x00] in Embroidermodder; but testing
68+
// reveals it to be [0x78, 0x78, 0x50, 0x50, 0x01, 0x00]
69+
read_exact_magic!(reader, [0x78, 0x78, 0x50, 0x50, 0x01, 0x00])?;
70+
71+
let another_software_vendor_string = read_wide_string_field(&mut reader, "another_software_vendor_string")?;
72+
73+
let number_of_threads: usize = read_int!(reader, u16, BigEndian)?.into();
74+
75+
Ok((
76+
Vp3Header {
77+
software_vendor_string,
78+
bytes_remaining,
79+
file_comment_string,
80+
hoop,
81+
another_software_vendor_string,
82+
number_of_threads,
83+
},
84+
reader,
85+
))
86+
}
87+
88+
fn read_hoop(reader: &mut dyn Read) -> Result<Vp3Hoop, ReadError> {
89+
let left = read_int!(reader, i32, BigEndian)?;
90+
let top = read_int!(reader, i32, BigEndian)?;
91+
let right = read_int!(reader, i32, BigEndian)?;
92+
let bottom = read_int!(reader, i32, BigEndian)?;
93+
94+
// Probably number of stitches
95+
let unknown_a = read_int!(reader, u32, BigEndian)?;
96+
// Probably number of colors(read: threads)
97+
let unknown_b = read_int!(reader, u16, BigEndian)?;
98+
99+
read_exact_magic!(reader, [0x0C, 0x00, 0x01, 0x00, 0x03, 0x00])?;
100+
101+
let bytes_remaining = read_int!(reader, u32, BigEndian)?;
102+
103+
let y_offset = read_int!(reader, i32, BigEndian)?;
104+
let x_offset = read_int!(reader, i32, BigEndian)?;
105+
106+
read_exact_magic!(reader, [0x00, 0x00, 0x00])?;
107+
108+
/* Centered hoop dimensions */
109+
let right2 = read_int!(reader, i32, BigEndian)?;
110+
let left2 = read_int!(reader, i32, BigEndian)?;
111+
let bottom2 = read_int!(reader, i32, BigEndian)?;
112+
let top2 = read_int!(reader, i32, BigEndian)?;
113+
114+
let width = read_int!(reader, i32, BigEndian)?;
115+
let height = read_int!(reader, i32, BigEndian)?;
116+
117+
return Ok(Vp3Hoop {
118+
right,
119+
bottom,
120+
left,
121+
top,
122+
unknown_a,
123+
unknown_b,
124+
bytes_remaining: bytes_remaining.try_into().unwrap(),
125+
x_offset,
126+
y_offset,
127+
right2,
128+
left2,
129+
bottom2,
130+
top2,
131+
width,
132+
height,
133+
});
134+
}
135+
136+
#[cfg(test)]
137+
mod tests {
138+
use super::*;
139+
140+
#[test]
141+
fn test_read_file_t160_vp3() {
142+
// T160.vp3 StartOffset(h): 00000000, EndOffset(h): 000000FF, Length(h): 00000100
143+
144+
let data: [u8; 256] = [
145+
0x25, 0x76, 0x73, 0x6D, 0x25, 0x00, 0x00, 0x38, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x75,
146+
0x00, 0x63, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
147+
0x00, 0x20, 0x00, 0x20, 0x00, 0x53, 0x00, 0x6F, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72,
148+
0x00, 0x65, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x74, 0x00, 0x64, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD8, 0x41, 0x00,
149+
0x00, 0x00, 0x00, 0xF2, 0x30, 0x00, 0x01, 0x4F, 0xF0, 0xFF, 0xFF, 0x0D, 0xD0, 0xFF, 0xFE, 0xB0, 0x10, 0x00,
150+
0x00, 0x69, 0xB5, 0x00, 0x08, 0x0C, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD8, 0x1F, 0x00, 0x00, 0x00,
151+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0D, 0xD0, 0x00, 0x00, 0xF2, 0x30, 0xFF, 0xFE,
152+
0xB0, 0x10, 0x00, 0x01, 0x4F, 0xF0, 0x00, 0x01, 0xE4, 0x60, 0x00, 0x02, 0x9F, 0xE0, 0x00, 0x00, 0x64, 0x64,
153+
0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x78, 0x78,
154+
0x50, 0x50, 0x01, 0x00, 0x00, 0x38, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63,
155+
0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x62, 0x00, 0x79, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
156+
0x00, 0x20, 0x00, 0x53, 0x00, 0x6F, 0x00, 0x66, 0x00, 0x74, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65,
157+
0x00, 0x20, 0x00, 0x4C, 0x00, 0x74, 0x00, 0x64, 0x00, 0x08, 0x00, 0x05, 0x00, 0x00, 0x00, 0x1C, 0xBB, 0x00,
158+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xDE, 0xE6, 0xE8, 0x00, 0x00, 0x00, 0x05, 0x28, 0x00,
159+
0x04, 0x31, 0x30, 0x30,
160+
];
161+
162+
let (header, _) = read_header(&mut &data[..]).unwrap();
163+
eprintln!("{:?}", header);
164+
assert_eq!(
165+
header,
166+
Vp3Header {
167+
software_vendor_string: "Produced by Software Ltd".to_string(),
168+
bytes_remaining: 55_361, /* 0x00_00_D8_41 */
169+
file_comment_string: "".to_string(),
170+
another_software_vendor_string: "Produced by Software Ltd".to_string(),
171+
number_of_threads: 8,
172+
hoop: Vp3Hoop {
173+
right: -62_000,
174+
left: 62_000,
175+
bottom: -86_000,
176+
top: 86_000,
177+
unknown_a: 27061,
178+
unknown_b: 8,
179+
bytes_remaining: 55327,
180+
x_offset: 0,
181+
y_offset: 0,
182+
183+
right2: -62_000,
184+
left2: 62_000,
185+
bottom2: -86_000,
186+
top2: 86_000,
187+
width: 124_000,
188+
height: 172_000,
189+
}
190+
}
191+
);
192+
}
193+
194+
#[test]
195+
fn test_read_hoop_t160_vp3() {
196+
// T160.vp3 StartOffset(h): 00000049, EndOffset(h): 0000008B, Length(h): 00000043
197+
let data: [u8; 67] = [
198+
0x00, 0x00, 0xF2, 0x30, 0x00, 0x01, 0x4F, 0xF0, 0xFF, 0xFF, 0x0D, 0xD0, 0xFF, 0xFE, 0xB0, 0x10, 0x00, 0x00,
199+
0x69, 0xB5, 0x00, 0x08, 0x0C, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD8, 0x1F, 0x00, 0x00, 0x00, 0x00,
200+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0D, 0xD0, 0x00, 0x00, 0xF2, 0x30, 0xFF, 0xFE, 0xB0,
201+
0x10, 0x00, 0x01, 0x4F, 0xF0, 0x00, 0x01, 0xE4, 0x60, 0x00, 0x02, 0x9F, 0xE0,
202+
];
203+
let hoop = read_hoop(&mut &data[..]).unwrap();
204+
eprintln!("{:?}", hoop);
205+
assert_eq!(
206+
hoop,
207+
Vp3Hoop {
208+
right: -62_000,
209+
left: 62_000,
210+
bottom: -86_000,
211+
top: 86_000,
212+
213+
unknown_a: 27061,
214+
unknown_b: 8,
215+
bytes_remaining: 55327,
216+
217+
x_offset: 0,
218+
y_offset: 0,
219+
220+
right2: -62_000,
221+
left2: 62_000,
222+
bottom2: -86_000,
223+
top2: 86_000,
224+
width: 124_000,
225+
height: 172_000,
226+
}
227+
);
228+
}
229+
230+
#[test]
231+
fn test_read_hoop_t42_1_vp3() {
232+
// T42-1.vp3 StartOffset(h): 00000049, EndOffset(h): 0000008B, Length(h): 00000043
233+
let data: [u8; 67] = [
234+
0x00, 0x01, 0x4F, 0xF0, 0x00, 0x01, 0x3C, 0x68, 0xFF, 0xFE, 0xB0, 0x10, 0xFF, 0xFE, 0xC3, 0x98, 0x00, 0x00,
235+
0x45, 0x71, 0x00, 0x01, 0x0C, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x8B, 0x9B, 0x00, 0x00, 0x00, 0x00,
236+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xB0, 0x10, 0x00, 0x01, 0x4F, 0xF0, 0xFF, 0xFE, 0xC3,
237+
0x98, 0x00, 0x01, 0x3C, 0x68, 0x00, 0x02, 0x9F, 0xE0, 0x00, 0x02, 0x78, 0xD0,
238+
];
239+
let hoop = read_hoop(&mut &data[..]).unwrap();
240+
eprintln!("{:?}", hoop);
241+
242+
assert_eq!(
243+
hoop,
244+
Vp3Hoop {
245+
right: -86_000,
246+
left: 86_000,
247+
bottom: -81_000,
248+
top: 81_000,
249+
250+
unknown_a: 17777,
251+
unknown_b: 1,
252+
bytes_remaining: 35739,
253+
254+
x_offset: 0,
255+
y_offset: 0,
256+
257+
right2: -86_000,
258+
left2: 86_000,
259+
bottom2: -81_000,
260+
top2: 81_000,
261+
width: 172_000,
262+
height: 162_000,
263+
}
264+
)
265+
}
266+
}

0 commit comments

Comments
 (0)