50 lines
2.1 KiB
Rust
50 lines
2.1 KiB
Rust
//! Writing for older readers: format v1's anchor form.
|
|
|
|
use serde_json::{Value, json};
|
|
|
|
/// Rewrite every anchor in a serialized document (`anchors` arrays of path data) the way format v1
|
|
/// wrote it: `{p: {x, y}, in: {x, y}, out: {x, y}, kind}`, every member present (v1 readers need
|
|
/// them all; v2 writes `{p: [x, y], in?, out?, kind?}`).
|
|
pub(crate) fn anchors_to_v1(v: &mut Value) {
|
|
match v {
|
|
Value::Object(o) => {
|
|
for (k, x) in o.iter_mut() {
|
|
match x {
|
|
Value::Array(anchors) if k == "anchors" => anchors.iter_mut().for_each(anchor_to_v1),
|
|
_ => anchors_to_v1(x),
|
|
}
|
|
}
|
|
}
|
|
Value::Array(a) => a.iter_mut().for_each(anchors_to_v1),
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
fn anchor_to_v1(a: &mut Value) {
|
|
let point = |v: &Value| match v.as_array().map(Vec::as_slice) {
|
|
Some([x, y]) => Some(json!({ "x": x, "y": y })),
|
|
_ => None,
|
|
};
|
|
let Some(o) = a.as_object() else { return };
|
|
// Not a v2 anchor (already a map, or something else called `anchors`): leave it alone.
|
|
let Some(p) = o.get("p").and_then(point) else { return };
|
|
let handle = |k: &str| o.get(k).and_then(point).unwrap_or_else(|| p.clone());
|
|
let kind = o.get("kind").cloned().unwrap_or_else(|| json!("Corner"));
|
|
*a = json!({ "p": p, "in": handle("in"), "out": handle("out"), "kind": kind });
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn anchors_are_written_the_v1_way() {
|
|
let mut v = json!({"layers": [{"path": {"subpaths": [{"anchors": [{"p": [1.0, 2.0]}, {"p": [3.0, 4.0], "out": [5.0, 4.0], "kind": "Smooth"}], "closed": true}]}}], "effect": {"anchors": true}});
|
|
anchors_to_v1(&mut v);
|
|
let a = &v["layers"][0]["path"]["subpaths"][0]["anchors"];
|
|
assert_eq!(a[0], json!({"p": {"x": 1.0, "y": 2.0}, "in": {"x": 1.0, "y": 2.0}, "out": {"x": 1.0, "y": 2.0}, "kind": "Corner"}));
|
|
assert_eq!(a[1], json!({"p": {"x": 3.0, "y": 4.0}, "in": {"x": 3.0, "y": 4.0}, "out": {"x": 5.0, "y": 4.0}, "kind": "Smooth"}));
|
|
assert_eq!(v["effect"]["anchors"], json!(true));
|
|
}
|
|
}
|