mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-30 05:16:56 -06:00
fix: 粘贴图片填充时避开目标文件已占用的图片键
目标文件已有同名键但数据不同时,粘贴的 paint 改用复制数据的内容哈希键,避免渲染成目标文件里的图片;目标文件原图片保留给已有图层。
This commit is contained in:
@@ -365,7 +365,7 @@ pub(super) fn paint_copy(s: &mut Session, p: &Value, fills: bool) -> Result<Valu
|
||||
/// stroke's copied settings go onto each target too.
|
||||
pub(super) fn paint_paste(s: &mut Session, p: &Value, fills: bool) -> Result<Value> {
|
||||
let cmd = if fills { "fill.paste" } else { "stroke.paste" };
|
||||
let Some((copied_fills, paint)) = s.clipboard.paint.clone() else {
|
||||
let Some((copied_fills, mut paint)) = s.clipboard.paint.clone() else {
|
||||
return Err(EngineError::Disabled(cmd.into(), "no copied fill or stroke".into()));
|
||||
};
|
||||
if copied_fills != fills {
|
||||
@@ -386,10 +386,15 @@ pub(super) fn paint_paste(s: &mut Session, p: &Value, fills: bool) -> Result<Val
|
||||
}
|
||||
}
|
||||
// An image paint names its data by key; a copy from another file brings the data with it.
|
||||
if let figcraft_color::PaintKind::Image(img) = &paint.kind {
|
||||
let key = img.image.clone();
|
||||
if let Some(d) = s.clipboard.paint_images.get(&key).cloned() {
|
||||
s.doc_mut()?.images.entry(key).or_insert(d);
|
||||
if let figcraft_color::PaintKind::Image(img) = &mut paint.kind {
|
||||
let copied = img.image.clone();
|
||||
if let Some(d) = s.clipboard.paint_images.get(&copied).cloned() {
|
||||
let doc = s.doc_mut()?;
|
||||
// The destination may already use that key for different data (other layers keep
|
||||
// that image): the pasted paint takes the copied data's content hash instead.
|
||||
let key = if doc.images.get(&copied).is_some_and(|existing| existing != &d) { figcraft_format::image_hash(&d.bytes) } else { copied };
|
||||
doc.images.entry(key.clone()).or_insert(d);
|
||||
img.image = key;
|
||||
}
|
||||
}
|
||||
let mut q = json!({"ids": ids, "paint": serde_json::to_value(paint).map_err(|e| bad(cmd, e.to_string()))?});
|
||||
|
||||
@@ -120,6 +120,29 @@ fn a_copied_image_fill_brings_its_image_to_another_file() {
|
||||
assert!(matches!(node(&s, b).fills[0].kind, figcraft_color::PaintKind::Image(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_copied_image_key_taken_in_another_file_gets_the_copied_data() {
|
||||
let mut s = Session::new();
|
||||
let a = rect(&mut s);
|
||||
let copied = figcraft_doc::ImageData { bytes: std::sync::Arc::new(vec![1, 2, 3]), width: 2, height: 2 };
|
||||
let taken = figcraft_doc::ImageData { bytes: std::sync::Arc::new(vec![9, 9, 9]), width: 3, height: 3 };
|
||||
ex(&mut s, "fill.add", json!({"ids": [a], "paint": {"type": "image", "image": "img-key"}}));
|
||||
s.doc_mut().unwrap().images.insert("img-key".into(), copied.clone());
|
||||
ex(&mut s, "fill.copy", json!({"id": a, "index": 1}));
|
||||
// The other file already uses that key for different data: the pasted paint takes a content
|
||||
// key for the copied data instead, and the destination's image stays as it is.
|
||||
ex(&mut s, "file.new", json!({}));
|
||||
let b = rect(&mut s);
|
||||
s.doc_mut().unwrap().images.insert("img-key".into(), taken.clone());
|
||||
ex(&mut s, "fill.paste", json!({"ids": [b], "index": 0}));
|
||||
let doc = s.doc().unwrap();
|
||||
let fill = &doc.node(b).unwrap().fills[0];
|
||||
let figcraft_color::PaintKind::Image(img) = &fill.kind else { panic!("the pasted fill is an image") };
|
||||
assert_ne!(img.image, "img-key");
|
||||
assert_eq!(doc.images.get(&img.image), Some(&copied));
|
||||
assert_eq!(doc.images.get("img-key"), Some(&taken), "the destination's image stays");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_copied_pattern_does_not_paste_into_another_file() {
|
||||
let mut s = Session::new();
|
||||
|
||||
Reference in New Issue
Block a user