From 6aaefc05469649edbf39d90d2a570eef76d8a41e Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Tue, 30 Jan 2024 18:03:21 +0400 Subject: [PATCH 1/2] On Wayland, pre-multiply alpha for custom cursor Fixes: #3360 --- examples/custom_cursors.rs | 3 ++- examples/data/gradient.png | Bin 0 -> 229 bytes src/platform_impl/linux/wayland/types/cursor.rs | 15 +++++++++------ 3 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 examples/data/gradient.png diff --git a/examples/custom_cursors.rs b/examples/custom_cursors.rs index fda157ff5a..0d0fb4469f 100644 --- a/examples/custom_cursors.rs +++ b/examples/custom_cursors.rs @@ -56,6 +56,7 @@ fn main() -> Result<(), impl std::error::Error> { let custom_cursors = [ decode_cursor(include_bytes!("data/cross.png"), &event_loop), decode_cursor(include_bytes!("data/cross2.png"), &event_loop), + decode_cursor(include_bytes!("data/gradient.png"), &event_loop), ]; event_loop.run(move |event, _elwt| match event { @@ -72,7 +73,7 @@ fn main() -> Result<(), impl std::error::Error> { Key::Character("1") => { log::debug!("Setting cursor to {:?}", cursor_idx); window.set_cursor(custom_cursors[cursor_idx].clone()); - cursor_idx = (cursor_idx + 1) % 2; + cursor_idx = (cursor_idx + 1) % 3; } Key::Character("2") => { log::debug!("Setting cursor icon to default"); diff --git a/examples/data/gradient.png b/examples/data/gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..41ce610e66221b0803d20b0dcca6f9215745ac3b GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ydl>XLo80uophJ$kO7aI|Ep(n z9Hm@k-Dg%N d=dCrYVq|Yu-*G2OKmq7(22WQ%mvv4FO#tkjTQ&dy literal 0 HcmV?d00001 diff --git a/src/platform_impl/linux/wayland/types/cursor.rs b/src/platform_impl/linux/wayland/types/cursor.rs index 4af996f6f3..c1a0c2613a 100644 --- a/src/platform_impl/linux/wayland/types/cursor.rs +++ b/src/platform_impl/linux/wayland/types/cursor.rs @@ -37,12 +37,15 @@ impl CustomCursor { ) .unwrap(); - for (canvas_chunk, rgba_chunk) in canvas.chunks_exact_mut(4).zip(image.rgba.chunks_exact(4)) - { - canvas_chunk[0] = rgba_chunk[2]; - canvas_chunk[1] = rgba_chunk[1]; - canvas_chunk[2] = rgba_chunk[0]; - canvas_chunk[3] = rgba_chunk[3]; + for (canvas_chunk, rgba) in canvas.chunks_exact_mut(4).zip(image.rgba.chunks_exact(4)) { + // Alpha in buffer is premultiplied. + let alpha = rgba[3] as f32 / 255.; + let r = (rgba[0] as f32 * alpha) as u32; + let g = (rgba[1] as f32 * alpha) as u32; + let b = (rgba[2] as f32 * alpha) as u32; + let color = ((rgba[3] as u32) << 24) + (r << 16) + (g << 8) + b; + let array: &mut [u8; 4] = canvas_chunk.try_into().unwrap(); + *array = color.to_le_bytes(); } CustomCursor { From f2fdb12e1045bb4e118cb4fd72edd991c3508691 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Tue, 30 Jan 2024 18:25:05 +0400 Subject: [PATCH 2/2] Specify that alpha channel is not premultiplied --- src/cursor.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cursor.rs b/src/cursor.rs index e1ed4622dc..b519b579fb 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -83,6 +83,8 @@ pub struct CustomCursor { impl CustomCursor { /// Creates a new cursor from an rgba buffer. + /// + /// The alpha channel is assumed to be **not** premultiplied. pub fn from_rgba( rgba: impl Into>, width: u16,