Merge pull request #6096 from Silvertree2010/fix/h7987-psd-export-writes-a-lone-utf-16

Cut PSD Unicode layer names on a character boundary
This commit is contained in:
BFlat
2026-11-09 03:17:43 +08:00
committed by GitHub
2 changed files with 19 additions and 1 deletions
+10 -1
View File
@@ -222,7 +222,16 @@ impl Record {
extra.push(ascii.len() as u8);
extra.extend(ascii);
extra.resize(extra.len().next_multiple_of(4), 0);
let units: Vec<u16> = self.name.encode_utf16().take(255).collect();
// Cut before the character that would pass 255 units, never inside a surrogate pair.
let mut units: Vec<u16> = vec![];
for c in self.name.chars() {
let mut buf = [0; 2];
let encoded = c.encode_utf16(&mut buf);
if units.len() + encoded.len() > 255 {
break;
}
units.extend_from_slice(encoded);
}
let mut luni = (units.len() as u32).to_be_bytes().to_vec();
luni.extend(units.iter().flat_map(|u| u.to_be_bytes()));
block(&mut extra, b"luni", &luni)?;
+9
View File
@@ -321,3 +321,12 @@ fn the_profile_and_the_size_limit() {
let err = Renderer::new().export_region(&doc, doc.artboards[0].rect, RasterFormat::Psd, &o).unwrap_err();
assert!(err.contains(&MAX_SIDE.to_string()), "{err}");
}
#[test]
fn long_unicode_name_is_cut_on_a_character_boundary() {
let mut b = DocBuilder::new(100.0, 60.0);
b.layer(&("a".repeat(254) + "😀"));
b.rect(Rect::new(0.0, 0.0, 5.0, 5.0), Color::rgb8(0, 0, 0), |_| {});
let file = export(&b.build(), &opts(PsdOptions::default()));
assert_eq!(parse(&file).records.last().unwrap().name, "a".repeat(254));
}