diff --git a/.gitignore b/.gitignore
index 9d605e3..8bc691d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@ original/
output/
Cargo.lock
target/
+blobfox-*.zip
diff --git a/Cargo.toml b/Cargo.toml
index 6b1fdcd..b0f2f12 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,3 +20,4 @@ resvg = "0.23"
usvg = "0.23"
tiny-skia = "0.6"
png = "0.17"
+css-color-parser = "0.1.2"
diff --git a/README.md b/README.md
index 0c3f86d..3cc3721 100644
--- a/README.md
+++ b/README.md
@@ -41,9 +41,21 @@ If you'd like to help, there are a few things that need attention outside of imp
- german shepherd
- collie
- sheep
+ - bird
- etc.
- clean up the SVG for the existing emotes (the `clean` binary in `feat/template` is meant to do the heavy-lifting)
+### TODO
+
+- set_stroke!
+- blobfox_ohmy
+- blobfox_trumpet
+- blobfox_highfive
+- googly eyes?
+- tea/coffee
+- sad
+- uwu
+
## License
All the code, images and assets of this repository are made available under the Apache 2.0 license.
diff --git a/snuggle.toml b/snuggle.toml
new file mode 100644
index 0000000..e4009fa
--- /dev/null
+++ b/snuggle.toml
@@ -0,0 +1,4 @@
+name = "snuggle"
+dx = -60
+dy = -40
+transform = "scale(1.02 1.02) translate(-1.5 -1)"
diff --git a/species/blobfox/assets/snuggle_right.svg b/species/blobfox/assets/snuggle_right.svg
new file mode 100644
index 0000000..1941986
--- /dev/null
+++ b/species/blobfox/assets/snuggle_right.svg
@@ -0,0 +1,49 @@
+
+
diff --git a/species/blobfox/species.toml b/species/blobfox/species.toml
index aec1dad..abf0481 100644
--- a/species/blobfox/species.toml
+++ b/species/blobfox/species.toml
@@ -6,6 +6,7 @@ body_color = "#ff8702"
ear_color = "#313131"
ear_fluff_color = "#ebdccc"
hand_color = "#ff8702"
+hand_stroke_color = "#313131"
tail_color = "#ff8702"
[variants]
@@ -51,3 +52,7 @@ heart_enby = ["body-basic", "eyes-basic", "left-hand", "right-hand", "holding",
heart_ace = ["body-basic", "eyes-basic", "left-hand", "right-hand", "holding", "big-object"]
heart_demisexual = ["body-basic", "eyes-basic", "left-hand", "right-hand", "holding", "big-object"]
heart_pan = ["body-basic", "eyes-basic", "left-hand", "right-hand", "holding", "big-object"]
+
+# Snuggle
+snuggle_right = ["body-snuggle", "eyes-snuggle", "mouth-w"]
+snuggle_right_shadow = ["body-snuggle", "eyes-snuggle", "mouth-w"]
diff --git a/species/blobfox/templates/body-snuggle.mustache b/species/blobfox/templates/body-snuggle.mustache
new file mode 100644
index 0000000..db2c8f7
--- /dev/null
+++ b/species/blobfox/templates/body-snuggle.mustache
@@ -0,0 +1,15 @@
+{{! Left ear }}
+{{#set-fill}} {{vars.ear_color}} | {{#snuggle_right}}#left-ear{{/snuggle_right}} {{/set-fill}}
+
+{{! Body }}
+
+
+ {{#snuggle_right}}#body{{/snuggle_right}}
+
+
+{{#set-fill}} {{vars.body_color}} | {{#snuggle_right}}#body{{/snuggle_right}} {{/set-fill}}
+{{#set-fill}} {{vars.body_color}} | {{#snuggle_right}}#hair{{/snuggle_right}} {{/set-fill}}
+
+{{! Right ear }}
+{{#set-fill}} {{vars.ear_color}} | {{#snuggle_right}}#right-ear{{/snuggle_right}} {{/set-fill}}
+{{#set-fill}} {{vars.ear_fluff_color}} | {{#snuggle_right}}#right-ear-fluff{{/snuggle_right}} {{/set-fill}}
diff --git a/species/blobfox/templates/body.mustache b/species/blobfox/templates/body.mustache
index d4239d8..ca18fc8 100644
--- a/species/blobfox/templates/body.mustache
+++ b/species/blobfox/templates/body.mustache
@@ -8,4 +8,7 @@
{{#tags.body-comfy}}
{{>body-comfy}}
{{/tags.body-comfy}}
+ {{#tags.body-snuggle}}
+ {{>body-snuggle}}
+ {{/tags.body-snuggle}}
diff --git a/species/blobfox/templates/eyes.mustache b/species/blobfox/templates/eyes.mustache
index 9658a4e..214917b 100644
--- a/species/blobfox/templates/eyes.mustache
+++ b/species/blobfox/templates/eyes.mustache
@@ -23,4 +23,8 @@
{{#blush}}#left-eye{{/blush}}
{{#blush}}#right-eye{{/blush}}
{{/tags.eyes-closed}}
+ {{#tags.eyes-snuggle}}
+ {{#snuggle_right}}#left-eye{{/snuggle_right}}
+ {{#snuggle_right}}#right-eye{{/snuggle_right}}
+ {{/tags.eyes-snuggle}}
diff --git a/species/blobfox/templates/hands.mustache b/species/blobfox/templates/hands.mustache
index e268cb6..57317b2 100644
--- a/species/blobfox/templates/hands.mustache
+++ b/species/blobfox/templates/hands.mustache
@@ -1,7 +1,19 @@
{{#tags.hands-reach}}
- {{#set-fill}} {{vars.hand_color}} | {{#reach_aww}}#left-hand{{/reach_aww}} {{/set-fill}}
- {{#set-fill}} {{vars.hand_color}} | {{#reach_aww}}#right-hand{{/reach_aww}} {{/set-fill}}
+ {{#set-stroke}}
+ {{vars.hand_stroke_color}} |
+ {{#set-fill}}
+ {{vars.hand_color}}
+ | {{#reach_aww}}#left-hand{{/reach_aww}}
+ {{/set-fill}}
+ {{/set-stroke}}
+ {{#set-stroke}}
+ {{vars.hand_stroke_color}} |
+ {{#set-fill}}
+ {{vars.hand_color}}
+ | {{#reach_aww}}#right-hand{{/reach_aww}}
+ {{/set-fill}}
+ {{/set-stroke}}
{{/tags.hands-reach}}
{{#tags.hand-3c}}
{{#tags.holding}}
diff --git a/species/blobfox/templates/nose.mustache b/species/blobfox/templates/nose.mustache
index edbdedf..7bb93d6 100644
--- a/species/blobfox/templates/nose.mustache
+++ b/species/blobfox/templates/nose.mustache
@@ -14,6 +14,9 @@
{{#tags.eyes-closed}}
{{#blush}}#nose-outline{{/blush}}
{{/tags.eyes-closed}}
+ {{#tags.eyes-snuggle}}
+ {{#snuggle_right}}#nose-outline{{/snuggle_right}}
+ {{/tags.eyes-snuggle}}
{{#base}}#nose{{/base}}
diff --git a/species/blobfox/variants/heart_ace.mustache b/species/blobfox/variants/heart_ace.mustache
index 90e5eeb..abf3d49 100644
--- a/species/blobfox/variants/heart_ace.mustache
+++ b/species/blobfox/variants/heart_ace.mustache
@@ -9,7 +9,11 @@
-
+
+ {{#heart}}#heart{{/heart}}
+
+
+
{{#flag_ace}}{{/flag_ace}}
diff --git a/species/blobfox/variants/heart_demisexual.mustache b/species/blobfox/variants/heart_demisexual.mustache
index c508c39..fff4d22 100644
--- a/species/blobfox/variants/heart_demisexual.mustache
+++ b/species/blobfox/variants/heart_demisexual.mustache
@@ -9,7 +9,11 @@
-
+
+ {{#heart}}#heart{{/heart}}
+
+
+
{{#flag_demisexual}}{{/flag_demisexual}}
diff --git a/species/blobfox/variants/heart_enby.mustache b/species/blobfox/variants/heart_enby.mustache
index 71ccdff..05c2eb4 100644
--- a/species/blobfox/variants/heart_enby.mustache
+++ b/species/blobfox/variants/heart_enby.mustache
@@ -9,7 +9,11 @@
-
+
+ {{#heart}}#heart{{/heart}}
+
+
+
{{#flag_enby}}{{/flag_enby}}
diff --git a/species/blobfox/variants/heart_pan.mustache b/species/blobfox/variants/heart_pan.mustache
index ec04719..db05a5e 100644
--- a/species/blobfox/variants/heart_pan.mustache
+++ b/species/blobfox/variants/heart_pan.mustache
@@ -9,7 +9,11 @@
-
+
+ {{#heart}}#heart{{/heart}}
+
+
+
{{#flag_pan}}{{/flag_pan}}
diff --git a/species/blobfox/variants/heart_progress.mustache b/species/blobfox/variants/heart_progress.mustache
index d515e0f..3ffc9f5 100644
--- a/species/blobfox/variants/heart_progress.mustache
+++ b/species/blobfox/variants/heart_progress.mustache
@@ -9,7 +9,11 @@
-
+
+ {{#heart}}#heart{{/heart}}
+
+
+
{{#flag_progress}}{{/flag_progress}}
diff --git a/species/blobfox/variants/snuggle_right.mustache b/species/blobfox/variants/snuggle_right.mustache
new file mode 100644
index 0000000..6a0a83d
--- /dev/null
+++ b/species/blobfox/variants/snuggle_right.mustache
@@ -0,0 +1,9 @@
+{{>header}}
+ {{>body}}
+
+
+ {{>eyes}}
+ {{>nose}}
+ {{>mouth}}
+
+{{>footer}}
diff --git a/src/bin/snuggle.rs b/src/bin/snuggle.rs
new file mode 100644
index 0000000..d4cb8b0
--- /dev/null
+++ b/src/bin/snuggle.rs
@@ -0,0 +1,148 @@
+//! Very crude tool for generating snuggle emotes
+use clap::Parser;
+use std::fmt::Write;
+use std::path::PathBuf;
+use serde::{Serialize, Deserialize};
+use xmltree::{Element, XMLNode};
+
+use blobfox_template::{
+ parse,
+ template,
+ export,
+};
+
+#[derive(Serialize, Deserialize, Debug)]
+struct Desc {
+ dx: f64,
+ dy: f64,
+
+ scale: Option,
+
+ #[serde(default)]
+ transform: String,
+}
+
+fn main() {
+ let args = Args::parse();
+
+ let left = std::fs::read_to_string(&args.input_left).unwrap_or_else(|err| {
+ panic!("Couldn't open {}: {}", args.input_right.display(), err);
+ });
+ let right = std::fs::read_to_string(&args.input_right).unwrap_or_else(|err| {
+ panic!("Couldn't open {}: {}", args.input_right.display(), err);
+ });
+
+ let desc = std::fs::read_to_string(&args.desc).unwrap_or_else(|err| {
+ panic!("Couldn't open {}: {}", args.desc.display(), err);
+ });
+ let desc: Desc = toml::from_str(&desc).unwrap();
+
+ let snuggle = generate_snuggle(left, right, desc);
+ let snuggle = export::xml_to_str(&snuggle).unwrap();
+
+ let output_dir = args.output_dir.clone().unwrap_or(PathBuf::from("output/"));
+
+ export::export(
+ snuggle,
+ &output_dir,
+ args.name.clone(),
+ &args.clone().into()
+ ).unwrap();
+}
+
+fn generate_snuggle(left: String, right: String, desc: Desc) -> Element {
+ let left_usvg = export::get_usvg(&left).unwrap();
+ let left_bbox = left_usvg.svg_node().view_box.rect;
+
+ //
+ let mut mask = Element::new("mask");
+ mask.attributes.insert("id".to_string(), "snuggle-mask".to_string());
+
+ let mut rect = Element::new("rect");
+ rect.attributes.insert("fill".to_string(), "white".to_string());
+ // TODO: use scale?
+ rect.attributes.insert("x".to_string(), (desc.dx + left_bbox.x()).to_string());
+ rect.attributes.insert("y".to_string(), (desc.dy + left_bbox.y()).to_string());
+ rect.attributes.insert("width".to_string(), left_bbox.width().to_string());
+ rect.attributes.insert("height".to_string(), left_bbox.height().to_string());
+
+ mask.children.push(XMLNode::Element(rect));
+
+ let mut right_mask = Element::new("g");
+ right_mask.attributes.insert("transform".to_string(), desc.transform);
+
+ let mut right_xml = Element::parse(right.as_bytes()).unwrap();
+ template::set_fill("#000000", &mut right_xml);
+ template::set_stroke("#000000", &mut right_xml);
+
+ for child in right_xml.children {
+ if let XMLNode::Element(child) = child {
+ right_mask.children.push(XMLNode::Element(child));
+ }
+ }
+
+ mask.children.push(XMLNode::Element(right_mask));
+
+ let mut right_xml = Element::parse(right.as_bytes()).unwrap();
+ let left_xml = Element::parse(left.as_bytes()).unwrap();
+
+ let mut left_group = Element::new("g");
+ left_group.attributes.insert("transform".to_string(), format!(
+ "translate({} {})",
+ desc.dx,
+ desc.dy
+ ));
+ left_group.children = left_xml.children;
+
+ let mut left_group2 = Element::new("g");
+ left_group2.attributes.insert("mask".to_string(), "url(#snuggle-mask)".to_string());
+ left_group2.children.push(XMLNode::Element(left_group));
+
+ let mut res = Element::new("svg");
+ res.attributes.insert("xmlns".to_string(), "http://www.w3.org/2000/svg".to_string());
+ res.attributes.insert("version".to_string(), "1.1".to_string());
+ res.attributes.insert("width".to_string(), "128".to_string());
+ res.attributes.insert("height".to_string(), "128".to_string());
+ res.children.push(XMLNode::Element(mask));
+ res.children.append(&mut right_xml.children);
+ res.children.push(XMLNode::Element(left_group2));
+
+ res
+}
+
+#[derive(Parser, Clone)]
+#[clap(author, version, about, long_about = None)]
+struct Args {
+ #[clap(value_parser)]
+ input_left: PathBuf,
+
+ #[clap(value_parser)]
+ input_right: PathBuf,
+
+ #[clap(short, long, value_parser)]
+ desc: PathBuf,
+
+ /// Disable automatically resizing the SVG's viewBox, defaults to false
+ #[clap(short, long, value_parser, default_value = "false")]
+ no_resize: bool,
+
+ #[clap(long, value_parser)]
+ name: String,
+
+ /// Dimension to export the images as; can be specified multiple times
+ #[clap(long, value_parser)]
+ dim: Vec,
+
+ /// Output directory
+ #[clap(short, long, value_parser)]
+ output_dir: Option,
+}
+
+impl From for export::ExportArgs {
+ fn from(args: Args) -> export::ExportArgs {
+ export::ExportArgs {
+ no_resize: args.no_resize,
+ dim: args.dim,
+ }
+ }
+}
diff --git a/src/export.rs b/src/export.rs
index 27c86db..8f730b8 100644
--- a/src/export.rs
+++ b/src/export.rs
@@ -48,6 +48,28 @@ impl From for ExportError {
}
}
+pub struct ExportArgs {
+ pub no_resize: bool,
+ pub dim: Vec,
+}
+
+pub fn get_usvg(svg_str: &str) -> Result {
+ let usvg_options = Options::default();
+ Tree::from_str(svg_str, &usvg_options.to_ref())
+}
+
+pub fn get_xml(svg_str: &str) -> Result {
+ Element::parse(svg_str.as_bytes())
+}
+
+pub fn xml_to_str(svg_xml: &Element) -> Result {
+ let mut s: Vec = Vec::new();
+
+ svg_xml.write(&mut s)?;
+
+ Ok(String::from_utf8(s)?)
+}
+
fn get_new_bbox(svg: &Tree) -> Option<(f64, f64, f64, f64)> {
let bbox = svg.root().calculate_bbox()?;
@@ -70,25 +92,45 @@ fn get_new_bbox(svg: &Tree) -> Option<(f64, f64, f64, f64)> {
}
}
-fn get_usvg(svg_str: &str) -> Result {
- let usvg_options = Options::default();
- Tree::from_str(svg_str, &usvg_options.to_ref())
-}
+/// Removes all elements marked with `blobfox-ignore-size="true"`
-fn get_xml(svg_str: &str) -> Result {
- Element::parse(svg_str.as_bytes())
-}
+macro_rules! strip {
+ ( $name:tt, $attribute:expr ) => {
+ fn $name(svg_str: &str) -> Result {
+ let mut xml = get_xml(svg_str)?;
-fn xml_to_str(svg_xml: &Element) -> Result {
- let mut s: Vec = Vec::new();
+ fn rec(element: &mut Element) {
+ // TODO: replace with Vec::drain_filter once https://github.com/rust-lang/rust/issues/43244 gets merged
+ for child in std::mem::take(&mut element.children) {
+ match child {
+ XMLNode::Element(mut child) => {
+ if let Some("true") = child.attributes.get($attribute).map(|s| s.as_str()) {
+ continue
+ }
- svg_xml.write(&mut s)?;
+ rec(&mut child);
- Ok(String::from_utf8(s)?)
+ element.children.push(XMLNode::Element(child));
+ }
+ child => element.children.push(child),
+ }
+ }
+ }
+
+ rec(&mut xml);
+
+ xml_to_str(&xml)
+ }
+ }
}
+strip!(strip_ignore_size, "blobfox-ignore-size");
+strip!(strip_only_size, "blobfox-only-size");
+
pub fn resize(svg_str: String) -> Result {
- if let Some(new_bbox) = get_new_bbox(&get_usvg(&svg_str)?) {
+ let stripped = strip_ignore_size(&svg_str)?;
+
+ if let Some(new_bbox) = get_new_bbox(&get_usvg(&stripped)?) {
let mut svg_xml = get_xml(&svg_str)?;
svg_xml.attributes.insert(
"viewBox".to_string(),
@@ -144,12 +186,14 @@ pub fn export(
mut svg_str: String,
output_dir: &PathBuf,
output_name: String,
- args: &super::Args,
+ args: &ExportArgs,
) -> Result<(), ExportError> {
if !args.no_resize {
svg_str = resize(svg_str)?;
}
+ svg_str = strip_only_size(&svg_str)?;
+
svg_str = combine_defs(svg_str)?;
mkdirp::mkdirp(output_dir.join("vector")).unwrap();
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..6a4f2b2
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,3 @@
+pub mod parse;
+pub mod template;
+pub mod export;
diff --git a/src/main.rs b/src/main.rs
index b25f515..f063643 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,14 +1,11 @@
use clap::Parser;
use std::path::PathBuf;
-pub mod parse;
-use parse::*;
-
-pub mod template;
-use template::*;
-
-pub mod export;
-use export::*;
+use blobfox_template::{
+ parse::*,
+ template::*,
+ export::*,
+};
fn main() {
let args = Args::parse();
@@ -30,6 +27,8 @@ fn main() {
}
fn generate_variant(context: &RenderingContext, name: &str, output_dir: &PathBuf, args: &Args) {
+ let args: ExportArgs = args.clone().into();
+
if let Some(path) = context.species().variant_paths.get(name) {
match context.compile(path).and_then(|template| {
template.render_data_to_string(&context.get_data(name))
@@ -39,7 +38,7 @@ fn generate_variant(context: &RenderingContext, name: &str, output_dir: &PathBuf
svg,
output_dir,
format!("{}_{}", context.species().name, name),
- args
+ &args
) {
Ok(_) => {}
Err(err) => {
@@ -56,7 +55,7 @@ fn generate_variant(context: &RenderingContext, name: &str, output_dir: &PathBuf
}
}
-#[derive(Parser, Debug)]
+#[derive(Parser, Debug, Clone)]
#[clap(author, version, about, long_about = None)]
pub struct Args {
/// A folder containing the declaration from which the emotes should be generated
@@ -79,3 +78,12 @@ pub struct Args {
#[clap(short, long, value_parser)]
output_dir: Option,
}
+
+impl From for ExportArgs {
+ fn from(args: Args) -> ExportArgs {
+ ExportArgs {
+ no_resize: args.no_resize,
+ dim: args.dim,
+ }
+ }
+}
diff --git a/src/template.rs b/src/template.rs
index 293e10b..d71876f 100644
--- a/src/template.rs
+++ b/src/template.rs
@@ -1,9 +1,10 @@
-use super::*;
+use crate::parse::SpeciesDecl;
use mustache::{Context, Data, MapBuilder, PartialLoader, Template};
use std::collections::HashMap;
use std::path::Path;
use std::sync::{Arc, Mutex};
use xmltree::{Element, XMLNode};
+use css_color_parser::Color as CssColor;
#[derive(Debug, Clone)]
pub struct RenderingContext {
@@ -90,39 +91,45 @@ impl RenderingContext {
});
}
- let this = self.clone();
- let variant_name_owned = variant_name.to_string();
- 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, &variant_name_owned),
- this.render_to_string(&xml, &variant_name_owned),
- ) {
- // Convert `xml` to XML
- match Element::parse(xml.as_bytes()) {
- Ok(mut xml) => {
- set_fill(&color.trim(), &mut xml);
-
- // Render XML to string
- if let Some(res) = xml_to_string(xml) {
- res
- } else {
- String::from("")
+ for (cb, name) in [
+ (set_fill as fn(&str, &mut Element), "set-fill"),
+ (set_stroke, "set-stroke")
+ ] {
+ let this = self.clone();
+ let variant_name_owned = variant_name.to_string();
+
+ builder = builder.insert_fn(name, 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, &variant_name_owned),
+ this.render_to_string(&xml, &variant_name_owned),
+ ) {
+ // Convert `xml` to XML
+ match Element::parse(xml.as_bytes()) {
+ Ok(mut xml) => {
+ cb(&color.trim(), &mut xml);
+
+ // Render XML to string
+ if let Some(res) = xml_to_string(xml) {
+ res
+ } else {
+ String::from("")
+ }
+ }
+ Err(err) => {
+ format!("", err)
}
}
- Err(err) => {
- format!("", err)
- }
+ } else {
+ String::from("")
}
} else {
- String::from("")
+ String::from("")
}
- } else {
- String::from("")
- }
- });
+ });
+ }
builder = builder.insert("vars", &self.species.vars).unwrap();
@@ -236,34 +243,54 @@ impl PartialLoader for RenderingContext {
}
}
-fn set_fill(color: &str, xml: &mut Element) {
- // Substitute the fill color; TODO: handle transparency for SVG 1.1
- if let Some(style) = xml.attributes.get_mut("style") {
- let mut new_style = Vec::new();
+macro_rules! set_color {
+ ( $fn_name:tt, $color_name:expr, $opacity_name:expr ) => {
+ pub fn $fn_name(color: &str, xml: &mut Element) {
+ let (color, opacity) = if let Ok(parsed) = color.parse::() {
+ (format!("#{:02x}{:02x}{:02x}", parsed.r, parsed.g, parsed.b), parsed.a)
+ } else {
+ (color.to_string(), 1.0)
+ };
- for rule in style.split(';') {
- if let [name, value] = rule.splitn(2, ':').collect::>()[..] {
- if name.trim() != "fill" && name.trim() != "fill-opacity" {
- new_style.push(format!("{}:{}", name, value));
- }
- }
- }
+ fn rec(color: &str, opacity: f32, xml: &mut Element) {
+ if let Some(style) = xml.attributes.get_mut("style") {
+ let mut new_style = Vec::new();
+
+ for rule in style.split(';') {
+ if let [name, value] = rule.splitn(2, ':').collect::>()[..] {
+ if name.trim() != $color_name && name.trim() != $opacity_name {
+ new_style.push(format!("{}:{}", name, value));
+ }
+ }
+ }
- new_style.push(format!("fill: {};", color));
+ new_style.push(format!(concat!($color_name, ": {};"), color));
+ new_style.push(format!(concat!($opacity_name, ": {};"), opacity));
- *style = new_style.join(";");
- }
- if let Some(_fill) = xml.attributes.get("fill") {
- xml.attributes.insert("fill".to_string(), color.to_string());
- }
+ *style = new_style.join(";");
+ }
+ if let Some(_fill) = xml.attributes.get($color_name) {
+ xml.attributes.insert($color_name.to_string(), color.to_string());
+ }
+ if let Some(_fill) = xml.attributes.get($opacity_name) {
+ xml.attributes.insert($opacity_name.to_string(), opacity.to_string());
+ }
+
+ for child in xml.children.iter_mut() {
+ if let XMLNode::Element(ref mut child) = child {
+ rec(color, opacity, child);
+ }
+ }
+ }
- for child in xml.children.iter_mut() {
- if let XMLNode::Element(ref mut child) = child {
- set_fill(color, child);
+ rec(&color, opacity, xml)
}
}
}
+set_color!(set_fill, "fill", "fill-opacity");
+set_color!(set_stroke, "stroke", "stroke-opacity");
+
pub fn query_selector(svg: Element, pattern: &str) -> Option {
if pattern == "" {
// NOTE: it looks like having a nested svg makes resvg unhappy
diff --git a/vector/blobfox_snuggle_right.svg b/vector/blobfox_snuggle_right.svg
new file mode 100644
index 0000000..f7a2382
--- /dev/null
+++ b/vector/blobfox_snuggle_right.svg
@@ -0,0 +1,125 @@
+
+