Lerp between two graphics. Solid color and gradient pairings interpolate; all other pairings step at the midpoint.
(a: Option<&List<Graphic>>, b: Option<&List<Graphic>>, time: f64)
| 2308 | |
| 2309 | // Lerp between two graphics. Solid color and gradient pairings interpolate; all other pairings step at the midpoint. |
| 2310 | fn lerp_graphic(a: Option<&List<Graphic>>, b: Option<&List<Graphic>>, time: f64) -> Option<List<Graphic>> { |
| 2311 | let transparent = List::new_from_element(Color::TRANSPARENT).into_graphic_list(); |
| 2312 | |
| 2313 | let a = a.filter(|graphic_list| is_paint_present(graphic_list)); |
| 2314 | let b = b.filter(|graphic_list| is_paint_present(graphic_list)); |
| 2315 | |
| 2316 | let (a, b) = match (a, b) { |
| 2317 | (None, None) => return None, |
| 2318 | (Some(a), None) => (a, &transparent), |
| 2319 | (None, Some(b)) => (&transparent, b), |
| 2320 | (Some(a), Some(b)) => (a, b), |
| 2321 | }; |
| 2322 | |
| 2323 | // This keeps the gradient metadata attributes |
| 2324 | let gradient_with_stops = |mut gradient_list: List<GradientStops>, stops: GradientStops| -> Graphic { |
| 2325 | if let Some(target) = gradient_list.element_mut(0) { |
| 2326 | *target = stops; |
| 2327 | } else { |
| 2328 | gradient_list.push(Item::new_from_element(stops)); |
| 2329 | } |
| 2330 | Graphic::Gradient(gradient_list) |
| 2331 | }; |
| 2332 | |
| 2333 | let graphic = match (a.element(0), b.element(0)) { |
| 2334 | (Some(Graphic::Color(color_list_a)), Some(Graphic::Color(color_list_b))) => color_list_a |
| 2335 | .element(0) |
| 2336 | .zip(color_list_b.element(0)) |
| 2337 | .map(|(color_a, color_b)| Graphic::from(color_a.lerp(color_b, time as f32))), |
| 2338 | (Some(Graphic::Color(color_list_a)), Some(Graphic::Gradient(gradient_list_b))) => color_list_a.element(0).zip(gradient_list_b.element(0)).map(|(color_a, stops_b)| { |
| 2339 | let mut solid_to_gradient = stops_b.clone(); |
| 2340 | solid_to_gradient.color.iter_mut().for_each(|color| *color = *color_a); |
| 2341 | let stops = solid_to_gradient.lerp(stops_b, time); |
| 2342 | gradient_with_stops(gradient_list_b.clone(), stops) |
| 2343 | }), |
| 2344 | (Some(Graphic::Gradient(gradient_list_a)), Some(Graphic::Color(color_list_b))) => gradient_list_a.element(0).zip(color_list_b.element(0)).map(|(stops_a, color_b)| { |
| 2345 | let mut gradient_to_solid = stops_a.clone(); |
| 2346 | gradient_to_solid.color.iter_mut().for_each(|color| *color = *color_b); |
| 2347 | let stops = stops_a.lerp(&gradient_to_solid, time); |
| 2348 | gradient_with_stops(gradient_list_a.clone(), stops) |
| 2349 | }), |
| 2350 | (Some(Graphic::Gradient(gradient_list_a)), Some(Graphic::Gradient(gradient_list_b))) => gradient_list_a.element(0).zip(gradient_list_b.element(0)).map(|(stops_a, stops_b)| { |
| 2351 | let stops = stops_a.lerp(stops_b, time); |
| 2352 | let metadata_source = if time < 0.5 { gradient_list_a } else { gradient_list_b }; |
| 2353 | |
| 2354 | let mut gradient_list = metadata_source.clone(); |
| 2355 | gradient_list.set_attribute(ATTR_TRANSFORM, 0, lerp_gradient_transform(gradient_list_a, gradient_list_b, time)); |
| 2356 | |
| 2357 | gradient_with_stops(gradient_list, stops) |
| 2358 | }), |
| 2359 | // Pairings beyond solid colors and gradients (raster, vector, or mixed) can't be interpolated, so step at the midpoint |
| 2360 | _ => return Some(if time < 0.5 { a.clone() } else { b.clone() }), |
| 2361 | }; |
| 2362 | |
| 2363 | graphic.map(List::new_from_element) |
| 2364 | } |
| 2365 | |
| 2366 | // Preserve original `List<Graphic>` as upstream data so this group layer's nested layers can be edited by the tools. |
| 2367 | let mut graphic_list_content = content.clone().into_graphic_list(); |
no test coverage detected