mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-05 18:18:49 +00:00
commit
072db0ca35
3 files changed
+33
-4
No files matched your search
@@ -316,7 +316,8 @@ fn masks(im: &Im, ids: &mut Ids, list: &[Json], g: &mut PropGroup) {
|
||||
import_prop(im, j, p, conv);
|
||||
}
|
||||
};
|
||||
set("pt", "path", &shapes::to_path);
|
||||
let closed = m.get("cl").and_then(Json::as_bool).unwrap_or(false);
|
||||
set("pt", "path", &|v| shapes::to_path(v, closed));
|
||||
set("o", "opacity", &anim::to_scalar);
|
||||
set("x", "expansion", &anim::to_scalar);
|
||||
set("f", "feather", &anim::to_vec2);
|
||||
|
||||
@@ -27,7 +27,9 @@ pub(crate) fn path_value(v: &Value) -> Json {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_path(j: &Json) -> Option<Value> {
|
||||
/// A Lottie path. `closed` is used when the path has no `c`: Bodymovin 3.x and early 4.x keep the
|
||||
/// flag outside the path, as `cl` on a mask and `closed` on an `sh` item.
|
||||
pub(crate) fn to_path(j: &Json, closed: bool) -> Option<Value> {
|
||||
let o = match j {
|
||||
Json::Array(a) => a.first()?,
|
||||
o => o,
|
||||
@@ -48,7 +50,7 @@ pub(crate) fn to_path(j: &Json) -> Option<Value> {
|
||||
in_tangents: fit(pts("i")),
|
||||
out_tangents: fit(pts("o")),
|
||||
vertices,
|
||||
closed: o.get("c").and_then(Json::as_bool).unwrap_or(false),
|
||||
closed: o.get("c").and_then(Json::as_bool).unwrap_or(closed),
|
||||
feather: Vec::new(),
|
||||
}))
|
||||
}
|
||||
@@ -493,7 +495,8 @@ pub(crate) fn import_items(im: &mut Im, ids: &mut Ids, items: &[Json]) -> Vec<Pr
|
||||
"sh" => {
|
||||
let mut g = build::shape_path(ids, ShapePath::default());
|
||||
dir(&mut g);
|
||||
set(im, &mut g, "path", j.get("ks"), &to_path);
|
||||
let closed = j.get("closed").and_then(Json::as_bool).unwrap_or(false);
|
||||
set(im, &mut g, "path", j.get("ks"), &|v| to_path(v, closed));
|
||||
g
|
||||
}
|
||||
"fl" => {
|
||||
|
||||
@@ -533,6 +533,31 @@ fn embedded_glyphs_are_reported_when_dropped() {
|
||||
assert_eq!(warnings(&blank), ["embedded glyphs (`chars`) are not imported; text uses the installed fonts"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn legacy_closed_flags_close_masks_and_paths() {
|
||||
// Bodymovin 3.x and early 4.x put the closed flag on the mask (`cl`) and on the `sh` item
|
||||
// (`closed`), with no `c` in the path. An open mask would leave the solid whole.
|
||||
let square = json!({"i": [[0, 0], [0, 0], [0, 0], [0, 0]], "o": [[0, 0], [0, 0], [0, 0], [0, 0]], "v": [[5, 5], [15, 5], [15, 15], [5, 15]]});
|
||||
let doc = json!({"w": 20, "h": 20, "fr": 30, "ip": 0, "op": 30, "assets": [], "layers": [
|
||||
{"ty": 4, "ind": 1, "ip": 0, "op": 30, "st": 0, "ks": {},
|
||||
"shapes": [{"ty": "sh", "closed": true, "ks": {"k": [{"t": 0, "s": [square], "e": [square]}, {"t": 10}]}}]},
|
||||
{"ty": 1, "ind": 2, "sc": "#ff0000", "sw": 20, "sh": 20, "ip": 0, "op": 30, "st": 0, "ks": {},
|
||||
"masksProperties": [{"mode": "a", "cl": true, "pt": {"k": square}}]}]});
|
||||
let mut q = Project::default();
|
||||
let nc = import(&mut q, doc.to_string().as_bytes(), "Imported", "", &mut |_| None).unwrap().comp;
|
||||
let comp = q.comp(nc).unwrap();
|
||||
let closed = |v: &Value| matches!(v, Value::Path(sp) if sp.closed);
|
||||
let shape = comp.layers[0].props.sub("contents").unwrap().groups().next().unwrap();
|
||||
let keys = &shape.get("path").unwrap().keys;
|
||||
assert_eq!(keys.len(), 2);
|
||||
assert!(keys.iter().all(|k| closed(&k.value)));
|
||||
let mask = comp.layers[1].masks().unwrap().groups().next().unwrap();
|
||||
assert!(closed(&mask.get("path").unwrap().value));
|
||||
let img = render_frame(&q, nc, s(0.0), 1.0);
|
||||
assert_eq!(img.data[0][3], 0.0, "the mask cuts the corner away");
|
||||
assert!(img.data[10 * 20 + 10][3] > 0.99);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn precomp_with_time_remap() {
|
||||
let (mut p, cid) = setup();
|
||||
|
||||
Reference in new issue
Block a user