diff --git a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs index c7555150e0..dd114bc713 100644 --- a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs +++ b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs @@ -314,38 +314,6 @@ impl PreferencesDialogMessageHandler { } if wgpu_available { - let vello_description = "Auto uses Vello renderer when GPU is available."; - let vello_renderer_label = vec![ - Separator::new(SeparatorStyle::Unrelated).widget_instance(), - Separator::new(SeparatorStyle::Unrelated).widget_instance(), - TextLabel::new("Vello Renderer") - .tooltip_label("Vello Renderer") - .tooltip_description(vello_description) - .widget_instance(), - ]; - let vello_preference = RadioInput::new(vec![ - RadioEntryData::new("Auto").label("Auto").on_update(move |_| { - PreferencesMessage::VelloPreference { - preference: graph_craft::wasm_application_io::VelloPreference::Auto, - } - .into() - }), - RadioEntryData::new("Disabled").label("Disabled").on_update(move |_| { - PreferencesMessage::VelloPreference { - preference: graph_craft::wasm_application_io::VelloPreference::Disabled, - } - .into() - }), - ]) - .selected_index(Some(preferences.vello_preference as u32)) - .widget_instance(); - let vello_preference = vec![ - Separator::new(SeparatorStyle::Unrelated).widget_instance(), - Separator::new(SeparatorStyle::Unrelated).widget_instance(), - vello_preference, - ]; - rows.extend_from_slice(&[vello_renderer_label, vello_preference]); - let render_tile_resolution_description = " Maximum X or Y resolution per render tile. Larger tiles may improve performance but can cause flickering or missing content in complex artwork if set too high.\n\ \n\ diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 234c0f383a..76fbfa4828 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -33,6 +33,7 @@ use graphene_std::math::quad::Quad; use graphene_std::path_bool::{boolean_intersect, path_bool_lib}; use graphene_std::raster::BlendMode; use graphene_std::raster_types::Raster; +use graphene_std::render_node::wgpu_available; use graphene_std::subpath::Subpath; use graphene_std::table::Table; use graphene_std::vector::PointId; @@ -2549,29 +2550,46 @@ impl DocumentMessageHandler { .popover_min_width(Some(320)) .widget_instance(), Separator::new(SeparatorStyle::Unrelated).widget_instance(), - RadioInput::new(vec![ - RadioEntryData::new("Normal") - .icon("RenderModeNormal") - .tooltip_label("Render Mode: Normal") - .on_update(|_| DocumentMessage::SetRenderMode { render_mode: RenderMode::Normal }.into()), - RadioEntryData::new("Outline") - .icon("RenderModeOutline") - .tooltip_label("Render Mode: Outline") - .on_update(|_| DocumentMessage::SetRenderMode { render_mode: RenderMode::Outline }.into()), - // TODO: See issue #320 - // RadioEntryData::new("PixelPreview") - // .icon("RenderModePixels") - // .tooltip_label("Render Mode: Pixel Preview") - // .on_update(|_| todo!()), - // TODO: See issue #1845 - // RadioEntryData::new("SvgPreview") - // .icon("RenderModeSvg") - // .tooltip_label("Render Mode: SVG Preview") - // .on_update(|_| todo!()), - ]) - .selected_index(Some(self.render_mode as u32)) - .narrow(true) - .widget_instance(), + { + let disabled = cfg!(target_family = "wasm") && wgpu_available() == Some(false); + + let mut entries = vec![ + RadioEntryData::new("Normal") + .icon("RenderModeNormal") + .tooltip_label("Render Mode: Normal") + .on_update(|_| DocumentMessage::SetRenderMode { render_mode: RenderMode::Normal }.into()), + RadioEntryData::new("Outline") + .icon("RenderModeOutline") + .tooltip_label("Render Mode: Outline") + .on_update(|_| DocumentMessage::SetRenderMode { render_mode: RenderMode::Outline }.into()), + // TODO: See issue #320 + // RadioEntryData::new("PixelPreview") + // .icon("RenderModePixels") + // .tooltip_label("Render Mode: Pixel Preview") + // .on_update(|_| todo!()), + RadioEntryData::new("SvgPreview") + .icon("RenderModeSvg") + .tooltip_label("Render Mode: SVG Preview") + .on_update(|_| DocumentMessage::SetRenderMode { render_mode: RenderMode::SvgPreview }.into()), + ]; + let mut selected_index = self.render_mode as u32; + + if disabled { + for entry in &mut entries { + entry.tooltip_description = " + *Normal* and *Outline* render modes are not available in this browser. For compatibility, *SVG Preview* mode is active as a fallback.\n\ + \n\ + This functionality requires WebGPU support. Check webgpu.org for browser implementation status. + " + .trim() + .into(); + } + + selected_index = entries.iter().position(|entry| entry.value == "SvgPreview").unwrap() as u32; + } + + RadioInput::new(entries).selected_index(Some(selected_index)).disabled(disabled).narrow(true).widget_instance() + }, Separator::new(SeparatorStyle::Unrelated).widget_instance(), ]; diff --git a/editor/src/messages/portfolio/portfolio_message.rs b/editor/src/messages/portfolio/portfolio_message.rs index 2db5945c78..97c39c624b 100644 --- a/editor/src/messages/portfolio/portfolio_message.rs +++ b/editor/src/messages/portfolio/portfolio_message.rs @@ -157,5 +157,4 @@ pub enum PortfolioMessage { ToggleRulers, UpdateDocumentWidgets, UpdateOpenDocumentsList, - UpdateVelloPreference, } diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index c9d5c57e68..e73eb4ef98 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -407,6 +407,13 @@ impl MessageHandler> for Portfolio // Use exact physical dimensions from browser (via ResizeObserver's devicePixelContentBoxSize) let physical_resolution = viewport.size().to_physical().into_dvec2().round().as_uvec2(); + // TODO: Remove this when we do the SVG rendering with a separate library on desktop, thus avoiding a need for the hole punch. + // TODO: See #3796. There is a second instance of this todo comment and code block (be sure to remove both). + #[cfg(not(target_family = "wasm"))] + responses.add_front(FrontendMessage::UpdateViewportHolePunch { + active: document.render_mode != graphene_std::vector::style::RenderMode::SvgPreview, + }); + if let Ok(message) = self.executor.submit_node_graph_evaluation( self.documents.get_mut(document_id).expect("Tried to render non-existent document"), *document_id, @@ -1163,6 +1170,13 @@ impl MessageHandler> for Portfolio // Use exact physical dimensions from browser (via ResizeObserver's devicePixelContentBoxSize) let physical_resolution = viewport.size().to_physical().into_dvec2().round().as_uvec2(); + // TODO: Remove this when we do the SVG rendering with a separate library on desktop, thus avoiding a need for the hole punch. + // TODO: See #3796. There is a second instance of this todo comment and code block (be sure to remove both). + #[cfg(not(target_family = "wasm"))] + responses.add_front(FrontendMessage::UpdateViewportHolePunch { + active: document.render_mode != graphene_std::vector::style::RenderMode::SvgPreview, + }); + let result = self .executor .submit_node_graph_evaluation(document, document_id, physical_resolution, scale, timing_information, node_to_inspect, ignore_hash, pointer_position); @@ -1197,7 +1211,7 @@ impl MessageHandler> for Portfolio let result = self .executor - .submit_eyedropper_preview(document_id, preview_transform, pointer_position, resolution, scale, timing_information); + .submit_eyedropper_preview(document, document_id, preview_transform, pointer_position, resolution, scale, timing_information); match result { Err(description) => { @@ -1364,13 +1378,6 @@ impl MessageHandler> for Portfolio responses.add(PortfolioMessage::RequestWelcomeScreenButtonsLayout); } } - PortfolioMessage::UpdateVelloPreference => { - // TODO: Resend this message once the GPU context is initialized to avoid having the hole punch be stuck in an invalid state - let active = if cfg!(target_family = "wasm") { false } else { preferences.use_vello() }; - responses.add(FrontendMessage::UpdateViewportHolePunch { active }); - responses.add(NodeGraphMessage::RunDocumentGraph); - self.persistent_data.use_vello = preferences.use_vello(); - } } } diff --git a/editor/src/messages/portfolio/utility_types.rs b/editor/src/messages/portfolio/utility_types.rs index c58e762ef1..0626cabf0a 100644 --- a/editor/src/messages/portfolio/utility_types.rs +++ b/editor/src/messages/portfolio/utility_types.rs @@ -6,7 +6,6 @@ use graphene_std::text::{Font, FontCache}; pub struct PersistentData { pub font_cache: FontCache, pub font_catalog: FontCatalog, - pub use_vello: bool, } // TODO: Should this be a BTreeMap instead? diff --git a/editor/src/messages/preferences/preferences_message.rs b/editor/src/messages/preferences/preferences_message.rs index ad9d570f6e..ff9803c0c3 100644 --- a/editor/src/messages/preferences/preferences_message.rs +++ b/editor/src/messages/preferences/preferences_message.rs @@ -10,7 +10,6 @@ pub enum PreferencesMessage { ResetToDefaults, // Per-preference messages - VelloPreference { preference: graph_craft::wasm_application_io::VelloPreference }, SelectionMode { selection_mode: SelectionMode }, BrushTool { enabled: bool }, ModifyLayout { zoom_with_scroll: bool }, diff --git a/editor/src/messages/preferences/preferences_message_handler.rs b/editor/src/messages/preferences/preferences_message_handler.rs index e11296acbb..9fb3b4cd16 100644 --- a/editor/src/messages/preferences/preferences_message_handler.rs +++ b/editor/src/messages/preferences/preferences_message_handler.rs @@ -5,7 +5,6 @@ use crate::messages::preferences::SelectionMode; use crate::messages::prelude::*; use crate::messages::tool::utility_types::ToolType; use graph_craft::wasm_application_io::EditorPreferences; -use graphene_std::application_io::GetEditorPreferences; #[derive(ExtractField)] pub struct PreferencesMessageContext<'a> { @@ -17,7 +16,6 @@ pub struct PreferencesMessageContext<'a> { pub struct PreferencesMessageHandler { pub selection_mode: SelectionMode, pub zoom_with_scroll: bool, - pub vello_preference: graph_craft::wasm_application_io::VelloPreference, pub brush_tool: bool, pub graph_wire_style: GraphWireStyle, pub viewport_zoom_wheel_rate: f64, @@ -37,7 +35,6 @@ impl PreferencesMessageHandler { pub fn editor_preferences(&self) -> EditorPreferences { EditorPreferences { - vello_preference: self.vello_preference, max_render_region_size: self.max_render_region_size, } } @@ -45,10 +42,6 @@ impl PreferencesMessageHandler { pub fn supports_wgpu(&self) -> bool { graph_craft::wasm_application_io::wgpu_available().unwrap_or_default() } - - pub fn use_vello(&self) -> bool { - self.editor_preferences().use_vello() - } } impl Default for PreferencesMessageHandler { @@ -56,7 +49,6 @@ impl Default for PreferencesMessageHandler { Self { selection_mode: SelectionMode::Touched, zoom_with_scroll: matches!(MappingVariant::default(), MappingVariant::ZoomWithScroll), - vello_preference: EditorPreferences::default().vello_preference, brush_tool: false, graph_wire_style: GraphWireStyle::default(), viewport_zoom_wheel_rate: VIEWPORT_ZOOM_WHEEL_RATE, @@ -78,7 +70,6 @@ impl MessageHandler> for Prefe *self = preferences; responses.add(PortfolioMessage::EditorPreferences); - responses.add(PortfolioMessage::UpdateVelloPreference); responses.add(PreferencesMessage::ModifyLayout { zoom_with_scroll: self.zoom_with_scroll, }); @@ -90,12 +81,6 @@ impl MessageHandler> for Prefe } // Per-preference messages - PreferencesMessage::VelloPreference { preference } => { - self.vello_preference = preference; - responses.add(PortfolioMessage::UpdateVelloPreference); - responses.add(PortfolioMessage::EditorPreferences); - responses.add(PreferencesDialogMessage::Update); - } PreferencesMessage::BrushTool { enabled } => { self.brush_tool = enabled; @@ -131,8 +116,8 @@ impl MessageHandler> for Prefe } PreferencesMessage::MaxRenderRegionSize { size } => { self.max_render_region_size = size; - responses.add(PortfolioMessage::UpdateVelloPreference); responses.add(PortfolioMessage::EditorPreferences); + responses.add(NodeGraphMessage::RunDocumentGraph); } } diff --git a/editor/src/node_graph_executor.rs b/editor/src/node_graph_executor.rs index d89fbe72e7..b325bfd2ab 100644 --- a/editor/src/node_graph_executor.rs +++ b/editor/src/node_graph_executor.rs @@ -187,9 +187,11 @@ impl NodeGraphExecutor { self.submit_current_node_graph_evaluation(document, document_id, viewport_resolution, viewport_scale, time, pointer) } + #[allow(clippy::too_many_arguments)] #[cfg(not(target_family = "wasm"))] pub(crate) fn submit_eyedropper_preview( &mut self, + document: &DocumentMessageHandler, document_id: DocumentId, transform: DAffine2, pointer: DVec2, @@ -208,7 +210,7 @@ impl NodeGraphExecutor { time, pointer, export_format: graphene_std::application_io::ExportFormat::Raster, - render_mode: graphene_std::vector::style::RenderMode::Normal, + render_mode: document.render_mode, hide_artboards: false, for_export: false, for_eyedropper: true, diff --git a/editor/src/node_graph_executor/runtime.rs b/editor/src/node_graph_executor/runtime.rs index e2a7be830b..e4fb9a84b0 100644 --- a/editor/src/node_graph_executor/runtime.rs +++ b/editor/src/node_graph_executor/runtime.rs @@ -18,6 +18,7 @@ use graphene_std::table::{Table, TableRow}; use graphene_std::text::FontCache; use graphene_std::transform::RenderQuality; use graphene_std::vector::Vector; +use graphene_std::vector::style::RenderMode; use graphene_std::wasm_application_io::{RenderOutputType, WasmApplicationIo, WasmEditorApi}; use graphene_std::{Artboard, Context, Graphic}; use interpreted_executor::dynamic_executor::{DynamicExecutor, IntrospectError, ResolvedDocumentNodeTypesDelta}; @@ -243,16 +244,11 @@ impl NodeRuntime { self.sender.send_generation_response(CompilationResponse { result, node_graph_errors }); } GraphRuntimeRequest::ExecutionRequest(ExecutionRequest { execution_id, mut render_config, .. }) => { - // There are cases where we want to export via the svg pipeline eventhough raster was requested. - if matches!(render_config.export_format, ExportFormat::Raster) { - let vello_available = self.editor_api.application_io.as_ref().unwrap().gpu_executor().is_some(); - let use_vello = vello_available && self.editor_api.editor_preferences.use_vello(); - - // On web when the user has disabled vello rendering in the preferences or we are exporting. - // And on all platforms when vello is not supposed to be used. - if !use_vello || cfg!(target_family = "wasm") && render_config.for_export { - render_config.export_format = ExportFormat::Svg; - } + // We may want to render via the SVG pipeline even though raster was requested, if SVG Preview render mode is active or WebGPU/Vello is unavailable + if render_config.export_format == ExportFormat::Raster + && (render_config.render_mode == RenderMode::SvgPreview || self.editor_api.application_io.as_ref().unwrap().gpu_executor().is_none()) + { + render_config.export_format = ExportFormat::Svg; } let result = self.execute_network(render_config).await; diff --git a/frontend/src/components/widgets/inputs/RadioInput.svelte b/frontend/src/components/widgets/inputs/RadioInput.svelte index 8760d2dea0..0fa6b0d883 100644 --- a/frontend/src/components/widgets/inputs/RadioInput.svelte +++ b/frontend/src/components/widgets/inputs/RadioInput.svelte @@ -79,15 +79,6 @@ margin-right: 2px; } - &:hover { - background: var(--color-6-lowergray); - color: var(--color-f-white); - - svg { - fill: var(--color-f-white); - } - } - &.active { background: var(--color-e-nearwhite); color: var(--color-2-mildblack); @@ -112,19 +103,12 @@ } } - &.narrow.narrow { - --widget-height: 20px; - height: var(--widget-height); + &:not(.disabled) button:not(.active):hover { + background: var(--color-6-lowergray); + color: var(--color-f-white); - button { - height: 16px; - } - } - - &.mixed { - button:not(:hover), - &.disabled button:hover { - background: var(--color-5-dullgray); + svg { + fill: var(--color-f-white); } } @@ -144,5 +128,21 @@ } } } + + &.narrow.narrow { + --widget-height: 20px; + height: var(--widget-height); + + button { + height: 16px; + } + } + + &.mixed { + button:not(:hover), + &.disabled button:hover { + background: var(--color-5-dullgray); + } + } } diff --git a/frontend/wasm/src/editor_api.rs b/frontend/wasm/src/editor_api.rs index 7c3b65252c..52c3d00126 100644 --- a/frontend/wasm/src/editor_api.rs +++ b/frontend/wasm/src/editor_api.rs @@ -967,7 +967,7 @@ async fn poll_node_graph_evaluation() { if !editor::node_graph_executor::run_node_graph().await.0 { return; - }; + } editor_and_handle(|editor, handle| { let mut messages = VecDeque::new(); diff --git a/node-graph/graph-craft/src/wasm_application_io.rs b/node-graph/graph-craft/src/wasm_application_io.rs index 6ca9ffa065..b02b8014e2 100644 --- a/node-graph/graph-craft/src/wasm_application_io.rs +++ b/node-graph/graph-craft/src/wasm_application_io.rs @@ -336,27 +336,13 @@ pub type WasmSurfaceHandle = SurfaceHandle; #[cfg(feature = "wgpu")] pub type WasmSurfaceHandleFrame = graphene_application_io::SurfaceHandleFrame; -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, specta::Type, serde::Serialize, serde::Deserialize)] -pub enum VelloPreference { - Auto, - Disabled, -} - #[derive(Clone, Debug, PartialEq, Hash, specta::Type, serde::Serialize, serde::Deserialize)] pub struct EditorPreferences { - pub vello_preference: VelloPreference, /// Maximum render region size in pixels along one dimension of the square area. pub max_render_region_size: u32, } impl graphene_application_io::GetEditorPreferences for EditorPreferences { - fn use_vello(&self) -> bool { - match self.vello_preference { - VelloPreference::Auto => wgpu_available().unwrap_or(false), - VelloPreference::Disabled => false, - } - } - fn max_render_region_area(&self) -> u32 { let size = self.max_render_region_size.min(u32::MAX.isqrt()); size.pow(2) @@ -365,10 +351,7 @@ impl graphene_application_io::GetEditorPreferences for EditorPreferences { impl Default for EditorPreferences { fn default() -> Self { - Self { - vello_preference: VelloPreference::Auto, - max_render_region_size: 1280, - } + Self { max_render_region_size: 1280 } } } diff --git a/node-graph/graphene-cli/src/main.rs b/node-graph/graphene-cli/src/main.rs index 1bf96b458e..4f559adf8f 100644 --- a/node-graph/graphene-cli/src/main.rs +++ b/node-graph/graphene-cli/src/main.rs @@ -126,7 +126,6 @@ async fn main() -> Result<(), Box> { let device = wgpu_executor_ref.context.device.clone(); let preferences = EditorPreferences { - vello_preference: graph_craft::wasm_application_io::VelloPreference::Auto, max_render_region_size: EditorPreferences::default().max_render_region_size, }; let editor_api = Arc::new(WasmEditorApi { diff --git a/node-graph/libraries/application-io/src/lib.rs b/node-graph/libraries/application-io/src/lib.rs index 7961107b35..c93ffaa445 100644 --- a/node-graph/libraries/application-io/src/lib.rs +++ b/node-graph/libraries/application-io/src/lib.rs @@ -217,7 +217,6 @@ impl NodeGraphUpdateSender for std::sync::Mutex { } pub trait GetEditorPreferences { - fn use_vello(&self) -> bool; fn max_render_region_area(&self) -> u32; } @@ -238,11 +237,11 @@ pub struct TimingInformation { pub struct RenderConfig { pub viewport: Footprint, pub scale: f64, - pub export_format: ExportFormat, pub time: TimingInformation, pub pointer: DVec2, #[serde(alias = "view_mode")] pub render_mode: RenderMode, + pub export_format: ExportFormat, pub hide_artboards: bool, pub for_export: bool, pub for_eyedropper: bool, @@ -259,10 +258,6 @@ impl NodeGraphUpdateSender for Logger { struct DummyPreferences; impl GetEditorPreferences for DummyPreferences { - fn use_vello(&self) -> bool { - false - } - fn max_render_region_area(&self) -> u32 { 1024 * 1024 } diff --git a/node-graph/libraries/rendering/src/render_ext.rs b/node-graph/libraries/rendering/src/render_ext.rs index a7eb895f54..302a0ef73e 100644 --- a/node-graph/libraries/rendering/src/render_ext.rs +++ b/node-graph/libraries/rendering/src/render_ext.rs @@ -1,9 +1,8 @@ -use crate::renderer::{RenderParams, black_or_white_for_best_contrast, format_transform_matrix}; -use core_types::consts::LAYER_OUTLINE_STROKE_WEIGHT; +use crate::renderer::{RenderParams, format_transform_matrix}; use core_types::uuid::generate_uuid; use glam::DAffine2; use graphic_types::vector_types::gradient::{Gradient, GradientType}; -use graphic_types::vector_types::vector::style::{Fill, PaintOrder, PathStyle, RenderMode, Stroke, StrokeAlign, StrokeCap, StrokeJoin}; +use graphic_types::vector_types::vector::style::{Fill, PaintOrder, PathStyle, Stroke, StrokeAlign, StrokeCap, StrokeJoin}; use std::fmt::Write; pub trait RenderExt { @@ -14,7 +13,7 @@ pub trait RenderExt { impl RenderExt for Gradient { type Output = u64; - // /// Adds the gradient def through mutating the first argument, returning the gradient ID. + /// Adds the gradient def through mutating the first argument, returning the gradient ID. fn render(&self, svg_defs: &mut String, element_transform: DAffine2, stroke_transform: DAffine2, bounds: DAffine2, transformed_bounds: DAffine2, _render_params: &RenderParams) -> Self::Output { let mut stop = String::new(); for (position, color) in self.stops.0.iter() { @@ -163,28 +162,12 @@ impl RenderExt for PathStyle { /// Renders the shape's fill and stroke attributes as a string with them concatenated together. #[allow(clippy::too_many_arguments)] fn render(&self, svg_defs: &mut String, element_transform: DAffine2, stroke_transform: DAffine2, bounds: DAffine2, transformed_bounds: DAffine2, render_params: &RenderParams) -> String { - let render_mode = render_params.render_mode; - match render_mode { - RenderMode::Outline => { - let fill_attribute = Fill::None.render(svg_defs, element_transform, stroke_transform, bounds, transformed_bounds, render_params); - - let outline_color = black_or_white_for_best_contrast(render_params.artboard_background); - let mut outline_stroke = Stroke::new(Some(outline_color), LAYER_OUTLINE_STROKE_WEIGHT); - // Outline strokes should be non-scaling by default - outline_stroke.non_scaling = true; - - let stroke_attribute = outline_stroke.render(svg_defs, element_transform, stroke_transform, bounds, transformed_bounds, render_params); - format!("{fill_attribute}{stroke_attribute}") - } - _ => { - let fill_attribute = self.fill.render(svg_defs, element_transform, stroke_transform, bounds, transformed_bounds, render_params); - let stroke_attribute = self - .stroke - .as_ref() - .map(|stroke| stroke.render(svg_defs, element_transform, stroke_transform, bounds, transformed_bounds, render_params)) - .unwrap_or_default(); - format!("{fill_attribute}{stroke_attribute}") - } - } + let fill_attribute = self.fill.render(svg_defs, element_transform, stroke_transform, bounds, transformed_bounds, render_params); + let stroke_attribute = self + .stroke + .as_ref() + .map(|stroke| stroke.render(svg_defs, element_transform, stroke_transform, bounds, transformed_bounds, render_params)) + .unwrap_or_default(); + format!("{fill_attribute}{stroke_attribute}") } } diff --git a/node-graph/libraries/vector-types/src/vector/style.rs b/node-graph/libraries/vector-types/src/vector/style.rs index 4330045f9a..4385d3f6e1 100644 --- a/node-graph/libraries/vector-types/src/vector/style.rs +++ b/node-graph/libraries/vector-types/src/vector/style.rs @@ -662,6 +662,6 @@ pub enum RenderMode { Outline, // /// Render with normal coloration at the document resolution, showing the pixels when the current viewport resolution is higher // PixelPreview, - // /// Render a preview of how the object would be exported as an SVG. - // SvgPreview, + /// Render a preview of how the object would be exported as an SVG. + SvgPreview, }