mirror of
https://github.com/storytold/cadcraft.git
synced 2026-11-10 20:40:30 -06:00
OLE2FRAME: MOVE rewrites the corners in the OLE data only when they are the frame's corners (review on #2587)
The data layout is only known when its corners match the frame's groups; any other header is left byte-identical while the tags still move. Test: move_leaves_ole_data_that_is_not_the_frames_corners_alone.
This commit is contained in:
@@ -51,7 +51,7 @@ const OLE_CORNERS: usize = 12;
|
||||
|
||||
/// Move the four corners at the start of the OLE data (the 310 groups' hex, in order) by `m`,
|
||||
/// keeping z and every tag's length. Data that is not valid hex or is too short is left alone.
|
||||
fn ole_data_transform(tags: &mut [crate::RawTag], m: &cadcraft_geom::Mat3) {
|
||||
fn ole_data_transform(tags: &mut [crate::RawTag], m: &cadcraft_geom::Mat3, frame: [f64; 4]) {
|
||||
let idx: Vec<usize> = outside_app(tags).into_iter().filter(|&i| tags.get(i).is_some_and(|t| t.code == 310)).collect();
|
||||
let mut bytes: Vec<u8> = Vec::new();
|
||||
let mut lens: Vec<usize> = Vec::new();
|
||||
@@ -71,6 +71,19 @@ fn ole_data_transform(tags: &mut [crate::RawTag], m: &cadcraft_geom::Mat3) {
|
||||
if bytes.len() < end {
|
||||
return;
|
||||
}
|
||||
// Only data whose corners are this frame's corners (UL, UR, LR, LL) has the layout above; any
|
||||
// other header is not ours to rewrite.
|
||||
let [x1, y1, x2, y2] = frame;
|
||||
let want = [(x1, y1), (x2, y1), (x2, y2), (x1, y2)];
|
||||
let near = |a: f64, b: f64| (a - b).abs() <= 1e-9 * a.abs().max(b.abs()).max(1.0);
|
||||
for (c, (wx, wy)) in want.iter().enumerate() {
|
||||
let at = OLE_HEADER + c * 24;
|
||||
let rd = |o: usize| bytes.get(o..o + 8).and_then(|s| <[u8; 8]>::try_from(s).ok()).map(f64::from_le_bytes);
|
||||
let (Some(x), Some(y)) = (rd(at), rd(at + 8)) else { return };
|
||||
if !(near(x, *wx) && near(y, *wy)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let mut out = bytes.clone();
|
||||
for c in 0..4 {
|
||||
let at = OLE_HEADER + c * 24;
|
||||
@@ -103,6 +116,7 @@ fn ole_data_transform(tags: &mut [crate::RawTag], m: &cadcraft_geom::Mat3) {
|
||||
/// left alone.
|
||||
pub fn ole_frame_transform(tags: &mut [crate::RawTag], m: &cadcraft_geom::Mat3) {
|
||||
let Some([(ix1, x1), (iy1, y1), (ix2, x2), (iy2, y2)]) = ole_corner_groups(tags) else { return };
|
||||
let frame = [x1, y1, x2, y2];
|
||||
let (a, b) = (m.apply(Vec2::new(x1, y1)), m.apply(Vec2::new(x2, y2)));
|
||||
if !(a.x.is_finite() && a.y.is_finite() && b.x.is_finite() && b.y.is_finite()) {
|
||||
return;
|
||||
@@ -112,7 +126,7 @@ pub fn ole_frame_transform(tags: &mut [crate::RawTag], m: &cadcraft_geom::Mat3)
|
||||
t.value = v.to_string();
|
||||
}
|
||||
}
|
||||
ole_data_transform(tags, m);
|
||||
ole_data_transform(tags, m, frame);
|
||||
}
|
||||
|
||||
/// Whether `m` can move an OLE2FRAME: only a translation (move, copy, stretch of the whole frame).
|
||||
|
||||
@@ -124,3 +124,21 @@ fn move_leaves_malformed_or_short_ole_data_alone() {
|
||||
assert_eq!(corners(&s)[0].1, "40", "the corner groups still move");
|
||||
}
|
||||
}
|
||||
|
||||
/// OLE data whose bytes are not this frame's corners (an unknown header, so the layout does not
|
||||
/// apply) is not rewritten by MOVE; the frame's own corner groups still move (review on #2587).
|
||||
#[test]
|
||||
fn move_leaves_ole_data_that_is_not_the_frames_corners_alone() {
|
||||
let mut blob = vec![9u8, 9];
|
||||
for (x, y) in [(1.0f64, 2.0f64), (3.0, 2.0), (3.0, 4.0), (1.0, 4.0)] {
|
||||
for v in [x, y, 7.0] {
|
||||
blob.extend_from_slice(&v.to_le_bytes());
|
||||
}
|
||||
}
|
||||
let hex: String = blob.iter().map(|b| format!("{b:02X}")).collect();
|
||||
let (mut s, h) = data_session(&[40, 100], Some(&hex));
|
||||
let before = data_tags(&s);
|
||||
s.execute("move", &json!({ "handles": [h], "delta": [10, 5] })).unwrap();
|
||||
assert_eq!(data_tags(&s), before);
|
||||
assert_eq!(corners(&s)[0].1, "40", "the corner groups still move");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user