use tiny_skia::{ Pixmap, PixmapPaint, Transform };
use crate::types::Rect;
use super::SoftwareCanvas;
impl SoftwareCanvas
{
pub fn draw_image_data( &mut self, rgba_data: &[u8], img_w: u32, img_h: u32, dest: Rect, opacity: f32 )
{
let expected = ( img_w as usize ).saturating_mul( img_h as usize ).saturating_mul( 4 );
if img_w == 0 || img_h == 0 || rgba_data.len() != expected
{
eprintln!(
"[ltk] SoftwareCanvas::draw_image_data: refusing draw — {}×{} declared, {} bytes provided, expected {}",
img_w, img_h, rgba_data.len(), expected,
);
return;
}
let Some( int_size ) = tiny_skia::IntSize::from_wh( img_w, img_h ) else { return };
thread_local! {
static PREMUL_BUF: std::cell::RefCell<Vec<u8>> = std::cell::RefCell::new( Vec::new() );
}
PREMUL_BUF.with( |cell|
{
let mut premul = cell.borrow_mut();
let needed = rgba_data.len();
premul.resize( needed, 0 );
for ( dst, src ) in premul.chunks_exact_mut( 4 ).zip( rgba_data.chunks_exact( 4 ) )
{
let a = (src[3] as f32 / 255.0) * opacity * self.global_alpha;
dst[0] = (src[0] as f32 * a) as u8;
dst[1] = (src[1] as f32 * a) as u8;
dst[2] = (src[2] as f32 * a) as u8;
dst[3] = (a * 255.0) as u8;
}
if let Some( src_pixmap ) = Pixmap::from_vec( std::mem::take( &mut *premul ), int_size )
{
let sx = dest.width / img_w as f32;
let sy = dest.height / img_h as f32;
let t = Transform::from_scale( sx, sy ).post_translate( dest.x, dest.y );
let paint = PixmapPaint
{
quality: tiny_skia::FilterQuality::Bilinear,
..PixmapPaint::default()
};
self.pixmap.draw_pixmap( 0, 0, src_pixmap.as_ref(), &paint, t, self.clip_mask.as_ref() );
*premul = src_pixmap.take();
}
} );
}
pub fn write_to_wayland_buf( &self, buf: &mut [u8], swap_rb: bool )
{
let src = self.pixmap.data();
let len = src.len().min( buf.len() );
if !swap_rb
{
buf[..len].copy_from_slice( &src[..len] );
return;
}
let chunks = len / 16;
let remainder = len % 16;
let mut i = 0;
for _ in 0..chunks
{
buf[i] = src[i + 2];
buf[i + 1] = src[i + 1];
buf[i + 2] = src[i];
buf[i + 3] = src[i + 3];
buf[i + 4] = src[i + 6];
buf[i + 5] = src[i + 5];
buf[i + 6] = src[i + 4];
buf[i + 7] = src[i + 7];
buf[i + 8] = src[i + 10];
buf[i + 9] = src[i + 9];
buf[i + 10] = src[i + 8];
buf[i + 11] = src[i + 11];
buf[i + 12] = src[i + 14];
buf[i + 13] = src[i + 13];
buf[i + 14] = src[i + 12];
buf[i + 15] = src[i + 15];
i += 16;
}
for _ in 0..(remainder / 4)
{
buf[i] = src[i + 2];
buf[i + 1] = src[i + 1];
buf[i + 2] = src[i];
buf[i + 3] = src[i + 3];
i += 4;
}
}
}