summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock52
-rw-r--r--Cargo.toml7
-rw-r--r--src/main.rs104
-rw-r--r--src/xcursor.rs23
4 files changed, 140 insertions, 46 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c9ed517..9727ba7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -30,6 +30,7 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
name = "batacli"
version = "0.1.0"
dependencies = [
+ "rayon",
"resvg",
"serde",
"serde_json",
@@ -92,12 +93,43 @@ dependencies = [
]
[[package]]
+name = "crossbeam-deque"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
+
+[[package]]
name = "data-url"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a"
[[package]]
+name = "either"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
+[[package]]
name = "fdeflate"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -274,6 +306,26 @@ dependencies = [
]
[[package]]
+name = "rayon"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
+dependencies = [
+ "crossbeam-deque",
+ "crossbeam-utils",
+]
+
+[[package]]
name = "resvg"
version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 41d2cf0..97dafb1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
+rayon = "1.11.0"
resvg = "0.44.0"
serde = { version = "1.0.216", features = ["derive"] }
serde_json = "1.0.133"
@@ -14,3 +15,9 @@ usvg = "0.44.0"
lto = "fat"
codegen-units = 1
strip = "symbols"
+
+[features]
+default = ["overalloc"]
+
+# Potentially over-allocate xcursor vectors to gain performance
+overalloc = []
diff --git a/src/main.rs b/src/main.rs
index fed8090..912d0cc 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,6 @@
-use std::{fs, io::Result, os::unix};
+use std::{fs, io::Result, os::unix, sync::{Arc, RwLock}};
+use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use serde::{Deserialize, Serialize};
use tiny_skia::Pixmap;
use xcursor::{ImageInfo, XCursorEncoder};
@@ -102,40 +103,65 @@ fn process_xcursor(
desired_sizes: Vec<u16>,
time_scale: u32,
) -> Vec<u8> {
- let mut image_info_vec: Vec<ImageInfo> = Vec::new();
- for cursor_frame in cursor.frames {
- for desired_size in &desired_sizes {
- let svg_data = apply_colours(
- resize_cursvg(&cursor_frame.svg, desired_size),
- &desired_colours,
- );
- let pixmap = vector_to_pixmap(svg_data.as_bytes());
-
- let pixels = {
- let pixels = pixmap.pixels();
- let mut otherpixels: Vec<u8> = Vec::new();
- for elem in pixels.iter() {
- otherpixels.push(elem.red());
- otherpixels.push(elem.green());
- otherpixels.push(elem.blue());
- otherpixels.push(elem.alpha());
+ let size = cursor.frames.len() * desired_sizes.len();
+ let image_info_vec: Arc<RwLock<Vec<ImageInfo>>> = Arc::new(RwLock::new(vec![ImageInfo {
+ r#type: 0,
+ subtype: 0,
+ width: 0,
+ height: 0,
+ xhot: 0,
+ yhot: 0,
+ data: vec![],
+ delay: 0,
+ };size]));
+ let desired_colours = Arc::new(desired_colours);
+ let desired_sizes = Arc::new(desired_sizes);
+ rayon::scope(|s| {
+ let mut i=0;
+ for cursor_frame in cursor.frames {
+ let ouridx = i;
+ i+=1;
+ let image_info_vec = image_info_vec.clone();
+ let desired_colours = desired_colours.clone();
+ let desired_sizes = desired_sizes.clone();
+ s.spawn(move |_| {
+ for desired_size in &desired_sizes.to_vec() {
+ let svg_data = apply_colours(
+ resize_cursvg(&cursor_frame.svg, desired_size),
+ &desired_colours,
+ );
+ let pixmap = vector_to_pixmap(svg_data.as_bytes());
+
+ let pixels = {
+ let pixels = pixmap.pixels();
+ let mut otherpixels: Vec<u8> = Vec::new();
+ for elem in pixels.iter() {
+ otherpixels.push(elem.red());
+ otherpixels.push(elem.green());
+ otherpixels.push(elem.blue());
+ otherpixels.push(elem.alpha());
+ }
+ otherpixels
+ };
+ let image_info = ImageInfo {
+ r#type: *desired_size as u32,
+ subtype: *desired_size as u32,
+ width: pixmap.width().try_into().unwrap(),
+ height: pixmap.height().try_into().unwrap(),
+ xhot: (cursor.hot.x * pixmap.width() / 256).try_into().unwrap(),
+ yhot: (cursor.hot.y * pixmap.height() / 256).try_into().unwrap(),
+ data: pixels.try_into().unwrap(),
+ delay: (time_scale / cursor_frame.delay).try_into().unwrap(),
+ };
+ {
+ let mut image_info_vec = image_info_vec.write().unwrap();
+ image_info_vec[ouridx] = image_info;
+ }
}
- otherpixels
- };
- let image_info = ImageInfo {
- r#type: *desired_size as u32,
- subtype: *desired_size as u32,
- width: pixmap.width().try_into().unwrap(),
- height: pixmap.height().try_into().unwrap(),
- xhot: (cursor.hot.x * pixmap.width() / 256).try_into().unwrap(),
- yhot: (cursor.hot.y * pixmap.height() / 256).try_into().unwrap(),
- data: pixels.try_into().unwrap(),
- delay: (time_scale / cursor_frame.delay).try_into().unwrap(),
- };
- image_info_vec.push(image_info);
+ });
}
- }
- let mut encoder = XCursorEncoder::new(image_info_vec);
+ });
+ let mut encoder = XCursorEncoder::new(image_info_vec.read().unwrap().to_vec());
encoder.pack()
}
@@ -150,7 +176,7 @@ fn main() -> Result<()> {
fs::create_dir("xcursor-out")?;
for style in cursor_style {
fs::create_dir(format!("xcursor-out/{}", style.kind))?;
- for cursor in style.cursors {
+ let c: usize = style.cursors.par_iter().map(|cursor|{
println!("xcursor-out/{}/{}", style.kind, cursor.name.clone());
// shove these files in a dir named `cursors` inside the theme dir
// the theme dir should have these 2 files in it:
@@ -185,14 +211,16 @@ fn main() -> Result<()> {
],
750,
),
- )?;
- for alias in cursor.aliases {
+ ).unwrap();
+ for alias in cursor.aliases.clone() {
unix::fs::symlink(
cursor.name.clone(),
format!("xcursor-out/{}/{}", style.kind, alias),
- )?;
+ ).unwrap();
}
- }
+ 1
+ }).sum();
+ println!("Generated {c} cursors");
}
Ok(())
diff --git a/src/xcursor.rs b/src/xcursor.rs
index ff6c3d6..8d329bf 100644
--- a/src/xcursor.rs
+++ b/src/xcursor.rs
@@ -31,11 +31,14 @@ impl XCursorEncoder {
}
pub fn pack(&mut self) -> Vec<u8> {
- fn insert_bytes(data: &mut Vec<u8>, new_data: impl IntoIterator<Item = u8>) {
- for int in new_data {
- data.push(int);
- }
+ fn insert_bytes(data: &mut Vec<u8>, new_data: &[u8]) {
+ data.extend_from_slice(new_data);
}
+ // fn insert_iterated(data: &mut Vec<u8>, new_data: impl IntoIterator<Item = u8>) {
+ // for int in new_data {
+ // data.push(int);
+ // }
+ // }
fn insert_int(data: &mut Vec<u8>, int: u32) {
data.push((int & 0xff) as u8);
data.push(((int >> 8) & 0xff) as u8);
@@ -44,11 +47,15 @@ impl XCursorEncoder {
}
let mut data: Vec<u8> = Vec::new();
+ #[cfg(feature="overalloc")]
+ data.reserve(
+ 4194304
+ );
// File Header
{
// MAGIC string ("Xcur")
- insert_bytes(&mut data, MAGIC);
+ insert_bytes(&mut data, &MAGIC);
// CARD32 bytes in this header
insert_int(&mut data, 16);
// CARD32 file version
@@ -62,7 +69,7 @@ impl XCursorEncoder {
let mut img_idx: usize = 0;
for img in self.images.clone().into_iter() {
// Some header
- insert_bytes(&mut data, IMAGE_HEADER);
+ insert_bytes(&mut data, &IMAGE_HEADER);
// CARD32 type-specific label - size for images
insert_int(&mut data, img.r#type);
// CARD32 absolute byte position of table in file
@@ -78,7 +85,7 @@ impl XCursorEncoder {
// Header Size (36)
insert_int(&mut data, 36);
// Image Type
- insert_bytes(&mut data, IMAGE_HEADER);
+ insert_bytes(&mut data, &IMAGE_HEADER);
// Subtype, for nominal size
insert_int(&mut data, img.subtype);
// Version
@@ -92,7 +99,7 @@ impl XCursorEncoder {
// Milliseconds till next frame
insert_int(&mut data, img.delay);
// Raw image data
- insert_bytes(&mut data, img.data);
+ insert_bytes(&mut data, &img.data);
}
}