Jelajahi Sumber

fix(core): performance when generating code for default window icon (#3633)

Lucas Fernandes Nogueira 3 tahun lalu
induk
melakukan
96a2040076
1 mengubah file dengan 67 tambahan dan 8 penghapusan
  1. 67 8
      core/tauri-codegen/src/context.rs

+ 67 - 8
core/tauri-codegen/src/context.rs

@@ -164,6 +164,19 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
     _ => unimplemented!(),
   };
 
+  #[cfg(any(windows, target_os = "linux"))]
+  let out_dir = {
+    let out_dir = std::env::var("OUT_DIR")
+      .map_err(|_| EmbeddedAssetsError::OutDir)
+      .map(PathBuf::from)
+      .and_then(|p| p.canonicalize().map_err(|_| EmbeddedAssetsError::OutDir))?;
+
+    // make sure that our output directory is created
+    std::fs::create_dir_all(&out_dir).map_err(|_| EmbeddedAssetsError::OutDir)?;
+
+    out_dir
+  };
+
   // handle default window icons for Windows targets
   #[cfg(windows)]
   let default_window_icon = {
@@ -173,7 +186,7 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
       |i| i.ends_with(".ico"),
       "icons/icon.ico",
     );
-    ico_icon(&root, icon_path)
+    ico_icon(&root, &out_dir, icon_path)?
   };
   #[cfg(target_os = "linux")]
   let default_window_icon = {
@@ -183,7 +196,7 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
       |i| i.ends_with(".png"),
       "icons/icon.png",
     );
-    png_icon(&root, icon_path)
+    png_icon(&root, &out_dir, icon_path)?
   };
   #[cfg(not(any(windows, target_os = "linux")))]
   let default_window_icon = quote!(None);
@@ -341,7 +354,14 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
 }
 
 #[cfg(windows)]
-fn ico_icon<P: AsRef<Path>>(root: &TokenStream, path: P) -> TokenStream {
+fn ico_icon<P: AsRef<Path>>(
+  root: &TokenStream,
+  out_dir: &Path,
+  path: P,
+) -> Result<TokenStream, EmbeddedAssetsError> {
+  use std::fs::File;
+  use std::io::Write;
+
   let path = path.as_ref();
   let bytes = std::fs::read(&path)
     .unwrap_or_else(|_| panic!("failed to read window icon {}", path.display()))
@@ -356,12 +376,35 @@ fn ico_icon<P: AsRef<Path>>(root: &TokenStream, path: P) -> TokenStream {
     .to_vec();
   let width = entry.width();
   let height = entry.height();
-  let rgba_items = rgba.into_iter();
-  quote!(Some(#root::Icon::Rgba { rgba: vec![#(#rgba_items),*], width: #width, height: #height }))
+
+  let out_path = out_dir.join(path.file_name().unwrap());
+  let mut out_file = File::create(&out_path).map_err(|error| EmbeddedAssetsError::AssetWrite {
+    path: out_path.clone(),
+    error,
+  })?;
+
+  out_file
+    .write_all(&rgba)
+    .map_err(|error| EmbeddedAssetsError::AssetWrite {
+      path: path.to_owned(),
+      error,
+    })?;
+
+  let out_path = out_path.display().to_string();
+
+  let icon = quote!(Some(#root::Icon::Rgba { rgba: include_bytes!(#out_path).to_vec(), width: #width, height: #height }));
+  Ok(icon)
 }
 
 #[cfg(target_os = "linux")]
-fn png_icon<P: AsRef<Path>>(root: &TokenStream, path: P) -> TokenStream {
+fn png_icon<P: AsRef<Path>>(
+  root: &TokenStream,
+  out_dir: &Path,
+  path: P,
+) -> Result<TokenStream, EmbeddedAssetsError> {
+  use std::fs::File;
+  use std::io::Write;
+
   let path = path.as_ref();
   let bytes = std::fs::read(&path)
     .unwrap_or_else(|_| panic!("failed to read window icon {}", path.display()))
@@ -374,10 +417,26 @@ fn png_icon<P: AsRef<Path>>(root: &TokenStream, path: P) -> TokenStream {
   while let Ok(Some(row)) = reader.next_row() {
     buffer.extend(row);
   }
-  let rgba_items = buffer.into_iter();
   let width = info.width;
   let height = info.height;
-  quote!(Some(#root::Icon::Rgba { rgba: vec![#(#rgba_items),*], width: #width, height: #height }))
+
+  let out_path = out_dir.join(path.file_name().unwrap());
+  let mut out_file = File::create(&out_path).map_err(|error| EmbeddedAssetsError::AssetWrite {
+    path: out_path.clone(),
+    error,
+  })?;
+
+  out_file
+    .write_all(&buffer)
+    .map_err(|error| EmbeddedAssetsError::AssetWrite {
+      path: path.to_owned(),
+      error,
+    })?;
+
+  let out_path = out_path.display().to_string();
+
+  let icon = quote!(Some(#root::Icon::Rgba { rgba: include_bytes!(#out_path).to_vec(), width: #width, height: #height }));
+  Ok(icon)
 }
 
 #[cfg(any(windows, target_os = "linux"))]