Skip complex layer thumbnails

This commit is contained in:
hypercube 2025-07-04 22:33:02 +01:00
parent 354a68911e
commit 30e9b3c5fd
6 changed files with 77 additions and 4 deletions

View file

@ -328,6 +328,19 @@ impl NodeRuntime {
return;
}
// Skip thumbnails if the layer is too complex (for performance)
if graphic_element.render_complexity() > 1000 {
let old = thumbnail_renders.insert(parent_network_node_id, Vec::new());
if old.is_none_or(|v| !v.is_empty()) {
responses.push_back(FrontendMessage::UpdateNodeThumbnail {
id: parent_network_node_id,
value: "<svg viewBox=\"0 -10 10 10\"><title>Layer too complex for thumbnail</title><text>\u{2102}</text></svg>".to_string(),
});
}
return;
}
let bounds = graphic_element.bounding_box(DAffine2::IDENTITY, true);
// Render the thumbnail from a `GraphicElement` into an SVG string

View file

@ -356,7 +356,7 @@ pub struct ContextImpl<'a> {
}
impl<'a> ContextImpl<'a> {
pub fn with_footprint<'f>(&self, new_footprint: &'f Footprint, varargs: Option<&'f impl (Borrow<[DynRef<'f>]>)>) -> ContextImpl<'f>
pub fn with_footprint<'f>(&self, new_footprint: &'f Footprint, varargs: Option<&'f impl Borrow<[DynRef<'f>]>>) -> ContextImpl<'f>
where
'a: 'f,
{

View file

@ -22,6 +22,7 @@ pub mod ops;
pub mod raster;
pub mod raster_types;
pub mod registry;
pub mod render_complexity;
pub mod structural;
pub mod text;
pub mod transform;

View file

@ -0,0 +1,58 @@
use crate::raster_types::{CPU, GPU, Raster};
use crate::{Artboard, Color, GraphicElement, instances::Instances, vector::VectorData};
use glam::DVec2;
pub trait RenderComplexity {
fn render_complexity(&self) -> usize {
0
}
}
impl<T: RenderComplexity> RenderComplexity for Instances<T> {
fn render_complexity(&self) -> usize {
self.instance_ref_iter().map(|instance| instance.instance.render_complexity()).sum()
}
}
impl RenderComplexity for Artboard {
fn render_complexity(&self) -> usize {
self.graphic_group.render_complexity()
}
}
impl RenderComplexity for GraphicElement {
fn render_complexity(&self) -> usize {
match self {
Self::GraphicGroup(instances) => instances.render_complexity(),
Self::VectorData(instances) => instances.render_complexity(),
Self::RasterDataCPU(instances) => instances.render_complexity(),
Self::RasterDataGPU(instances) => instances.render_complexity(),
}
}
}
impl RenderComplexity for VectorData {
fn render_complexity(&self) -> usize {
self.segment_domain.ids().len()
}
}
impl RenderComplexity for Raster<CPU> {
fn render_complexity(&self) -> usize {
(self.width * self.height) as usize
}
}
impl RenderComplexity for Raster<GPU> {
fn render_complexity(&self) -> usize {
(self.width() * self.height()) as usize
}
}
impl RenderComplexity for String {}
impl RenderComplexity for bool {}
impl RenderComplexity for f32 {}
impl RenderComplexity for f64 {}
impl RenderComplexity for DVec2 {}
impl RenderComplexity for Option<Color> {}
impl RenderComplexity for Vec<Color> {}

View file

@ -97,7 +97,7 @@ macro_rules! tagged_value {
}
}
/// Attempts to downcast the dynamic type to a tagged value
pub fn try_from_std_any_ref(input: &(dyn std::any::Any)) -> Result<Self, String> {
pub fn try_from_std_any_ref(input: &dyn std::any::Any) -> Result<Self, String> {
use std::any::TypeId;
match input.type_id() {

View file

@ -10,6 +10,7 @@ use graphene_core::instances::Instance;
use graphene_core::math::quad::Quad;
use graphene_core::raster::Image;
use graphene_core::raster_types::{CPU, GPU, RasterDataTable};
use graphene_core::render_complexity::RenderComplexity;
use graphene_core::transform::{Footprint, Transform};
use graphene_core::uuid::{NodeId, generate_uuid};
use graphene_core::vector::VectorDataTable;
@ -203,7 +204,7 @@ pub struct RenderMetadata {
}
// TODO: Rename to "Graphical"
pub trait GraphicElementRendered: BoundingBox {
pub trait GraphicElementRendered: BoundingBox + RenderComplexity {
fn render_svg(&self, render: &mut SvgRender, render_params: &RenderParams);
#[cfg(feature = "vello")]
@ -1149,7 +1150,7 @@ impl GraphicElementRendered for GraphicElement {
}
/// Used to stop rust complaining about upstream traits adding display implementations to `Option<Color>`. This would not be an issue as we control that crate.
trait Primitive: std::fmt::Display + BoundingBox {}
trait Primitive: std::fmt::Display + BoundingBox + RenderComplexity {}
impl Primitive for String {}
impl Primitive for bool {}
impl Primitive for f32 {}