Add the SVG Preview render mode in place of the Vello option in the preferences (#3797)
* Remove Vello from preferences * Add the Render Mode: SVG Preview radio button * Remove SVG outline renderer * Add a tooltip explaination when disabled in unsupported browsers * Fix Eyedropper tool to support Outline render mode * Use #[allow(clippy::too_many_arguments)] instead of tuple * Rerun nodegraph when max render area is changed --------- Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
parent
a2d3b3f410
commit
9f2c8713ff
|
|
@ -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\
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -157,5 +157,4 @@ pub enum PortfolioMessage {
|
|||
ToggleRulers,
|
||||
UpdateDocumentWidgets,
|
||||
UpdateOpenDocumentsList,
|
||||
UpdateVelloPreference,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -407,6 +407,13 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> 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<PortfolioMessage, PortfolioMessageContext<'_>> 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<PortfolioMessage, PortfolioMessageContext<'_>> 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<PortfolioMessage, PortfolioMessageContext<'_>> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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<PreferencesMessage, PreferencesMessageContext<'_>> 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<PreferencesMessage, PreferencesMessageContext<'_>> 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<PreferencesMessage, PreferencesMessageContext<'_>> for Prefe
|
|||
}
|
||||
PreferencesMessage::MaxRenderRegionSize { size } => {
|
||||
self.max_render_region_size = size;
|
||||
responses.add(PortfolioMessage::UpdateVelloPreference);
|
||||
responses.add(PortfolioMessage::EditorPreferences);
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -336,27 +336,13 @@ pub type WasmSurfaceHandle = SurfaceHandle<wgpu_executor::Window>;
|
|||
#[cfg(feature = "wgpu")]
|
||||
pub type WasmSurfaceHandleFrame = graphene_application_io::SurfaceHandleFrame<wgpu_executor::Window>;
|
||||
|
||||
#[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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,6 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||
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 {
|
||||
|
|
|
|||
|
|
@ -217,7 +217,6 @@ impl<T: NodeGraphUpdateSender> NodeGraphUpdateSender for std::sync::Mutex<T> {
|
|||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue