fixed bug with color layering issue
This commit is contained in:
@@ -77,16 +77,36 @@ pub fn parse(data: &[u8]) -> Result<Vec<StitchCommand>, Error> {
|
||||
/// Standard bit layout for dx across bytes b0, b1, b2.
|
||||
fn decode_dx(b0: u8, b1: u8, b2: u8) -> i16 {
|
||||
let mut x: i16 = 0;
|
||||
if b0 & 0x01 != 0 { x += 1; }
|
||||
if b0 & 0x02 != 0 { x -= 1; }
|
||||
if b0 & 0x04 != 0 { x += 9; }
|
||||
if b0 & 0x08 != 0 { x -= 9; }
|
||||
if b1 & 0x01 != 0 { x += 3; }
|
||||
if b1 & 0x02 != 0 { x -= 3; }
|
||||
if b1 & 0x04 != 0 { x += 27; }
|
||||
if b1 & 0x08 != 0 { x -= 27; }
|
||||
if b2 & 0x04 != 0 { x += 81; }
|
||||
if b2 & 0x08 != 0 { x -= 81; }
|
||||
if b0 & 0x01 != 0 {
|
||||
x += 1;
|
||||
}
|
||||
if b0 & 0x02 != 0 {
|
||||
x -= 1;
|
||||
}
|
||||
if b0 & 0x04 != 0 {
|
||||
x += 9;
|
||||
}
|
||||
if b0 & 0x08 != 0 {
|
||||
x -= 9;
|
||||
}
|
||||
if b1 & 0x01 != 0 {
|
||||
x += 3;
|
||||
}
|
||||
if b1 & 0x02 != 0 {
|
||||
x -= 3;
|
||||
}
|
||||
if b1 & 0x04 != 0 {
|
||||
x += 27;
|
||||
}
|
||||
if b1 & 0x08 != 0 {
|
||||
x -= 27;
|
||||
}
|
||||
if b2 & 0x04 != 0 {
|
||||
x += 81;
|
||||
}
|
||||
if b2 & 0x08 != 0 {
|
||||
x -= 81;
|
||||
}
|
||||
x
|
||||
}
|
||||
|
||||
@@ -94,16 +114,36 @@ fn decode_dx(b0: u8, b1: u8, b2: u8) -> i16 {
|
||||
/// Standard bit layout for dy across bytes b0, b1, b2.
|
||||
fn decode_dy(b0: u8, b1: u8, b2: u8) -> i16 {
|
||||
let mut y: i16 = 0;
|
||||
if b0 & 0x80 != 0 { y += 1; }
|
||||
if b0 & 0x40 != 0 { y -= 1; }
|
||||
if b0 & 0x20 != 0 { y += 9; }
|
||||
if b0 & 0x10 != 0 { y -= 9; }
|
||||
if b1 & 0x80 != 0 { y += 3; }
|
||||
if b1 & 0x40 != 0 { y -= 3; }
|
||||
if b1 & 0x20 != 0 { y += 27; }
|
||||
if b1 & 0x10 != 0 { y -= 27; }
|
||||
if b2 & 0x20 != 0 { y += 81; }
|
||||
if b2 & 0x10 != 0 { y -= 81; }
|
||||
if b0 & 0x80 != 0 {
|
||||
y += 1;
|
||||
}
|
||||
if b0 & 0x40 != 0 {
|
||||
y -= 1;
|
||||
}
|
||||
if b0 & 0x20 != 0 {
|
||||
y += 9;
|
||||
}
|
||||
if b0 & 0x10 != 0 {
|
||||
y -= 9;
|
||||
}
|
||||
if b1 & 0x80 != 0 {
|
||||
y += 3;
|
||||
}
|
||||
if b1 & 0x40 != 0 {
|
||||
y -= 3;
|
||||
}
|
||||
if b1 & 0x20 != 0 {
|
||||
y += 27;
|
||||
}
|
||||
if b1 & 0x10 != 0 {
|
||||
y -= 27;
|
||||
}
|
||||
if b2 & 0x20 != 0 {
|
||||
y += 81;
|
||||
}
|
||||
if b2 & 0x10 != 0 {
|
||||
y -= 81;
|
||||
}
|
||||
// DST Y axis is inverted (positive = up in machine coords, down in screen coords)
|
||||
-y
|
||||
}
|
||||
@@ -166,7 +206,7 @@ mod tests {
|
||||
assert_eq!(decode_dx(0x04, 0x00, 0x00), 9);
|
||||
assert_eq!(decode_dx(0x00, 0x04, 0x00), 27);
|
||||
assert_eq!(decode_dx(0x00, 0x00, 0x04), 81);
|
||||
assert_eq!(decode_dx(0x05, 0x05, 0x04), 1 + 9 + 27 + 81); // 118
|
||||
assert_eq!(decode_dx(0x05, 0x05, 0x04), 1 + 9 + 3 + 27 + 81); // 121
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -88,10 +88,7 @@ mod tests {
|
||||
fn parse_simple_stitches() {
|
||||
let data = [0x0A, 0x14, 0x05, 0x03];
|
||||
let cmds = parse(&data).unwrap();
|
||||
assert!(matches!(
|
||||
cmds[0],
|
||||
StitchCommand::Stitch { dx: 10, dy: 20 }
|
||||
));
|
||||
assert!(matches!(cmds[0], StitchCommand::Stitch { dx: 10, dy: 20 }));
|
||||
assert!(matches!(cmds[1], StitchCommand::Stitch { dx: 5, dy: 3 }));
|
||||
assert!(matches!(cmds[2], StitchCommand::End));
|
||||
}
|
||||
@@ -120,10 +117,7 @@ mod tests {
|
||||
fn parse_jump() {
|
||||
let data = [0x80, 0x04, 0x0A, 0x14];
|
||||
let cmds = parse(&data).unwrap();
|
||||
assert!(matches!(
|
||||
cmds[0],
|
||||
StitchCommand::Jump { dx: 10, dy: 20 }
|
||||
));
|
||||
assert!(matches!(cmds[0], StitchCommand::Jump { dx: 10, dy: 20 }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -15,7 +15,9 @@ use palette::JEF_PALETTE;
|
||||
///
|
||||
/// Stitch data: 2 bytes per stitch (signed i8 dx, dy).
|
||||
/// Control codes: 0x80 0x01 = color change, 0x80 0x02 = jump, 0x80 0x10 = end.
|
||||
pub fn parse(data: &[u8]) -> Result<(Vec<StitchCommand>, Vec<(u8, u8, u8)>), Error> {
|
||||
type ParseResult = Result<(Vec<StitchCommand>, Vec<(u8, u8, u8)>), Error>;
|
||||
|
||||
pub fn parse(data: &[u8]) -> ParseResult {
|
||||
if data.len() < 116 {
|
||||
return Err(Error::TooShort {
|
||||
expected: 116,
|
||||
@@ -146,10 +148,7 @@ mod tests {
|
||||
fn decode_simple_stitches() {
|
||||
let data = [0x0A, 0x14, 0x05, 0x03, 0x80, 0x10];
|
||||
let cmds = decode_stitches(&data).unwrap();
|
||||
assert!(matches!(
|
||||
cmds[0],
|
||||
StitchCommand::Stitch { dx: 10, dy: -20 }
|
||||
));
|
||||
assert!(matches!(cmds[0], StitchCommand::Stitch { dx: 10, dy: -20 }));
|
||||
assert!(matches!(cmds[1], StitchCommand::Stitch { dx: 5, dy: -3 }));
|
||||
assert!(matches!(cmds[2], StitchCommand::End));
|
||||
}
|
||||
@@ -165,9 +164,6 @@ mod tests {
|
||||
fn decode_jump() {
|
||||
let data = [0x80, 0x02, 0x0A, 0x14, 0x80, 0x10];
|
||||
let cmds = decode_stitches(&data).unwrap();
|
||||
assert!(matches!(
|
||||
cmds[0],
|
||||
StitchCommand::Jump { dx: 10, dy: -20 }
|
||||
));
|
||||
assert!(matches!(cmds[0], StitchCommand::Jump { dx: 10, dy: -20 }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,11 @@ pub mod format;
|
||||
pub mod palette;
|
||||
pub mod types;
|
||||
|
||||
pub mod dst;
|
||||
pub mod exp;
|
||||
pub mod jef;
|
||||
pub mod pes;
|
||||
pub mod vp3;
|
||||
|
||||
mod render;
|
||||
mod resolve;
|
||||
@@ -32,6 +36,9 @@ fn parse_and_resolve(data: &[u8], fmt: Format) -> Result<ResolvedDesign, Error>
|
||||
let design = pes::parse(data)?;
|
||||
pes::resolve(&design)
|
||||
}
|
||||
_ => Err(Error::UnsupportedFormat),
|
||||
Format::Dst => dst::parse_and_resolve(data),
|
||||
Format::Exp => exp::parse_and_resolve(data),
|
||||
Format::Jef => jef::parse_and_resolve(data),
|
||||
Format::Vp3 => vp3::parse_and_resolve(data),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,19 @@ pub fn decode_stitches(data: &[u8]) -> Result<Vec<StitchCommand>, Error> {
|
||||
let (dx, dx_flags, bytes_dx) = decode_coordinate(data, i)?;
|
||||
i += bytes_dx;
|
||||
|
||||
// Check for special bytes at dy position — color change or end markers
|
||||
// can appear between dx and dy when the preceding stitch ends on an
|
||||
// odd byte boundary relative to the next control byte.
|
||||
if i < data.len() && data[i] == 0xFF {
|
||||
commands.push(StitchCommand::End);
|
||||
break;
|
||||
}
|
||||
if i < data.len() && data[i] == 0xFE {
|
||||
commands.push(StitchCommand::ColorChange);
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
let (dy, dy_flags, bytes_dy) = decode_coordinate(data, i)?;
|
||||
i += bytes_dy;
|
||||
|
||||
|
||||
@@ -12,7 +12,9 @@ use crate::types::{ResolvedDesign, StitchCommand};
|
||||
///
|
||||
/// Byte order: mixed, but length-prefixed strings and section sizes use big-endian.
|
||||
/// Stitch encoding: variable-length (1 byte for small moves, 3 bytes for large).
|
||||
pub fn parse(data: &[u8]) -> Result<(Vec<StitchCommand>, Vec<(u8, u8, u8)>), Error> {
|
||||
type ParseResult = Result<(Vec<StitchCommand>, Vec<(u8, u8, u8)>), Error>;
|
||||
|
||||
pub fn parse(data: &[u8]) -> ParseResult {
|
||||
if data.len() < 20 {
|
||||
return Err(Error::TooShort {
|
||||
expected: 20,
|
||||
@@ -93,10 +95,11 @@ fn skip_vp3_header(reader: &mut Reader) -> Result<(), Error> {
|
||||
// Skip another potential string
|
||||
if reader.remaining() >= 2 {
|
||||
let peek = reader.peek_u16_be();
|
||||
if let Ok(len) = peek {
|
||||
if len < 1000 && (len as usize) + 2 <= reader.remaining() {
|
||||
skip_string(reader)?;
|
||||
}
|
||||
if let Ok(len) = peek
|
||||
&& len < 1000
|
||||
&& (len as usize) + 2 <= reader.remaining()
|
||||
{
|
||||
skip_string(reader)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user