Add checkbox for a transparent BG when exporting image (#1344)

This commit is contained in:
Keavon Chambers 2023-07-30 10:57:07 -07:00 committed by GitHub
parent 1fc3808b7f
commit f151ba39b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 9 deletions

View file

@ -9,6 +9,7 @@ pub enum ExportDialogMessage {
FileName(String),
FileType(FileType),
ScaleFactor(f64),
TransparentBackground(bool),
ExportBounds(ExportBounds),
Submit,

View file

@ -2,7 +2,7 @@ use crate::messages::frontend::utility_types::{ExportBounds, FileType};
use crate::messages::layout::utility_types::layout_widget::{Layout, LayoutGroup, PropertyHolder, Widget, WidgetCallback, WidgetHolder, WidgetLayout};
use crate::messages::layout::utility_types::misc::LayoutTarget;
use crate::messages::layout::utility_types::widgets::button_widgets::TextButton;
use crate::messages::layout::utility_types::widgets::input_widgets::{DropdownEntryData, DropdownInput, NumberInput, RadioEntryData, RadioInput, TextInput};
use crate::messages::layout::utility_types::widgets::input_widgets::{CheckboxInput, DropdownEntryData, DropdownInput, NumberInput, RadioEntryData, RadioInput, TextInput};
use crate::messages::layout::utility_types::widgets::label_widgets::{Separator, SeparatorDirection, SeparatorType, TextLabel};
use crate::messages::prelude::*;
@ -15,6 +15,7 @@ pub struct ExportDialogMessageHandler {
pub file_type: FileType,
pub scale_factor: f64,
pub bounds: ExportBounds,
pub transparent_background: bool,
pub artboards: HashMap<LayerId, String>,
pub has_selection: bool,
}
@ -24,7 +25,8 @@ impl MessageHandler<ExportDialogMessage, ()> for ExportDialogMessageHandler {
match message {
ExportDialogMessage::FileName(name) => self.file_name = name,
ExportDialogMessage::FileType(export_type) => self.file_type = export_type,
ExportDialogMessage::ScaleFactor(x) => self.scale_factor = x,
ExportDialogMessage::ScaleFactor(factor) => self.scale_factor = factor,
ExportDialogMessage::TransparentBackground(transparent_background) => self.transparent_background = transparent_background,
ExportDialogMessage::ExportBounds(export_area) => self.bounds = export_area,
ExportDialogMessage::Submit => responses.add_front(DocumentMessage::ExportDocument {
@ -32,6 +34,7 @@ impl MessageHandler<ExportDialogMessage, ()> for ExportDialogMessageHandler {
file_type: self.file_type,
scale_factor: self.scale_factor,
bounds: self.bounds,
transparent_background: self.file_type != FileType::Jpg && self.transparent_background,
}),
}
@ -120,6 +123,24 @@ impl PropertyHolder for ExportDialogMessageHandler {
})),
];
let transparent_background = vec![
WidgetHolder::new(Widget::TextLabel(TextLabel {
value: "Transparency".into(),
table_align: true,
..Default::default()
})),
WidgetHolder::new(Widget::Separator(Separator {
separator_type: SeparatorType::Unrelated,
direction: SeparatorDirection::Horizontal,
})),
WidgetHolder::new(Widget::CheckboxInput(CheckboxInput {
checked: self.transparent_background,
disabled: self.file_type == FileType::Jpg,
on_update: WidgetCallback::new(move |value: &CheckboxInput| ExportDialogMessage::TransparentBackground(value.checked).into()),
..Default::default()
})),
];
let resolution = vec![
WidgetHolder::new(Widget::TextLabel(TextLabel {
value: "Scale Factor".into(),
@ -174,6 +195,7 @@ impl PropertyHolder for ExportDialogMessageHandler {
LayoutGroup::Row { widgets: export_type },
LayoutGroup::Row { widgets: resolution },
LayoutGroup::Row { widgets: export_area },
LayoutGroup::Row { widgets: transparent_background },
LayoutGroup::Row { widgets: button_widgets },
]))
}

View file

@ -82,6 +82,7 @@ pub enum DocumentMessage {
file_type: FileType,
scale_factor: f64,
bounds: ExportBounds,
transparent_background: bool,
},
FlipSelectedLayers {
flip_axis: FlipAxis,

View file

@ -370,6 +370,7 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
file_type,
scale_factor,
bounds,
transparent_background,
} => {
let old_transforms = self.remove_document_transform();
@ -383,7 +384,7 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
let size = bounds[1] - bounds[0];
let transform = (DAffine2::from_translation(bounds[0]) * DAffine2::from_scale(size)).inverse();
let document = self.render_document(size, transform, persistent_data, DocumentRenderMode::Root);
let document = self.render_document(size, transform, transparent_background, persistent_data, DocumentRenderMode::Root);
self.restore_document_transform(old_transforms);
@ -1011,7 +1012,8 @@ impl DocumentMessageHandler {
// Calculate the size of the region to be exported and generate an SVG of the artwork below this layer within that region
let transform = self.document_legacy.multiply_transforms(&layer_path).unwrap();
let size = DVec2::new(transform.transform_vector2(DVec2::new(1., 0.)).length(), transform.transform_vector2(DVec2::new(0., 1.)).length());
let svg = self.render_document(size, transform.inverse(), persistent_data, DocumentRenderMode::OnlyBelowLayerInFolder(&layer_path));
// TODO: Test if this would be better to have a transparent background
let svg = self.render_document(size, transform.inverse(), false, persistent_data, DocumentRenderMode::OnlyBelowLayerInFolder(&layer_path));
self.restore_document_transform(old_transforms);
@ -1053,7 +1055,7 @@ impl DocumentMessageHandler {
DocumentLegacy::mark_children_as_dirty(&mut self.artboard_message_handler.artboards_document.root);
}
pub fn render_document(&mut self, size: DVec2, transform: DAffine2, persistent_data: &PersistentData, render_mode: DocumentRenderMode) -> String {
pub fn render_document(&mut self, size: DVec2, transform: DAffine2, transparent_background: bool, persistent_data: &PersistentData, render_mode: DocumentRenderMode) -> String {
// Render the document SVG code
let render_data = RenderData::new(&persistent_data.font_cache, ViewMode::Normal, None);
@ -1063,20 +1065,26 @@ impl DocumentMessageHandler {
DocumentRenderMode::OnlyBelowLayerInFolder(below_layer_path) => (self.document_legacy.render_layers_below(below_layer_path, &render_data).unwrap(), None),
DocumentRenderMode::LayerCutout(layer_path, background) => (self.document_legacy.render_layer(layer_path, &render_data).unwrap(), Some(background)),
};
let artboards = self.artboard_message_handler.artboards_document.render_root(&render_data);
let artboards = match transparent_background {
false => self.artboard_message_handler.artboards_document.render_root(&render_data),
true => "".into(),
};
let outside_artboards_color = outside.map_or_else(
|| if self.artboard_message_handler.artboard_ids.is_empty() { "ffffff" } else { "222222" }.to_string(),
|col| col.rgba_hex(),
);
let outside_artboards = format!(r##"<rect x="0" y="0" width="100%" height="100%" fill="#{}" />"##, outside_artboards_color);
let outside_artboards = match transparent_background {
false => format!(r##"<rect x="0" y="0" width="100%" height="100%" fill="#{}" />"##, outside_artboards_color),
true => "".into(),
};
let matrix = transform
.to_cols_array()
.iter()
.enumerate()
.fold(String::new(), |acc, (i, entry)| acc + &(entry.to_string() + if i == 5 { "" } else { "," }));
let svg = format!(
r#"<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 1 1" width="{}" height="{}">{}{}<g transform="matrix({})">{}{}</g></svg>"#,
size.x, size.y, "\n", outside_artboards, matrix, artboards, artwork
r#"<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 1 1" width="{}" height="{}">{}{outside_artboards}<g transform="matrix({matrix})">{artboards}{artwork}</g></svg>"#,
size.x, size.y, "\n",
);
svg