Applying a text data set re-renders the type layer instead of blanking it (#990) (#1025)

apply_to_doc replaced a text-replacement variable's text and set the layer's
render cache to None, but nothing rebuilt it. The compositor draws a type
layer from that cache, so the text vanished from the canvas after
image.applyDataSet and from every file written by
file.export.dataSetsAsFiles. The layer is now re-rendered with
type_cmds::refresh, as type.edit does.
This commit is contained in:
Ian Swope authored and GitHub committed 2026-10-08 14:30:50 -04:00
1 parent 3179093985
commit 8f5a0817e4
2 files changed
+26 -1

No files matched your search

+4 -1
View File
@@ -164,13 +164,16 @@ fn apply_to_doc(doc: &mut Document, vars: &Variables, set: &DataSet) -> Result<(
}
}
(VarKind::TextReplacement, VarValue::Text(text)) => {
let snapshot = doc.clone();
if let Some(l) = doc.layer_mut(def.layer)
&& let LayerContent::Text(t) = &mut l.content
{
t.text = text.clone();
t.cache = None; // force re-render
t.runs.clear(); // re-flow as one run from the summary style
t.paragraphs.clear();
// The compositor draws a type layer from its cache: clearing it left the
// layer blank until some other edit re-rendered it (#990).
crate::type_cmds::refresh(&snapshot, t);
}
}
(VarKind::PixelReplacement { method, align, clip }, VarValue::Pixels(path)) => {
+22
View File
@@ -190,3 +190,25 @@ fn pixel_replacement_changes_the_layer() {
assert!(b > r, "replacement is blue-ish: {rgba:?}");
}
}
#[test]
fn applied_text_is_rendered_in_the_document_and_in_exports() {
// Applying a text value cleared the type layer's render cache and nothing rebuilt it, so the
// text vanished from the canvas and from every exported file (#990).
let mut s = Session::new();
s.execute("file.new", json!({"width": 200, "height": 60, "background": "white"})).unwrap();
let id = s.execute("type.create", json!({"x": 4, "y": 40, "text": "HELLO", "size": 32, "color": "#000000"})).unwrap()["layer"].clone();
let dark = |d: &Document| photocraft_compose::render(d, d.bounds()).px.iter().filter(|p| p[0] < 0.5).count();
assert!(dark(doc(&s)) > 0);
s.execute("image.variables.define", json!({"defs": [{"name": "headline", "layer": id, "type": "textReplacement"}]})).unwrap();
s.execute("image.variables.dataSets", json!({"dataSets": [{"name": "row1", "values": [{"variable": "headline", "kind": "text", "value": "BYE"}]}]}))
.unwrap();
let dir = tmp("text-export");
let out = s.execute("file.export.dataSetsAsFiles", json!({"dir": dir, "format": "png"})).unwrap();
let path = out["files"][0].as_str().unwrap();
let exported = photocraft_io::import(path, &std::fs::read(path).unwrap()).unwrap().document;
assert!(dark(&exported) > 0, "the exported row keeps its text");
s.execute("image.applyDataSet", json!({"name": "row1"})).unwrap();
assert!(dark(doc(&s)) > 0, "the applied text is drawn");
let _ = std::fs::remove_dir_all(&dir);
}