Fixed bugs for svg
This commit is contained in:
@ -75,9 +75,9 @@ pub enum BasicDataType {
|
||||
derive(serde::Serialize, serde::Deserialize)
|
||||
)]
|
||||
pub enum BasicValue {
|
||||
SaveString {
|
||||
SaveBytes {
|
||||
path: String,
|
||||
value: String,
|
||||
value: Vec<u8>,
|
||||
},
|
||||
Error {
|
||||
value: LayoutJob,
|
||||
@ -225,7 +225,7 @@ impl Hash for BasicValue {
|
||||
);
|
||||
|
||||
match self {
|
||||
| Self::SaveString { path, value } => {
|
||||
| Self::SaveBytes { path, value } => {
|
||||
path.hash(state);
|
||||
value.hash(state);
|
||||
},
|
||||
@ -284,6 +284,7 @@ pub enum NodeInstruction {
|
||||
ColorNode,
|
||||
ColorEdge,
|
||||
StringToSvg,
|
||||
SaveSvg,
|
||||
|
||||
// convert basic data types
|
||||
ToPositiveSet,
|
||||
@ -493,6 +494,7 @@ impl NodeInstruction {
|
||||
],
|
||||
| Self::Sleep => vec![("seconds", PositiveInt)],
|
||||
| Self::StringToSvg => vec![("value", String)],
|
||||
| Self::SaveSvg => vec![("path", Path), ("value", Svg)]
|
||||
}
|
||||
.into_iter()
|
||||
.map(|e| (e.0.to_string(), e.1))
|
||||
@ -589,6 +591,7 @@ impl NodeInstruction {
|
||||
| Self::PositiveBisimilarityPaigeTarjan => vec![("out", String)],
|
||||
| Self::Sleep => vec![("out", PositiveInt)],
|
||||
| Self::StringToSvg => vec![("out", Svg)],
|
||||
| Self::SaveSvg => vec![],
|
||||
};
|
||||
res.into_iter()
|
||||
.map(|res| (res.0.to_string(), res.1))
|
||||
@ -1087,6 +1090,7 @@ impl NodeTemplateTrait for NodeInstruction {
|
||||
"Positive Paige & Torjan",
|
||||
| Self::Sleep => "Sleep",
|
||||
| Self::StringToSvg => "String to SVG",
|
||||
| Self::SaveSvg => "Save SVG",
|
||||
})
|
||||
}
|
||||
|
||||
@ -1169,7 +1173,8 @@ impl NodeTemplateTrait for NodeInstruction {
|
||||
| Self::PositiveBisimilarityPaigeTarjan =>
|
||||
vec!["Positive Graph", "Positive Bisimilarity"],
|
||||
| Self::Sleep
|
||||
| Self::StringToSvg => vec!["General"],
|
||||
| Self::StringToSvg
|
||||
| Self::SaveSvg => vec!["General"],
|
||||
}
|
||||
}
|
||||
|
||||
@ -1276,6 +1281,7 @@ impl NodeTemplateIter for AllInstructions {
|
||||
NodeInstruction::PositiveBisimilarityPaigeTarjan,
|
||||
NodeInstruction::Sleep,
|
||||
NodeInstruction::StringToSvg,
|
||||
NodeInstruction::SaveSvg,
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -1298,7 +1304,7 @@ impl WidgetValueTrait for BasicValue {
|
||||
|
||||
match self {
|
||||
// Dummy values used to save files, no ui since not needed
|
||||
| BasicValue::SaveString { path: _, value: _ } => {},
|
||||
| BasicValue::SaveBytes { path: _, value: _ } => {},
|
||||
| BasicValue::Error { value: _ } => {},
|
||||
|
||||
| BasicValue::String { value } => {
|
||||
@ -1461,6 +1467,13 @@ impl NodeDataTrait for NodeData {
|
||||
));
|
||||
}
|
||||
},
|
||||
| (_, NodeInstruction::SaveSvg) => {
|
||||
if ui.button("Write").clicked() {
|
||||
responses.push(NodeResponse::User(
|
||||
CustomResponse::SaveToFile(node_id),
|
||||
));
|
||||
}
|
||||
}
|
||||
| (true, NodeInstruction::ReadPath) => {
|
||||
// since no filewatcher we simply give the option to reload the
|
||||
// file
|
||||
@ -1936,7 +1949,7 @@ impl eframe::App for AppHandle {
|
||||
let text = get_layout(Err(e), &self.translator.lock().unwrap(), ctx);
|
||||
self.cached_last_value = Some(text);
|
||||
} else if let Some(l_b_v) = self.cache.get_last_state() {
|
||||
if let BasicValue::SaveString { path, value } = &l_b_v {
|
||||
if let BasicValue::SaveBytes { path, value } = &l_b_v {
|
||||
use std::io::Write;
|
||||
let mut f = match std::fs::File::create(path) {
|
||||
Ok(f) => f,
|
||||
@ -1945,7 +1958,7 @@ impl eframe::App for AppHandle {
|
||||
return;
|
||||
}
|
||||
};
|
||||
if let Err(e) = write!(f, "{}", value) {
|
||||
if let Err(e) = f.write_all(value) {
|
||||
println!("Error writing to file {path}: {e}");
|
||||
return;
|
||||
}
|
||||
@ -1970,7 +1983,7 @@ impl eframe::App for AppHandle {
|
||||
let text = get_layout(Err(e), &self.translator.lock().unwrap(), ctx);
|
||||
self.cached_last_value = Some(content.clone());
|
||||
} else if let Some(l_b_v) = self.cache.get_last_state() {
|
||||
if let BasicValue::SaveString { path, value } = &l_b_v {
|
||||
if let BasicValue::SaveBytes { path, value } = &l_b_v {
|
||||
use std::io::Write;
|
||||
let mut f = match std::fs::File::create(path) {
|
||||
Ok(f) => f,
|
||||
@ -2103,7 +2116,7 @@ fn get_layout(
|
||||
|
||||
match value {
|
||||
| Ok(value) => match value {
|
||||
| BasicValue::SaveString { path, value: _ } => text.append(
|
||||
| BasicValue::SaveBytes { path, value: _ } => text.append(
|
||||
&format!("Saving to file \"{}\"", path),
|
||||
0., Default::default(),
|
||||
),
|
||||
|
||||
@ -108,11 +108,14 @@ fn generate_to_evaluate(
|
||||
for n_id in dependencies {
|
||||
let mut input_hashes = vec![];
|
||||
|
||||
if let NodeInstruction::SaveString = graph[n_id].user_data.template {
|
||||
match graph[n_id].user_data.template {
|
||||
NodeInstruction::SaveString | NodeInstruction::SaveSvg => {
|
||||
res.push(n_id);
|
||||
invalid_ids.insert(n_id);
|
||||
outputs_cache.invalidate_outputs(graph, n_id);
|
||||
continue;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let first_output =
|
||||
@ -848,7 +851,7 @@ fn process_template(
|
||||
BasicValue::Path { value: path },
|
||||
BasicValue::String { value },
|
||||
) => {
|
||||
*to_ret = Some(BasicValue::SaveString { path, value });
|
||||
*to_ret = Some(BasicValue::SaveBytes { path, value: value.into() });
|
||||
},
|
||||
| (BasicValue::Path { .. }, _) => {
|
||||
anyhow::bail!("Not a string");
|
||||
@ -2513,6 +2516,36 @@ fn process_template(
|
||||
anyhow::bail!("Not a string");
|
||||
}
|
||||
},
|
||||
| NodeInstruction::SaveSvg => {
|
||||
let (path, svg) = retrieve_from_cache![2];
|
||||
|
||||
match (path, svg) {
|
||||
| (
|
||||
BasicValue::Path { value: path },
|
||||
BasicValue::Svg { value },
|
||||
) => {
|
||||
let mut path = path.to_string();
|
||||
if !path.ends_with(".png") {
|
||||
path.push_str(".png");
|
||||
}
|
||||
let svg = match value.rasterize() {
|
||||
Ok(svg) => svg,
|
||||
Err(e) => anyhow::bail!(e),
|
||||
};
|
||||
let raw = svg.into_raw();
|
||||
*to_ret = Some(BasicValue::SaveBytes { path, value: raw });
|
||||
},
|
||||
| (BasicValue::Path { .. }, _) => {
|
||||
anyhow::bail!("Not an svg");
|
||||
},
|
||||
| (_, BasicValue::Svg { .. }) => {
|
||||
anyhow::bail!("Not a path");
|
||||
},
|
||||
| (_, _) => {
|
||||
anyhow::bail!("Values of wrong type");
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(unsafe_code)]
|
||||
#![warn(clippy::all, rust_2018_idioms)]
|
||||
// Forbid warnings in release builds
|
||||
#![cfg_attr(not(debug_assertions), deny(warnings))]
|
||||
|
||||
@ -13,6 +13,8 @@ pub(crate) struct Svg {
|
||||
/// original size of the svg
|
||||
svg_size: egui::Vec2,
|
||||
|
||||
original: String,
|
||||
|
||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||
svg_texture: Arc<Mutex<Option<egui::TextureHandle>>>,
|
||||
}
|
||||
@ -53,7 +55,10 @@ impl Svg {
|
||||
|
||||
let image = egui::ColorImage::from_rgba_unmultiplied([w as _, h as _], &data);
|
||||
|
||||
let svg = Svg { image, svg_size, svg_texture: Arc::new(Mutex::new(None)) };
|
||||
let svg = Svg { image,
|
||||
original: content,
|
||||
svg_size,
|
||||
svg_texture: Arc::new(Mutex::new(None)) };
|
||||
|
||||
Ok(svg)
|
||||
}
|
||||
@ -69,6 +74,19 @@ impl Svg {
|
||||
svg_texture
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn rasterize(&self) -> Result<nsvg::image::ImageBuffer<nsvg::image::Rgba<u8>, Vec<u8>>, String> {
|
||||
let svg = match nsvg::parse_str(&self.original, nsvg::Units::Pixel, 96.0) {
|
||||
Ok(svg) => svg,
|
||||
Err(nsvg_err) => return Err(format!("{}", nsvg_err)),
|
||||
};
|
||||
let data = match svg.rasterize(1.) {
|
||||
Ok(o) => o,
|
||||
Err(e) => return Err(format!("{}", e)),
|
||||
};
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Svg {
|
||||
@ -105,6 +123,7 @@ impl Hash for Svg {
|
||||
hash_float!(self.svg_size.y);
|
||||
self.image.pixels.hash(state);
|
||||
self.image.size.hash(state);
|
||||
self.original.hash(state);
|
||||
hash_float!(self.image.source_size.x);
|
||||
hash_float!(self.image.source_size.y);
|
||||
self.svg_texture.lock().expect("Poisoned").hash(state);
|
||||
|
||||
Reference in New Issue
Block a user