#634: region fills drawn by their own helper, and the long region-paint test split by case, for cognitive_complexity

This commit is contained in:
bflatastic
2026-10-29 12:28:47 +07:00
parent 789fa33444
commit 2a63418d57
2 changed files with 43 additions and 16 deletions
@@ -79,7 +79,11 @@ fn region_paints_survive_simplify_offset_and_bucket_normalization() {
prior_world_frame.as_coeffs().iter().zip(after_world_frame.as_coeffs()).all(|(before, after)| (before - after).abs() < 1e-8),
"flattening an already framed gradient preserves its source coordinates"
);
}
#[test]
fn explicit_and_inherited_region_paints_survive_refit() {
let mut s = Session::new();
let empty_id = square(&mut s, false);
ex_to_vector(s.doc_mut().unwrap(), empty_id);
{
@@ -106,7 +110,11 @@ fn region_paints_survive_simplify_offset_and_bucket_normalization() {
assert_eq!(inherited.fills, None, "inherited paints remain inherited after offset");
let inherited_space = inherited.paint_space.expect("offset binds inherited paints to the original frame");
assert_eq!((inherited_space.width, inherited_space.height), (100.0, 100.0));
}
#[test]
fn flatten_keeps_inherited_region_paints_inherited() {
let mut s = Session::new();
let inherited_flatten = square(&mut s, false);
let inherited_fills = s.doc().unwrap().get(inherited_flatten).unwrap().fills.clone();
ex_to_vector(s.doc_mut().unwrap(), inherited_flatten);
@@ -142,7 +150,11 @@ fn region_paints_survive_simplify_offset_and_bucket_normalization() {
s.doc_mut().unwrap().get_mut(group).unwrap().fills.clear();
let flattened = id_of(&ex(&mut s, "vector.flatten", json!({"ids": [group]}))["id"]).unwrap();
assert_eq!(net(&s, flattened).regions[0].fills, Some(source_fills), "flatten retains paints that differ from output node fills");
}
#[test]
fn legacy_offset_preserves_the_gradients_world_paint_frame() {
let mut s = Session::new();
let legacy_gradient = square(&mut s, false);
let mut gradient = figcraft_color::Gradient::default_for(figcraft_color::GradientKind::Linear, figcraft_color::Color::BLACK);
gradient.from = (0.2, 0.1);
@@ -164,7 +176,11 @@ fn region_paints_survive_simplify_offset_and_bucket_normalization() {
before_world.as_coeffs().iter().zip(after_world.as_coeffs()).all(|(before, after)| (before - after).abs() < 1e-8),
"legacy offset preserves the gradient's world paint frame"
);
}
#[test]
fn bucket_fills_an_explicitly_empty_face_and_leaves_the_other_empty() {
let mut s = Session::new();
let empty_faces =
id_of(&ex(&mut s, "vector.create", json!({"path": "M0 0 L100 0 L100 100 L0 100 Z M200 0 L300 0 L300 100 L200 100 Z"}))["id"]).unwrap();
{
+27 -16
View File
@@ -723,6 +723,31 @@ fn draw_outline(ctx: &Ctx, pix: &mut Pixmap, n: &Node, xf: Affine, depth: usize)
/// What paints over a node's fills, under its children and strokes (its inner shadows).
type OverFills<'a> = Option<&'a dyn Fn(&mut Pixmap)>;
/// A vector's network when any of its regions has paints or a paint frame of its own.
fn region_painted(n: &Node) -> Option<&figcraft_doc::VectorNetwork> {
match &n.kind {
NodeKind::Vector { network } if network.regions.iter().any(|r| r.fills.is_some() || r.paint_space.is_some()) => Some(network),
_ => None,
}
}
/// Each region of a vector with region paints, filled with its own paints (or the layer's) in its
/// own paint frame.
fn fill_vector_regions(ctx: &Ctx, pix: &mut Pixmap, n: &Node, network: &figcraft_doc::VectorNetwork, xf: Affine) {
let rounded = network.rounded();
let net = rounded.as_ref().unwrap_or(network);
for (i, region) in net.regions.iter().enumerate() {
let paints = region.fills.as_deref().unwrap_or(&n.fills);
if let Some(mut path) = net.region_path(i) {
let (pw, ph, frame) = region.paint_frame(n.width, n.height);
path.apply_affine(frame.inverse());
let Some(tp) = ts_path(&path) else { continue };
let rule = if region.winding == figcraft_doc::WindingRule::EvenOdd { FillRule::EvenOdd } else { FillRule::Winding };
fill_with(pix, &tp, paints, pw, ph, xf * frame, rule, ctx, None);
}
}
}
/// Fills, `over_fills`, children (clipped), strokes and text of a node, without opacity/effects.
fn draw_content(ctx: &Ctx, pix: &mut Pixmap, n: &Node, xf: Affine, depth: usize, over_fills: OverFills) {
let doc = ctx.doc;
@@ -804,27 +829,13 @@ fn draw_content(ctx: &Ctx, pix: &mut Pixmap, n: &Node, xf: Affine, depth: usize,
let closed = figcraft_doc::geometry::is_closed(n) || matches!(n.kind, NodeKind::BooleanOp { .. });
let splatted = ctx.lod && closed && lod::splat_fills(pix, n, xf);
let clips = n.clip && n.kind.is_frame_like() && !n.children.is_empty();
let styled_network = match &n.kind {
NodeKind::Vector { network } if network.regions.iter().any(|r| r.fills.is_some() || r.paint_space.is_some()) => Some(network),
_ => None,
};
let styled_network = region_painted(n);
// The outline fills, clips children to rounded corners and strokes booleans.
let outline =
if styled_network.is_some() || (splatted && !(clips && n.corners.uniform() != Some(0.0))) { None } else { node_outline(doc, n) };
if !splatted && closed {
if let Some(network) = styled_network {
let rounded = network.rounded();
let net = rounded.as_ref().unwrap_or(network);
for (i, region) in net.regions.iter().enumerate() {
let paints = region.fills.as_deref().unwrap_or(&n.fills);
if let Some(mut path) = net.region_path(i) {
let (pw, ph, frame) = region.paint_frame(w, h);
path.apply_affine(frame.inverse());
let Some(tp) = ts_path(&path) else { continue };
let rule = if region.winding == figcraft_doc::WindingRule::EvenOdd { FillRule::EvenOdd } else { FillRule::Winding };
fill_with(pix, &tp, paints, pw, ph, xf * frame, rule, ctx, None);
}
}
fill_vector_regions(ctx, pix, n, network, xf);
} else if let Some((path, rule)) = &outline
&& let Some(tp) = ts_path(path)
{