From 5688294d5603a45ec7f7d0f2794d0563503c3c4e Mon Sep 17 00:00:00 2001 From: bflatastic Date: Wed, 14 Oct 2026 08:48:39 +0700 Subject: [PATCH] Fix #1683: a template layer dims its images by Dim Images, not the whole layer The canvas faded a template layer as a whole by a fixed half and ignored its Dim Images option, so unchecking it or setting another percentage changed nothing, and the layer's paths were faded with its images. A template layer's images are now dimmed to its Dim Images percentage (50 % when Layer Options makes it a template), shown at full strength with the option off, and its vector art is drawn as it is. --- crates/render/src/lib.rs | 12 ++++++------ crates/render/src/tests_layeropts.rs | 28 ++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/crates/render/src/lib.rs b/crates/render/src/lib.rs index d293c6f8..a5676805 100644 --- a/crates/render/src/lib.rs +++ b/crates/render/src/lib.rs @@ -83,7 +83,8 @@ pub struct RenderOptions { pub artboards: bool, /// Objects not to draw (e.g. the object being edited by a live drag preview). pub hidden: Vec, - /// Draw template layers dimmed (50%). + /// Draw the layers as their Layer Options show them on screen: Preview off in outline, Dim + /// Images fading their images (a template layer's too), a template in Preview in Outline view. pub dim_templates: bool, /// Soft proof / separations preview (see [`proof`]). pub proof: Option, @@ -1088,8 +1089,8 @@ impl Renderer { return; } // Layer Options on screen: a layer whose Preview is off draws in outline, and Dim Images - // fades its images (exports and thumbnails, which leave templates out, ignore both). - // (A template is dimmed as a whole already.) + // fades its images, a template's too (exports and thumbnails, which leave templates out, + // ignore both). if let NodeKind::Layer { preview, dim_images, template, .. } = &n.kind && f.opts.dim_templates && !f.opts.skip_templates @@ -1104,7 +1105,7 @@ impl Renderer { let opts = RenderOptions { outline: true, ..f.opts.clone() }; return self.draw_node(ctx, &Frame { opts: &opts, ..*f }, n, force); } - if let Some(p) = dim_images.filter(|_| !template) { + if let Some(p) = *dim_images { let outer = self.dim_images; let dim = f32::from(p).clamp(0.0, 100.0) / 100.0; self.dim_images = Some(outer.map_or(dim, |o| o.min(dim))); @@ -1162,8 +1163,7 @@ impl Renderer { return self.draw_object_fx(ctx, f, &Arc::new(n.clone()), false); } let outline = f.opts.outline; - let template_dim = matches!(n.kind, NodeKind::Layer { template: true, .. }) && f.opts.dim_templates; - let opacity = if template_dim { self.opacity_of(n) * 0.5 } else { self.opacity_of(n) }; + let opacity = self.opacity_of(n); // Whether this container's children knock each other out. let knockout = !outline && n.knocks_out(self.knockout); let enclosing = std::mem::replace(&mut self.knockout, knockout); diff --git a/crates/render/src/tests_layeropts.rs b/crates/render/src/tests_layeropts.rs index a2864cc6..12aa36cf 100644 --- a/crates/render/src/tests_layeropts.rs +++ b/crates/render/src/tests_layeropts.rs @@ -67,13 +67,37 @@ fn dim_images_fades_only_the_images() { assert_eq!(render(&d, true).pixel(65, 25), [255, 0, 0, 255], "exports are not dimmed"); } +/// #1683: a template layer dims its images by its Dim Images percentage and nothing else: with +/// the option off they show at full strength, and the layer's paths are never faded. +#[test] +fn a_template_layer_dims_its_images_by_dim_images() { + let template = |dim: Option| { + let d = doc(|k| { + if let NodeKind::Layer { template, dim_images, .. } = k { + (*template, *dim_images) = (true, dim); + } + }); + let img = render(&d, false); + (img.pixel(65, 25), img.pixel(25, 25)) + }; + let red = [255, 0, 0, 255]; + assert_eq!(template(None), (red, red), "Dim Images off: as it is"); + let (image, path) = template(Some(50)); + assert!(image[0] == 255 && (120..=135).contains(&image[1]) && image[1] == image[2], "half way to white: {image:?}"); + assert_eq!(path, red, "vector art stays"); + let (image, _) = template(Some(20)); + assert!((198..=210).contains(&image[1]) && image[1] == image[2], "a fifth of its strength: {image:?}"); + assert_eq!(template(Some(100)), (red, red)); +} + /// In Outline view a template layer still draws in Preview, dimmed, so its picture can be traced; /// the layer above it draws in outline (#1486). #[test] fn a_template_layer_stays_in_preview_in_outline_view() { let mut d = doc(|k| { - if let NodeKind::Layer { template, preview, .. } = k { - *template = true; + if let NodeKind::Layer { template, preview, dim_images, .. } = k { + // As Layer Options makes a template: its images dimmed to 50 %. + (*template, *dim_images) = (true, Some(50)); // Preview off doesn't put a template in outline either. *preview = false; }