From a8f1573fbaf5dee9a52429d38b2d055bca482deb Mon Sep 17 00:00:00 2001 From: Dominik Strebel Date: Sat, 24 Oct 2026 14:29:30 +0200 Subject: [PATCH] fix(pptx): an object saved as its preview picture keeps the fallback picture's fill --- crates/pptx/src/write/shapes.rs | 6 +++++- crates/pptx/tests/it/ole.rs | 13 ++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/pptx/src/write/shapes.rs b/crates/pptx/src/write/shapes.rs index 5ef269f3..87200a89 100644 --- a/crates/pptx/src/write/shapes.rs +++ b/crates/pptx/src/write/shapes.rs @@ -909,8 +909,12 @@ fn shape_with_id(w: &mut W, x: &mut Exp, o: &mut Out, cx: &mut Ctx, s: &Shape, i w.empty0("p:nvPr"); w.close("p:nvPicPr"); dml::blip_fill(w, x, o, "p:blipFill", fill); + // As for any picture, a colour or pattern fill shows behind the image (an object's preview + // keeps its fallback picture's fill). let mut s2 = s.clone(); - s2.fill = None; + if matches!(s2.fill, Some(Fill::Picture(_) | Fill::Background | Fill::Group)) { + s2.fill = None; + } sp_pr(w, x, o, &s2, true); w.close("p:pic"); } else { diff --git a/crates/pptx/tests/it/ole.rs b/crates/pptx/tests/it/ole.rs index 1b0ef779..f24d0ac6 100644 --- a/crates/pptx/tests/it/ole.rs +++ b/crates/pptx/tests/it/ole.rs @@ -131,8 +131,19 @@ fn an_ole_objects_fallback_picture_gives_it_its_fill_and_outline() { r#""#, ))); let orange = deckcraft_model::style::Fill::solid(deckcraft_model::ColorRef::rgb(deckcraft_color::Rgba::rgb(0xFF, 0x99, 0))); - assert_eq!(filled.fill, Some(orange)); + assert_eq!(filled.fill, Some(orange.clone())); assert_eq!(filled.line.as_ref().and_then(|l| l.width), Some(1.0)); + // Saved as its preview picture (its kept XML can't be written back), it keeps the fill. + let mut p = deckcraft_pptx::import(&deck(pic(r#""#))).expect("import"); + for s in &mut std::sync::Arc::make_mut(&mut p.slides[0]).shapes { + if let ShapeKind::Opaque { xml, .. } = &mut s.kind { + xml.clear(); + } + } + let back = deckcraft_pptx::import(&deckcraft_pptx::export(&p).expect("export")).expect("reimport"); + let saved = back.slides[0].shapes.iter().find(|s| s.name == "Object 3").expect("object"); + assert!(matches!(saved.kind, ShapeKind::Picture { .. }), "{:?}", saved.kind); + assert_eq!(saved.fill, Some(orange)); // Without a fill of its own the object stays unfilled. assert_eq!(object(deck(pic(""))).fill, None); }