Custom Shape: refuse an operation for a shape that can't be one component

Its parts would all take the operation and change the shape.
This commit is contained in:
Khawar Zamman Wani committed 2026-11-12 15:39:41 +05:30
1 parent 4b16507738
commit 23a0772776
2 files changed
+35 -1

No files matched your search

@@ -172,3 +172,27 @@ fn a_custom_shape_with_an_operation_joins_the_active_shape_layer() {
let ops: Vec<PathOp> = active_shape(&app).path.subpaths.iter().map(|s| s.op).collect();
assert_eq!(ops, [PathOp::Combine, PathOp::Subtract, PathOp::Join], "the ellipse, the ring and its hole");
}
/// #13442 review: a custom shape that can't be made one component (its parts exclude each other)
/// is not added with an operation, which would change its parts' operations: the layer stays as
/// it was and the status says why.
#[test]
fn a_custom_shape_that_is_not_one_component_is_refused() {
use photocraft_doc::vector::{Path, Subpath};
let mut app = app();
drag(&mut app, [50.0, 50.0], [200.0, 200.0]);
let before = active_shape(&app).path;
let xor = Path::new(vec![
Subpath::polygon(&[(0.0, 0.0), (60.0, 0.0), (60.0, 60.0), (0.0, 60.0)]),
Subpath::polygon(&[(40.0, 40.0), (100.0, 40.0), (100.0, 100.0), (40.0, 100.0)]).with_op(PathOp::Exclude),
]);
let r = app.run("shape.presets.new", json!({"name": "Xor", "path": photocraft_engine::vector_cmds::path_json(&xor)})).unwrap();
app.ui.tool = Tool::CustomShape;
app.ui.presets_ui.custom_shape = r["name"].as_str().unwrap().into();
app.ui.tool_options.shape_path_op = "combine".into();
let layers = layer_count(&app);
drag(&mut app, [100.0, 100.0], [250.0, 250.0]);
assert_eq!(layer_count(&app), layers);
assert_eq!(active_shape(&app).path, before, "the layer is unchanged");
assert!(app.ui.status_error, "{}", app.ui.status);
}
+11 -1
View File
@@ -179,7 +179,17 @@ pub fn finish_shape(app: &mut PhotocraftApp, tool: Tool, start: [f64; 2], end: [
&& let Some(id) = super::options::selected_shape(&app.session)
&& let Some(outline) = shape_outline(app, tool, start, end, mods)
{
let outline = as_one_component(&outline, outline.fill_rule).unwrap_or(outline);
// `shape.create` gives every component the operation, so a shape of several components
// that can't be made one (its parts intersect or exclude) would change: refuse it.
let outline = match as_one_component(&outline, outline.fill_rule) {
Some(one) => one,
None if outline.subpaths.len() <= 1 => outline,
None => {
app.ui.status = tl!("This custom shape can't be added to a shape layer with a path operation: choose New Layer").into();
app.ui.status_error = true;
return;
}
};
let path = photocraft_engine::vector_cmds::path_json(&outline);
if let Err(e) = app.run("shape.create", json!({"kind": "path", "path": path, "addTo": id.0, "op": op})) {
app.ui.status = e;