fix(render): animation state never applies to layout and master shapes sharing a slide shape id (fixes #1362)

This commit is contained in:
Harrison Booth committed 2026-10-26 18:20:19 -05:00
1 parent 27009cd941
commit 8c8ab9561b
2 files changed
+27 -4

No files matched your search

+7 -4
View File
@@ -267,6 +267,7 @@ impl Default for RenderOpts<'_> {
}
}
#[derive(Clone)]
struct SlideFields {
num: u32,
/// Text for every date field instead of the date ([`RenderOpts::date_text`]).
@@ -667,6 +668,10 @@ impl Renderer {
/// Background plus the master and layout graphics the slide shows.
fn backdrop(&mut self, ctx: &mut RenderContext, f: &Frame, rctx: &Ctx, slide: &Slide, view: Affine) {
// Backdrop graphics never take shape states: their ids may clash with the slide's shapes.
let bopts = RenderOpts { state: None, date_text: f.opts.date_text.clone(), ..*f.opts };
let bf = Frame { pres: f.pres, opts: &bopts, fields: f.fields.clone() };
let f = &bf;
self.background(ctx, f, rctx, Some(slide), view);
let (show_layout, show_master) = resolve::show_master_shapes(slide, rctx.layout);
if show_master {
@@ -742,14 +747,12 @@ impl Renderer {
self.in_shadow_pass = false;
let (mut ctx, w, h, view) = Self::canvas(pres, opts, needs_filters(pres, old.0) || needs_filters(pres, new.0));
let (Some(co), Some(cn)) = (Ctx::for_slide(pres, old.0), Ctx::for_slide(pres, new.0)) else { return self.finish(ctx, w, h) };
// Backdrop graphics never take shape states: their ids may clash with the frame's shapes.
let bopts = RenderOpts { state: None, date_text: opts.date_text.clone(), ..*opts };
if mix < 1.0 {
let f = Frame { pres, opts: &bopts, fields: Self::fields(pres, old.1, opts) };
let f = Frame { pres, opts, fields: Self::fields(pres, old.1, opts) };
self.backdrop(&mut ctx, &f, &co, old.0, view);
}
if mix > 0.0 {
let f = Frame { pres, opts: &bopts, fields: Self::fields(pres, new.1, opts) };
let f = Frame { pres, opts, fields: Self::fields(pres, new.1, opts) };
let layered = mix < 1.0;
if layered {
ctx.push_layer(None, None, Some(mix as f32), None, None);
+20
View File
@@ -1776,6 +1776,26 @@ fn the_editor_pasteboard_draws_shapes_off_the_slide() {
assert!(drawn.x0 <= -100.0 && drawn.y1 >= 660.0 && drawn.x1 >= 960.0, "{drawn:?}");
}
#[test]
fn animation_state_skips_layout_and_master_shapes_sharing_a_slide_shape_id() {
let mut p = Presentation::default();
let bar = |x| Shape {
id: ShapeId(77),
xfrm: Some(Xfrm::new(x, 400.0, 100.0, 60.0)),
fill: Some(Fill::solid(ColorRef::rgb(Rgba::rgb(200, 0, 0)))),
..Default::default()
};
let lid = p.slides[0].layout;
let m = std::sync::Arc::make_mut(&mut p.masters[0]);
m.shapes.push(bar(100.0));
m.layouts.iter_mut().find(|l| l.id == lid).expect("layout").shapes.push(bar(400.0));
let hide = |_: ShapeId| ShapeState { visible: false, ..Default::default() };
let img = render_slide(&p, 0, &RenderOpts { scale: 1.0, state: Some(&hide), ..Default::default() });
for x in [150, 450] {
assert_eq!(img.pixel(x, 430)[..3], [200, 0, 0], "the backdrop bar at x={x} stays");
}
}
#[test]
fn master_graphics_off_the_slide_show_on_the_pasteboard() {
let mut p = Presentation::default();