Merge pull request #5399 from storytold/fix/sec-followup-5301

Copy: a PNG too large to make is not offered, and the status bar says why
This commit is contained in:
BFlat
2026-11-03 23:14:09 +07:00
committed by GitHub
28 changed files with 51 additions and 15 deletions
+21 -13
View File
@@ -127,6 +127,8 @@ pub struct Flavour {
const COPY_PNG_SIDE: f64 = 4096.0;
/// The smallest scale (pixels a point) the PNG encoder renders at.
const MIN_COPY_PNG_SCALE: f64 = 0.01;
/// What Copy says when the art is too large for its PNG.
const TOO_LARGE_FOR_PNG: &str = "The art is too large to copy as a picture: other apps get no PNG of it";
/// Most bytes of text `clipboard.importText` takes.
const MAX_TEXT: usize = 1 << 20;
/// Most bytes of images the SVG markup may embed and still go out as plain text. A paste reads the
@@ -290,7 +292,18 @@ impl Clipboard {
let text = (svg && self.image_bytes() <= COPY_TEXT_IMAGE_BYTES) || self.nodes.iter().all(type_only);
// Art without an area (a lone guide-like line) has no page or picture.
let area = self.bounds().is_some_and(|b| b.width() > 0.0 && b.height() > 0.0);
[(TEXT, text), (SVG, svg), (PDF, pdf && area), (PNG, area)].into_iter().filter_map(|(m, on)| on.then_some(m)).collect()
[(TEXT, text), (SVG, svg), (PDF, pdf && area), (PNG, area && self.png_scale().is_some())]
.into_iter()
.filter_map(|(m, on)| on.then_some(m))
.collect()
}
/// The scale (pixels a point) of the PNG Copy offers: at most [`COPY_PNG_SIDE`] pixels a side,
/// and `None` when even [`MIN_COPY_PNG_SCALE`], the encoder's smallest, can't bring it that small
/// (rather than a PNG of up to a gigabyte of pixels).
fn png_scale(&self) -> Option<f64> {
let side = self.bounds().map_or(1.0, |b| b.width().max(b.height()));
Some((COPY_PNG_SIDE / side).min(1.0)).filter(|s| *s >= MIN_COPY_PNG_SCALE)
}
/// What Copy offers other apps, best first, with Include SVG Code (`svg`) and On Copy: PDF
@@ -308,6 +321,9 @@ impl Clipboard {
let svg = types.contains(&SVG).then(|| self.svg()).flatten();
let mut out = vec![];
let mut warnings: Vec<String> = vec![];
if !self.is_empty() && self.png_scale().is_none() {
warnings.push(TOO_LARGE_FOR_PNG.to_string());
}
let mut keep = |(bytes, notes): (Vec<u8>, Vec<String>)| {
for w in notes {
if !warnings.contains(&w) {
@@ -321,18 +337,10 @@ impl Clipboard {
TEXT => self.text().or_else(|| svg.clone()).map(String::into_bytes),
SVG => svg.clone().map(String::into_bytes),
PDF => self.pdf().inspect_err(|e| log::warn!("clipboard PDF: {e}")).ok().flatten().map(&mut keep),
_ => {
let side = self.bounds().map_or(1.0, |b| b.width().max(b.height()));
let scale = (COPY_PNG_SIDE / side).min(1.0);
// The encoder renders at no fewer than MIN_COPY_PNG_SCALE pixels a point: art
// too large to fit COPY_PNG_SIDE at that scale gets no PNG, rather than one
// of up to a gigabyte of pixels.
if scale < MIN_COPY_PNG_SCALE {
log::warn!("clipboard PNG: art {side} pt across is too large to copy as a picture");
continue;
}
self.png(scale).inspect_err(|e| log::warn!("clipboard PNG: {e}")).ok().flatten().map(|(png, _, _, notes)| keep((png, notes)))
}
_ => self
.png_scale()
.and_then(|scale| self.png(scale).inspect_err(|e| log::warn!("clipboard PNG: {e}")).ok().flatten())
.map(|(png, _, _, notes)| keep((png, notes))),
};
out.extend(data.map(|data| Flavour { mime, data }));
}
+4 -2
View File
@@ -358,8 +358,10 @@ fn copy_leaves_out_the_png_of_art_too_large_to_scale_down() {
let id = run(&mut s, "shape.rectangle", json!({"x": 0, "y": 0, "width": 1_000_000, "height": 1_000_000}))["id"].clone();
run(&mut s, "select.set", json!({"ids": [id]}));
run(&mut s, "edit.copy", json!({}));
assert!(s.clipboard.flavour_types(false, false).contains(&PNG));
assert!(s.clipboard.flavours(false, false).iter().all(|f| f.mime != PNG));
assert!(!s.clipboard.flavour_types(false, false).contains(&PNG), "not offered either");
let (flavours, notes) = s.clipboard.flavours_with_warnings(false, false);
assert!(flavours.iter().all(|f| f.mime != PNG));
assert!(notes.iter().any(|n| n.contains("too large to copy as a picture")), "{notes:?}");
// Art that fits at that scale still gets its PNG, at most 4096 pixels a side.
let id = run(&mut s, "shape.rectangle", json!({"x": 0, "y": 0, "width": 200_000, "height": 100}))["id"].clone();
run(&mut s, "select.set", json!({"ids": [id]}));
+1
View File
@@ -6134,3 +6134,4 @@ breakText Glyphs Глифи
Bow Дъга
Spike Връх
Skip Spaces Пропускане на интервалите
@msg The art is too large to copy as a picture: other apps get no PNG of it Графиката е твърде голяма, за да се копира като изображение: другите приложения не получават PNG от нея
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6168,3 +6168,4 @@ shape Open Otvoren
Bow Luk
Spike Šiljak
Skip Spaces Preskoči razmake
@msg The art is too large to copy as a picture: other apps get no PNG of it Grafika je prevelika da bi se kopirala kao slika: druge aplikacije ne dobijaju njen PNG
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6268,3 +6268,4 @@ breakText Glyphs Glifs
Bow Arc
Spike Pic
Skip Spaces Omet els espais
@msg The art is too large to copy as a picture: other apps get no PNG of it La il·lustració és massa gran per copiar-la com a imatge: les altres aplicacions no en reben cap PNG
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6282,3 +6282,4 @@ breakText Glyphs Glyfy
Bow Oblouk
Spike Špička
Skip Spaces Přeskočit mezery
@msg The art is too large to copy as a picture: other apps get no PNG of it Kresba je příliš velká na zkopírování jako obrázek: ostatní aplikace z ní nedostanou PNG
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6150,3 +6150,4 @@ breakText Glyphs Glyffer
Bow Bue
Spike Spids
Skip Spaces Spring mellemrum over
@msg The art is too large to copy as a picture: other apps get no PNG of it Grafikken er for stor til at blive kopieret som et billede: andre programmer får ingen PNG af den
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -5868,3 +5868,4 @@ breakText Glyphs Glyphen
Bow Bogen
Spike Spitze
Skip Spaces Leerzeichen überspringen
@msg The art is too large to copy as a picture: other apps get no PNG of it Das Bildmaterial ist zu groß, um es als Bild zu kopieren: Andere Apps erhalten kein PNG davon
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6234,3 +6234,4 @@ breakText Glyphs Γλύφοι
Bow Τόξο
Spike Αιχμή
Skip Spaces Παράλειψη κενών
@msg The art is too large to copy as a picture: other apps get no PNG of it Το γραφικό είναι πολύ μεγάλο για αντιγραφή ως εικόνα: οι άλλες εφαρμογές δεν λαμβάνουν PNG του
Can't render this file because it contains an unexpected character in line 163 and column 5.
+1
View File
@@ -6224,3 +6224,4 @@ breakText Glyphs Glifos
Bow Arco
Spike Pico
Skip Spaces Omitir espacios
@msg The art is too large to copy as a picture: other apps get no PNG of it La ilustración es demasiado grande para copiarla como imagen: las demás aplicaciones no reciben un PNG de ella
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6312,3 +6312,4 @@ breakText Glyphs Merkit
Bow Kaari
Spike Piikki
Skip Spaces Ohita välilyönnit
@msg The art is too large to copy as a picture: other apps get no PNG of it Grafiikka on liian suuri kopioitavaksi kuvana: muut sovellukset eivät saa siitä PNG-kuvaa
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6277,3 +6277,4 @@ breakText Glyphs Glyphes
Bow Arc
Spike Pointe
Skip Spaces Ignorer les espaces
@msg The art is too large to copy as a picture: other apps get no PNG of it L’illustration est trop grande pour être copiée en tant qu’image : les autres applications n’en reçoivent pas de PNG
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6266,3 +6266,4 @@ breakText Glyphs Glifák
Bow Ív
Spike Csúcs
Skip Spaces Szóközök kihagyása
@msg The art is too large to copy as a picture: other apps get no PNG of it A grafika túl nagy ahhoz, hogy képként másolható legyen: más alkalmazások nem kapnak róla PNG-t
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6150,3 +6150,4 @@ breakText Glyphs Glif
Bow Busur
Spike Puncak
Skip Spaces Lewati Spasi
@msg The art is too large to copy as a picture: other apps get no PNG of it Gambar terlalu besar untuk disalin sebagai gambar: aplikasi lain tidak mendapatkan PNG darinya
Can't render this file because it contains an unexpected character in line 2211 and column 5.
+1
View File
@@ -5902,3 +5902,4 @@ breakText Glyphs Glifi
Bow Arco
Spike Picco
Skip Spaces Salta gli spazi
@msg The art is too large to copy as a picture: other apps get no PNG of it La grafica è troppo grande per essere copiata come immagine: le altre app non ne ricevono un PNG
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -5967,3 +5967,4 @@ breakText Glyphs 字形
Bow 弓形
Spike 山形
Skip Spaces スペースをスキップ
@msg The art is too large to copy as a picture: other apps get no PNG of it アートワークが大きすぎるため画像としてコピーできません:他のアプリには PNG が渡されません
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6270,3 +6270,4 @@ breakText Glyphs გლიფები
Bow რკალი
Spike პიკი
Skip Spaces ჰარების გამოტოვება
@msg The art is too large to copy as a picture: other apps get no PNG of it ნახატი ზედმეტად დიდია სურათად დასაკოპირებლად: სხვა აპები მის PNG-ს ვერ მიიღებენ
Can't render this file because it is too large.
+1
View File
@@ -5863,3 +5863,4 @@ breakText Glyphs 글리프
Bow 활 모양
Spike 뾰족한 모양
Skip Spaces 공백 건너뛰기
@msg The art is too large to copy as a picture: other apps get no PNG of it 아트워크가 너무 커서 이미지로 복사할 수 없습니다: 다른 앱에는 PNG가 전달되지 않습니다
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6194,3 +6194,4 @@ breakText Glyphs Glyphs
Bow Boog
Spike Piek
Skip Spaces Spaties overslaan
@msg The art is too large to copy as a picture: other apps get no PNG of it Het illustratiewerk is te groot om als afbeelding te kopiëren: andere apps krijgen er geen PNG van
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6137,3 +6137,4 @@ breakText Glyphs Glify
Bow Łuk
Spike Szpic
Skip Spaces Pomiń spacje
@msg The art is too large to copy as a picture: other apps get no PNG of it Grafika jest zbyt duża, aby skopiować ją jako obraz: inne aplikacje nie otrzymają jej w formacie PNG
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6355,3 +6355,4 @@ swatch Yellow Green Verde-amarelado
Bow Arco
Spike Pico
Skip Spaces Ignorar espaços
@msg The art is too large to copy as a picture: other apps get no PNG of it A arte é grande demais para ser copiada como imagem: outros aplicativos não recebem um PNG dela
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1
View File
@@ -6371,3 +6371,4 @@ shape Open Открытый
Bow Дуга
Spike Пик
Skip Spaces Пропускать пробелы
@msg The art is too large to copy as a picture: other apps get no PNG of it Графика слишком велика для копирования в виде изображения: другие приложения не получат её PNG
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -6338,3 +6338,4 @@ digits Hindi Hindi
Bow Båge
Spike Spets
Skip Spaces Hoppa över mellanslag
@msg The art is too large to copy as a picture: other apps get no PNG of it Teckningen är för stor för att kopieras som en bild: andra appar får ingen PNG av den
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -6239,3 +6239,4 @@ breakText Glyphs Glifler
Bow Yay
Spike Sivri Uç
Skip Spaces Boşlukları Atla
@msg The art is too large to copy as a picture: other apps get no PNG of it Çizim, resim olarak kopyalanamayacak kadar büyük: diğer uygulamalar bunun PNG'sini almaz
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -5882,3 +5882,4 @@ breakText Glyphs Гліфи
Bow Дуга
Spike Пік
Skip Spaces Пропускати пробіли
@msg The art is too large to copy as a picture: other apps get no PNG of it Графіка завелика, щоб скопіювати її як зображення: інші програми не отримають її PNG
Can't render this file because it contains an unexpected character in line 177 and column 5.
+1
View File
@@ -5883,3 +5883,4 @@ breakText Glyphs Glyph
Bow Cung
Spike Đỉnh nhọn
Skip Spaces Bỏ qua khoảng trắng
@msg The art is too large to copy as a picture: other apps get no PNG of it Hình vẽ quá lớn để sao chép dưới dạng ảnh: các ứng dụng khác không nhận được PNG của nó
Can't render this file because it contains an unexpected character in line 199 and column 5.
+1
View File
@@ -6123,3 +6123,4 @@ breakText Glyphs 字形
Bow 弓形
Spike 尖峰
Skip Spaces 跳过空格
@msg The art is too large to copy as a picture: other apps get no PNG of it 图稿太大,无法作为图片复制:其他应用不会获得它的 PNG
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -5920,3 +5920,4 @@ breakText Glyphs 字符
Bow 弓形
Spike 尖峰
Skip Spaces 略過空格
@msg The art is too large to copy as a picture: other apps get no PNG of it 圖稿太大,無法作為圖片複製:其他應用程式不會取得它的 PNG
Can't render this file because it contains an unexpected character in line 6 and column 47.