Fix screenshot byte order conversion (critical bug)

The conversion functions were producing big-endian ARGB (A,R,G,B) but
Cairo's ARGB32 on little-endian systems expects B,G,R,A byte order.
This caused screenshots to appear completely corrupted (likely black or
solid color).

Fixed both convert_xbgr8888_to_argb32 and convert_xrgb8888_to_argb32:
- Xbgr8888: source [R,G,B,X] -> dest [B,G,R,A=255]
- Xrgb8888: source [B,G,R,X] -> dest [B,G,R,A=255]

Added detailed comments explaining memory layouts and conversion logic
to prevent future regressions.

This should make screenshots display correctly.
This commit is contained in:
2026-03-06 21:30:05 +01:00
parent 8aa84209a8
commit 1426b2d2d0
+22 -22
View File
@@ -273,34 +273,34 @@ impl ScreenshotManager {
}
}
/// Convert Xbgr8888 buffer data to ARGB32 format.
/// Convert Xbgr8888 buffer data to ARGB32 format (little-endian byte order).
/// Xbgr8888: 32-bit word 0xXXBBGGRR, memory layout: [R, G, B, X]
/// ARGB32: 32-bit word 0xAARRGGBB, memory layout: [B, G, R, A]
fn convert_xbgr8888_to_argb32(data: &[u8], width: usize, height: usize) -> Vec<u8> {
let mut result = vec![0u8; width * height * 4];
for y in 0..height {
for x in 0..width {
let src_idx = (y * width + x) * 4;
let dst_idx = (y * width + x) * 4;
result[dst_idx] = 255;
result[dst_idx + 1] = data[src_idx + 2];
result[dst_idx + 2] = data[src_idx + 1];
result[dst_idx + 3] = data[src_idx];
}
let mut result = Vec::with_capacity(width * height * 4);
for i in 0..width * height {
let src = i * 4;
// Source: [R, G, B, X] -> Destination: [B, G, R, A=255]
result.push(data[src + 2]); // B
result.push(data[src + 1]); // G
result.push(data[src]); // R
result.push(255); // A
}
result
}
/// Convert Xrgb8888 buffer data to ARGB32 format.
/// Convert Xrgb8888 buffer data to ARGB32 format (little-endian byte order).
/// Xrgb8888: 32-bit word 0xXXRRGGBB, memory layout: [B, G, R, X]
/// ARGB32: 32-bit word 0xAARRGGBB, memory layout: [B, G, R, A]
fn convert_xrgb8888_to_argb32(data: &[u8], width: usize, height: usize) -> Vec<u8> {
let mut result = vec![0u8; width * height * 4];
for y in 0..height {
for x in 0..width {
let src_idx = (y * width + x) * 4;
let dst_idx = (y * width + x) * 4;
result[dst_idx] = 255;
result[dst_idx + 1] = data[src_idx + 1];
result[dst_idx + 2] = data[src_idx + 2];
result[dst_idx + 3] = data[src_idx + 3];
}
let mut result = Vec::with_capacity(width * height * 4);
for i in 0..width * height {
let src = i * 4;
// Source: [B, G, R, X] -> Destination: [B, G, R, A=255]
result.push(data[src]); // B
result.push(data[src + 1]); // G
result.push(data[src + 2]); // R
result.push(255); // A
}
result
}