summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatarLarge Libravatar memdmp <memdmpestrogenzone>2026-01-25 16:31:33 +0100
committerLibravatarLarge Libravatar memdmp <memdmpestrogenzone>2026-01-25 16:31:33 +0100
commit6ae2681aa1abc1fa447d64d2a269878e29b1d904 (patch)
treec2069ee898a2d30c8eab1ddde36691653d6abb93 /src
parent6e3b3c8013e6d8814dbf70c854e55d062bedbdf4 (diff)
downloadbibata-cursor-cli-6ae2681aa1abc1fa447d64d2a269878e29b1d904.tar.gz
bibata-cursor-cli-6ae2681aa1abc1fa447d64d2a269878e29b1d904.tar.bz2
bibata-cursor-cli-6ae2681aa1abc1fa447d64d2a269878e29b1d904.tar.lz
bibata-cursor-cli-6ae2681aa1abc1fa447d64d2a269878e29b1d904.zip

feat: paralllelism, memory overcommitment to save on repeated mallocs

Diffstat (limited to 'src')
-rw-r--r--src/main.rs104
-rw-r--r--src/xcursor.rs23
2 files changed, 81 insertions, 46 deletions
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);
}
}