Skip to content

Commit

Permalink
feat(cli): add option to make custom icon sizes, closes #5121 (#5246)
Browse files Browse the repository at this point in the history
Co-authored-by: Fabian-Lars <fabianlars@fabianlars.de>
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
  • Loading branch information
3 people committed Dec 27, 2022
1 parent f5305de commit 9d21441
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 19 deletions.
6 changes: 6 additions & 0 deletions .changes/custom-icon.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"cli.rs": minor
"cli.js": minor
---

Add `--png` option for the `icon` command to generate custom icon sizes.
68 changes: 49 additions & 19 deletions tooling/cli/src/icon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ struct IcnsEntry {
ostype: String,
}

struct PngTarget {
size: u32,
file_name: String,
}

impl PngTarget {
fn new(size: u32, file_name: impl Into<String>) -> Self {
Self {
size,
file_name: file_name.into(),
}
}
}

#[derive(Debug, Parser)]
#[clap(about = "Generates various icons for all major platforms")]
pub struct Options {
Expand All @@ -41,15 +55,18 @@ pub struct Options {
/// Default: 'icons' directory next to the tauri.conf.json file.
#[clap(short, long)]
output: Option<PathBuf>,

/// Custom PNG icon sizes to generate. When set, the default icons are not generated.
#[clap(short, long, use_value_delimiter = true)]
png: Option<Vec<u32>>,
}

pub fn command(options: Options) -> Result<()> {
let input = options.input;
let out_dir = options.output.unwrap_or_else(|| tauri_dir().join("icons"));
let png_icon_sizes = options.png.unwrap_or_default();
create_dir_all(&out_dir).context("Can't create output directory")?;

// Try to read the image as a DynamicImage, convert it to rgba8 and turn it into a DynamicImage again.
// Both things should be catched by the explicit conversions to rgba8 anyway.
let source = open(input)
.context("Can't read and decode source image")?
.into_rgba8();
Expand All @@ -60,13 +77,32 @@ pub fn command(options: Options) -> Result<()> {
panic!("Source image must be square");
}

appx(&source, &out_dir).context("Failed to generate appx icons")?;

icns(&source, &out_dir).context("Failed to generate .icns file")?;

ico(&source, &out_dir).context("Failed to generate .ico file")?;

png(&source, &out_dir).context("Failed to generate png icons")?;
if png_icon_sizes.is_empty() {
appx(&source, &out_dir).context("Failed to generate appx icons")?;
icns(&source, &out_dir).context("Failed to generate .icns file")?;
ico(&source, &out_dir).context("Failed to generate .ico file")?;

let mut png_targets = vec![
PngTarget::new(256, "128x128@2x.png"),
PngTarget::new(512, "icon.png"),
];
png_targets.extend(
[32, 128]
.into_iter()
.map(|size| PngTarget::new(size, format!("{}x{}.png", size, size)))
.collect::<Vec<PngTarget>>(),
);
png(&source, &out_dir, png_targets).context("Failed to generate png icons")?;
} else {
png(
&source,
&out_dir,
png_icon_sizes
.into_iter()
.map(|size| PngTarget::new(size, format!("{}x{}.png", size, size)))
.collect(),
)?;
}

Ok(())
}
Expand Down Expand Up @@ -154,16 +190,10 @@ fn ico(source: &DynamicImage, out_dir: &Path) -> Result<()> {

// Generate .png files in 32x32, 128x128, 256x256, 512x512 (icon.png)
// Main target: Linux
fn png(source: &DynamicImage, out_dir: &Path) -> Result<()> {
for size in [32, 128, 256, 512] {
let file_name = match size {
256 => "128x128@2x.png".to_string(),
512 => "icon.png".to_string(),
_ => format!("{size}x{size}.png"),
};

log::info!(action = "PNG"; "Creating {}", file_name);
resize_and_save_png(source, size, &out_dir.join(&file_name))?;
fn png(source: &DynamicImage, out_dir: &Path, targets: Vec<PngTarget>) -> Result<()> {
for target in targets {
log::info!(action = "PNG"; "Creating {}", target.file_name);
resize_and_save_png(source, target.size, &out_dir.join(&target.file_name))?;
}

Ok(())
Expand Down

0 comments on commit 9d21441

Please sign in to comment.