Archived
add canvas_image builtin for PNG rendering with alpha blending
Registers canvas_image(path, x, y, w, h) in the type system and implements it in the interpreter using the image crate — scales to exact dimensions via Lanczos3 and alpha-composites onto the pixmap.
This commit is contained in:
@@ -4724,6 +4724,50 @@ fn dispatch_builtin(
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
"canvas_image" => {
|
||||
// canvas_image(path: String, x: Int, y: Int, w: Int, h: Int) -> Void
|
||||
// Draws a PNG image scaled to w×h at (x, y) with alpha blending.
|
||||
let draw_h = match stack.pop().unwrap_or(Value::Nil) { Value::Int(n) => n as i32, _ => 0 };
|
||||
let draw_w = match stack.pop().unwrap_or(Value::Nil) { Value::Int(n) => n as i32, _ => 0 };
|
||||
let dy = match stack.pop().unwrap_or(Value::Nil) { Value::Int(n) => n as i32, _ => 0 };
|
||||
let dx = match stack.pop().unwrap_or(Value::Nil) { Value::Int(n) => n as i32, _ => 0 };
|
||||
let path = match stack.pop().unwrap_or(Value::Nil) { Value::Str(s) => s, _ => { stack.push(Value::Nil); return BuiltinResult::Handled; } };
|
||||
|
||||
if draw_w <= 0 || draw_h <= 0 { stack.push(Value::Nil); return BuiltinResult::Handled; }
|
||||
|
||||
use image::GenericImageView;
|
||||
if let Ok(img) = image::open(&path) {
|
||||
let img = img.resize_exact(draw_w as u32, draw_h as u32, image::imageops::FilterType::Lanczos3);
|
||||
let rgba = img.to_rgba8();
|
||||
CANVAS.with(|cv| {
|
||||
let mut cv = cv.borrow_mut();
|
||||
if let Some(px) = cv.pixmap.as_mut() {
|
||||
let pw = px.width() as i32;
|
||||
let ph = px.height() as i32;
|
||||
let data = px.data_mut();
|
||||
for row in 0..draw_h {
|
||||
for col in 0..draw_w {
|
||||
let ix = dx + col;
|
||||
let iy = dy + row;
|
||||
if ix < 0 || iy < 0 || ix >= pw || iy >= ph { continue; }
|
||||
let p = rgba.get_pixel(col as u32, row as u32);
|
||||
let sa = p[3] as u32;
|
||||
if sa == 0 { continue; }
|
||||
let ia = 255 - sa;
|
||||
let idx = (iy as usize * pw as usize + ix as usize) * 4;
|
||||
data[idx] = ((ia * data[idx] as u32 + sa * p[0] as u32) / 255) as u8;
|
||||
data[idx + 1] = ((ia * data[idx+1] as u32 + sa * p[1] as u32) / 255) as u8;
|
||||
data[idx + 2] = ((ia * data[idx+2] as u32 + sa * p[2] as u32) / 255) as u8;
|
||||
data[idx + 3] = ((ia * data[idx+3] as u32 + sa * sa) / 255) as u8;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
stack.push(Value::Nil);
|
||||
BuiltinResult::Handled
|
||||
}
|
||||
|
||||
_ => BuiltinResult::NotBuiltin,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user