From de48f936e95b86e569ffdb20d2faf10ef4937017 Mon Sep 17 00:00:00 2001 From: Adrien Burgun Date: Thu, 28 Jul 2022 13:16:41 +0200 Subject: [PATCH] :sparkles: Species inheritance, set-fill --- species/blobcat/assets/base.svg | 47 +++++++++++++++++++ species/blobcat/species.toml | 2 + species/blobcat/templates/base-extra.mustache | 1 + .../blobcat/templates/hands-reach.mustache | 4 ++ .../blobcat/templates/mouth-reach.mustache | 1 + species/blobcat/templates/mouth-w.mustache | 1 + species/blobcat/templates/nose-aww.mustache | 1 + species/blobcat/templates/nose-snug.mustache | 1 + species/blobcat/templates/nose.mustache | 1 + species/blobcat/templates/whiskers.mustache | 6 +++ species/blobfox/templates/base-extra.mustache | 2 + species/blobfox/templates/base-owo.mustache | 2 +- species/blobfox/templates/base.mustache | 2 +- .../blobfox/templates/reach-extra.mustache | 2 + species/blobfox/variants/base.mustache | 1 + species/blobfox/variants/boop.mustache | 1 + species/blobfox/variants/boop_aww.mustache | 1 + species/blobfox/variants/boop_owo.mustache | 1 + species/blobfox/variants/happy.mustache | 1 + species/blobfox/variants/owo.mustache | 1 + species/blobfox/variants/reach.mustache | 1 + species/blobfox/variants/reach_aww.mustache | 1 + src/export.rs | 21 ++++++--- src/main.rs | 6 +-- src/parse.rs | 21 +++++++-- src/template.rs | 46 ++++++++++++++++++ 26 files changed, 161 insertions(+), 14 deletions(-) create mode 100644 species/blobcat/assets/base.svg create mode 100644 species/blobcat/species.toml create mode 100644 species/blobcat/templates/base-extra.mustache create mode 100644 species/blobcat/templates/hands-reach.mustache create mode 100644 species/blobcat/templates/mouth-reach.mustache create mode 100644 species/blobcat/templates/mouth-w.mustache create mode 100644 species/blobcat/templates/nose-aww.mustache create mode 100644 species/blobcat/templates/nose-snug.mustache create mode 100644 species/blobcat/templates/nose.mustache create mode 100644 species/blobcat/templates/whiskers.mustache create mode 100644 species/blobfox/templates/base-extra.mustache create mode 100644 species/blobfox/templates/reach-extra.mustache diff --git a/species/blobcat/assets/base.svg b/species/blobcat/assets/base.svg new file mode 100644 index 0000000..3ac4901 --- /dev/null +++ b/species/blobcat/assets/base.svg @@ -0,0 +1,47 @@ + + + blobcat + + + + + + + + + + + + + + + + + + + + + + + + + + Blobfox team (https://git.shadamethyst.xyz/adri326/blobfox), licensed under the Apache 2.0 License + + + blobcat + + + Feuerfuchs + + + https://git.shadamethyst.xyz/adri326/blobfox + + + + diff --git a/species/blobcat/species.toml b/species/blobcat/species.toml new file mode 100644 index 0000000..5e598ca --- /dev/null +++ b/species/blobcat/species.toml @@ -0,0 +1,2 @@ +name = "blobcat" +base = "../blobfox/" diff --git a/species/blobcat/templates/base-extra.mustache b/species/blobcat/templates/base-extra.mustache new file mode 100644 index 0000000..ba90093 --- /dev/null +++ b/species/blobcat/templates/base-extra.mustache @@ -0,0 +1 @@ +{{>whiskers}} diff --git a/species/blobcat/templates/hands-reach.mustache b/species/blobcat/templates/hands-reach.mustache new file mode 100644 index 0000000..58d4100 --- /dev/null +++ b/species/blobcat/templates/hands-reach.mustache @@ -0,0 +1,4 @@ + + {{#set-fill}}#fcc21b|{{#reach_aww}}#left-hand{{/reach_aww}}{{/set-fill}} + {{#set-fill}}#fcc21b|{{#reach_aww}}#right-hand{{/reach_aww}}{{/set-fill}} + diff --git a/species/blobcat/templates/mouth-reach.mustache b/species/blobcat/templates/mouth-reach.mustache new file mode 100644 index 0000000..8e1d73a --- /dev/null +++ b/species/blobcat/templates/mouth-reach.mustache @@ -0,0 +1 @@ +{{#base}}#mouth{{/base}} diff --git a/species/blobcat/templates/mouth-w.mustache b/species/blobcat/templates/mouth-w.mustache new file mode 100644 index 0000000..8e1d73a --- /dev/null +++ b/species/blobcat/templates/mouth-w.mustache @@ -0,0 +1 @@ +{{#base}}#mouth{{/base}} diff --git a/species/blobcat/templates/nose-aww.mustache b/species/blobcat/templates/nose-aww.mustache new file mode 100644 index 0000000..b7d321d --- /dev/null +++ b/species/blobcat/templates/nose-aww.mustache @@ -0,0 +1 @@ + diff --git a/species/blobcat/templates/nose-snug.mustache b/species/blobcat/templates/nose-snug.mustache new file mode 100644 index 0000000..3a79eeb --- /dev/null +++ b/species/blobcat/templates/nose-snug.mustache @@ -0,0 +1 @@ + diff --git a/species/blobcat/templates/nose.mustache b/species/blobcat/templates/nose.mustache new file mode 100644 index 0000000..1b4b8bc --- /dev/null +++ b/species/blobcat/templates/nose.mustache @@ -0,0 +1 @@ + diff --git a/species/blobcat/templates/whiskers.mustache b/species/blobcat/templates/whiskers.mustache new file mode 100644 index 0000000..dfc44f2 --- /dev/null +++ b/species/blobcat/templates/whiskers.mustache @@ -0,0 +1,6 @@ + + {{#base}}#left-whisker{{/base}} + {{#base}}#left-whisker-2{{/base}} + {{#base}}#right-whisker{{/base}} + {{#base}}#right-whisker-2{{/base}} + diff --git a/species/blobfox/templates/base-extra.mustache b/species/blobfox/templates/base-extra.mustache new file mode 100644 index 0000000..5e859b1 --- /dev/null +++ b/species/blobfox/templates/base-extra.mustache @@ -0,0 +1,2 @@ +{{! Should be included after >base if there is no arm, object, etc. on the emote }} + diff --git a/species/blobfox/templates/base-owo.mustache b/species/blobfox/templates/base-owo.mustache index 2142de4..a5e4dec 100644 --- a/species/blobfox/templates/base-owo.mustache +++ b/species/blobfox/templates/base-owo.mustache @@ -1,7 +1,7 @@ - {{#base}}#body{{/base}} {{#boop_owo}}#left-ear{{/boop_owo}} {{#boop_owo}}#left-ear-fluff{{/boop_owo}} + {{#base}}#body{{/base}} {{#base}}#hair{{/base}} {{#base}}#right-ear{{/base}} {{#base}}#right-ear-fluff{{/base}} diff --git a/species/blobfox/templates/base.mustache b/species/blobfox/templates/base.mustache index e653823..515a103 100644 --- a/species/blobfox/templates/base.mustache +++ b/species/blobfox/templates/base.mustache @@ -1,6 +1,6 @@ - {{#base}}#body{{/base}} {{#base}}#left-ear{{/base}} + {{#base}}#body{{/base}} {{#base}}#hair{{/base}} {{#base}}#right-ear{{/base}} {{#base}}#right-ear-fluff{{/base}} diff --git a/species/blobfox/templates/reach-extra.mustache b/species/blobfox/templates/reach-extra.mustache new file mode 100644 index 0000000..1dc66f5 --- /dev/null +++ b/species/blobfox/templates/reach-extra.mustache @@ -0,0 +1,2 @@ +{{! cf. base-extra }} + diff --git a/species/blobfox/variants/base.mustache b/species/blobfox/variants/base.mustache index c1ab55d..a8b5ad8 100644 --- a/species/blobfox/variants/base.mustache +++ b/species/blobfox/variants/base.mustache @@ -1,6 +1,7 @@ {{>header}} {{>base}} + {{>base-extra}} {{>eyes}} diff --git a/species/blobfox/variants/boop.mustache b/species/blobfox/variants/boop.mustache index caa2ec3..e2228af 100644 --- a/species/blobfox/variants/boop.mustache +++ b/species/blobfox/variants/boop.mustache @@ -1,6 +1,7 @@ {{>header}} {{>base}} + {{>base-extra}} {{>eyes}} diff --git a/species/blobfox/variants/boop_aww.mustache b/species/blobfox/variants/boop_aww.mustache index 507867d..63a696f 100644 --- a/species/blobfox/variants/boop_aww.mustache +++ b/species/blobfox/variants/boop_aww.mustache @@ -1,6 +1,7 @@ {{>header}} {{>base}} + {{>base-extra}} {{>eyes-aww}} diff --git a/species/blobfox/variants/boop_owo.mustache b/species/blobfox/variants/boop_owo.mustache index e6ffd0b..d91d892 100644 --- a/species/blobfox/variants/boop_owo.mustache +++ b/species/blobfox/variants/boop_owo.mustache @@ -1,6 +1,7 @@ {{>header}} {{>base-owo}} + {{>base-extra}} {{>eyes-owo}} diff --git a/species/blobfox/variants/happy.mustache b/species/blobfox/variants/happy.mustache index c9e1847..dd826d3 100644 --- a/species/blobfox/variants/happy.mustache +++ b/species/blobfox/variants/happy.mustache @@ -1,6 +1,7 @@ {{>header}} {{>base}} + {{>base-extra}} {{>eyes-snug}} diff --git a/species/blobfox/variants/owo.mustache b/species/blobfox/variants/owo.mustache index ac0a191..4476a58 100644 --- a/species/blobfox/variants/owo.mustache +++ b/species/blobfox/variants/owo.mustache @@ -1,6 +1,7 @@ {{>header}} {{>base-owo}} + {{>base-extra}} {{>eyes-owo}} diff --git a/species/blobfox/variants/reach.mustache b/species/blobfox/variants/reach.mustache index 56fa5ea..8552195 100644 --- a/species/blobfox/variants/reach.mustache +++ b/species/blobfox/variants/reach.mustache @@ -2,6 +2,7 @@ {{>base}} {{>hands-reach}} + {{>reach-extra}} {{>eyes}} diff --git a/species/blobfox/variants/reach_aww.mustache b/species/blobfox/variants/reach_aww.mustache index 695f33e..cb22b44 100644 --- a/species/blobfox/variants/reach_aww.mustache +++ b/species/blobfox/variants/reach_aww.mustache @@ -2,6 +2,7 @@ {{>base}} {{>hands-reach}} + {{>reach-extra}} {{>eyes-aww}} diff --git a/src/export.rs b/src/export.rs index 715db2a..c7c0122 100644 --- a/src/export.rs +++ b/src/export.rs @@ -50,14 +50,23 @@ impl From for ExportError { pub fn get_new_bbox(svg: &Tree) -> Option<(f64, f64, f64, f64)> { let bbox = svg.root().calculate_bbox()?; - if bbox.width() > bbox.height() { - let y = bbox.y() - (bbox.width() - bbox.height()) / 2.0; - Some((bbox.x(), y, bbox.width(), bbox.width())) + // FIXME: remove once https://github.com/RazrFalcon/resvg/issues/528 is fixed + const MARGIN: f64 = 1.0; + + let x = bbox.x() - MARGIN; + let y = bbox.y() - MARGIN; + let width = bbox.width() + MARGIN * 2.0; + let height = bbox.height() + MARGIN * 2.0; + + if width > height { + let y = y - (width - height) / 2.0; + + Some((x, y, width, width)) } else { - let x = bbox.x() - (bbox.height() - bbox.width()) / 2.0; + let x = x - (height - width) / 2.0; - Some((x, bbox.y(), bbox.height(), bbox.height())) + Some((x, y, height, height)) } } @@ -98,7 +107,7 @@ pub fn export( output_name: String, args: &super::Args, ) -> Result<(), ExportError> { - if args.resize { + if !args.no_resize { svg_str = resize(svg_str)?; } diff --git a/src/main.rs b/src/main.rs index e0d3097..9e1984a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -68,9 +68,9 @@ pub struct Args { #[clap(value_parser)] names: Vec, - /// Automatically resize the SVG's viewBox, defaults to true - #[clap(short, long, value_parser, default_value = "true")] - resize: bool, + /// Disable automatically resizing the SVG's viewBox, defaults to false + #[clap(short, long, value_parser, default_value = "false")] + no_resize: bool, /// Dimension to export the images as; can be specified multiple times #[clap(long, value_parser)] diff --git a/src/parse.rs b/src/parse.rs index f438616..7370cbb 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -59,15 +59,30 @@ pub fn load_species(path: impl AsRef) -> Result { let mut res: SpeciesDecl = toml::from_str(&declaration)?; + if let Some(ref base) = &res.base { + let path = path.as_ref().to_path_buf().join(base); + let base = load_species(path)?; + + res.templates = base.templates; + res.variants = base.variants; + res.assets = base.assets; + } + // Read the `templates` directory and populate the `templates` field; // on error, ignore the directory. - res.templates = read_dir_xml(path.as_ref().join("templates")); + for (name, path) in read_dir_xml(path.as_ref().join("templates")) { + res.templates.insert(name, path); + } // Read the `variants` directory - res.variants = read_dir_xml(path.as_ref().join("variants")); + for (name, path) in read_dir_xml(path.as_ref().join("variants")) { + res.variants.insert(name, path); + } // Read the `assets` directory - res.assets = read_dir_xml(path.as_ref().join("assets")); + for (name, path) in read_dir_xml(path.as_ref().join("assets")) { + res.assets.insert(name, path); + } Ok(res) } diff --git a/src/template.rs b/src/template.rs index 16ace95..e427eed 100644 --- a/src/template.rs +++ b/src/template.rs @@ -34,6 +34,12 @@ impl RenderingContext { Context::with_loader(self.clone()).compile(template.chars()) } + fn render_to_string(&self, string: &str) -> Result { + Context::with_loader(self.clone()) + .compile(string.chars())? + .render_data_to_string(&self.get_data()) + } + pub fn get_data(&self) -> Data { let mut builder = MapBuilder::new(); @@ -75,6 +81,46 @@ impl RenderingContext { }); } + let this = self.clone(); + builder = builder.insert_fn("set-fill", move |input| { + // Parse `color|xml` + if let [color, xml] = input.splitn(2, '|').collect::>()[..] { + // Render `color` and `xml` + if let (Ok(color), Ok(xml)) = (this.render_to_string(&color), this.render_to_string(&xml)) { + // Convert `xml` to XML + match Element::parse(xml.as_bytes()) { + Ok(mut xml) => { + // Substitute the fill color + if let Some(style) = xml.attributes.get("style") { + xml.attributes.insert("style".to_string(), format!( + "{};fill: {};", + style, + color + )); + } + if let Some(_fill) = xml.attributes.get("fill") { + xml.attributes.insert("fill".to_string(), color); + } + + // Render XML to string + if let Some(res) = xml_to_string(xml) { + res + } else { + String::from("") + } + } + Err(err) => { + format!("", err) + } + } + } else { + String::from("") + } + } else { + String::from("") + } + }); + builder.build() }