Merge pull request #2038 from denisg0mes/clipboard-png-decode

M7: #1360 follow-up: decode a clipboard PNG before pasting it
This commit is contained in:
BFlat
2026-11-07 09:03:29 +08:00
committed by GitHub
2 changed files with 23 additions and 5 deletions
+8 -5
View File
@@ -129,9 +129,6 @@ fn clipboard_png(app: &mut FigApp) -> Option<(Vec<u8>, f64, f64)> {
Some(readable) => readable,
None => with_pixel_size(encoded_clipboard_image(app)?)?,
};
if w == 0 || h == 0 || u64::from(w) * u64::from(h) > MAX_PASTED_IMAGE_PIXELS {
return None;
}
let density = figcraft_format::pixel_density(&png);
let (w, h) = figcraft_format::placed_size(w, h, density, figcraft_engine::cmd::create::PLACED_IMAGE_MAX_SIDE);
Some((png, w, h))
@@ -140,8 +137,14 @@ fn clipboard_png(app: &mut FigApp) -> Option<(Vec<u8>, f64, f64)> {
const MAX_PASTED_IMAGE_PIXELS: u64 = 100_000_000;
fn with_pixel_size(png: Vec<u8>) -> Option<(Vec<u8>, (u32, u32))> {
let size = image::ImageReader::new(std::io::Cursor::new(&png)).with_guessed_format().ok()?.into_dimensions().ok()?;
Some((png, size))
use image::ImageDecoder as _;
let decoder = image::ImageReader::new(std::io::Cursor::new(&png)).with_guessed_format().ok()?.into_decoder().ok()?;
let (w, h) = decoder.dimensions();
if w == 0 || h == 0 || u64::from(w) * u64::from(h) > MAX_PASTED_IMAGE_PIXELS {
return None;
}
image::DynamicImage::from_decoder(decoder).ok()?;
Some((png, (w, h)))
}
fn encoded_clipboard_image(app: &mut FigApp) -> Option<Vec<u8>> {
+15
View File
@@ -549,3 +549,18 @@ fn a_clipboard_png_past_the_byte_limit_falls_back_to_the_decoded_image() {
let pasted = doc.nodes().find(|n| n.name == "Pasted image").expect("pasted from the decoded image");
assert_eq!((pasted.width, pasted.height), (2.0, 2.0));
}
#[test]
fn a_clipboard_png_with_a_cut_off_body_falls_back_to_the_decoded_image() {
let mut w = Win::new();
let mut png = std::io::Cursor::new(Vec::new());
image::RgbaImage::new(4, 4).write_to(&mut png, image::ImageFormat::Png).unwrap();
let png = png.into_inner();
let cut_off = png[..png.len() - 20].to_vec();
assert_eq!(image::ImageReader::new(std::io::Cursor::new(&cut_off)).with_guessed_format().unwrap().into_dimensions().unwrap(), (4, 4));
*w.clip.borrow_mut() = Clip { png: Some(cut_off), image: Some((2, 2, vec![255; 16])), ..Clip::default() };
w.cmd_v();
let doc = w.app.session.doc().unwrap();
let pasted = doc.nodes().find(|n| n.name == "Pasted image").expect("pasted from the decoded image");
assert_eq!((pasted.width, pasted.height), (2.0, 2.0));
}