From 8aa76142c9e6729adfcd79a15861c05fc0de9c4c Mon Sep 17 00:00:00 2001 From: Leonardo Date: Fri, 23 Oct 2026 17:04:32 -0300 Subject: [PATCH] Render: a shape with no fill and no line draws no glow round its box A text box with a glow in its shape properties but no fill and no line got a blurred ring round the whole box; PowerPoint shows only the text's own glow. The glow of a frame with a line, and of a filled shape, is unchanged. Co-Authored-By: Claude Sonnet 5.5 --- ROADMAP.md | 1 + crates/render/src/lib.rs | 5 ++++- crates/render/src/tests.rs | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index 4268eec9..15f4199e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -131,6 +131,7 @@ app's JSON control channel (`deckcraft --control PORT`). | Date | What landed | |---|---| +| 2026-10-23 | A shape with no fill and no line (a text box) no longer draws its shape-level glow as a halo round its box; the text's own glow is all PowerPoint shows | | 2026-10-18 | Native chart sidecar bytes move from JSON arrays into referenced ZIP entries, with shared media byte/item limits and bounded reads; older inline sidecars still load. Synthetic format regressions cover large workbooks and malformed members | | 2026-10-18 | Slide thumbnails and the Slide Sorter render only the slides in view: on a deck of more than 600 slides they used to evict their own thumbnails, so the pane flashed white and never finished (#969) | | 2026-10-17 | Opening a file caps absurd effect sizes (glow, soft edges, shadows, reflections, on shapes, text and table text) at what Format Shape allows: a glow of 10^18 pt in a .pptx made rendering ask for 34 GB and abort | diff --git a/crates/render/src/lib.rs b/crates/render/src/lib.rs index cf124a9f..28df6567 100644 --- a/crates/render/src/lib.rs +++ b/crates/render/src/lib.rs @@ -1437,7 +1437,10 @@ impl Renderer { } ctx.pop_layer(); } - if let Some(g) = &e.glow { + // A shape with no fill and no line (a text box) draws nothing to glow around: its text's + // own glow is all PowerPoint shows, not a halo round the box. + let glows = fill_alpha.is_some() || content.is_some() || outline.is_some(); + if let Some(g) = e.glow.as_ref().filter(|_| glows) { let c = rctx.color(&g.color, ph); ctx.set_transform(Affine::IDENTITY); // Measured on PowerPoint's export: a glow of radius r is half strength about half of r diff --git a/crates/render/src/tests.rs b/crates/render/src/tests.rs index 4ee1c889..e0ca08fe 100644 --- a/crates/render/src/tests.rs +++ b/crates/render/src/tests.rs @@ -431,6 +431,22 @@ fn glow_of_an_unfilled_shape_follows_its_line() { assert!(img.pixel(300, 94)[0] < 240); } +#[test] +fn glow_of_a_shape_with_no_fill_and_no_line_is_not_drawn() { + // A text box (no fill, no line) with a glow in its shape properties: PowerPoint shows no halo + // round the box (its text carries its own glow), so the box's edge and surroundings stay white. + let mut sh = Shape { id: ShapeId(611), xfrm: Some(Xfrm::new(100.0, 100.0, 400.0, 300.0)), fill: Some(Fill::None), ..Default::default() }; + sh.effects = Some(deckcraft_model::Effects { + glow: Some(deckcraft_model::style::Glow { color: ColorRef::rgb(deckcraft_color::Rgba::rgb(255, 255, 0)), radius: 15.0 }), + ..Default::default() + }); + let img = render_slide(&deck_with(vec![sh]), 0, &RenderOpts { scale: 1.0, ..Default::default() }); + for (x, y) in [(300, 250), (300, 100), (300, 95), (96, 250)] { + let px = img.pixel(x, y); + assert!(px[2] > 245, "({x}, {y}): {px:?}"); + } +} + #[test] fn placeholder_prompts_only_in_edit_view() { let p = Presentation::default();