Files
vectorcraft/crates/render/src/tests_tileedge.rs
T
bflatasticandClaude Opus 5.5 b36fd67bf4 M3.72: Tile Edge Color dialog and Show Swatch Bounds in pattern editing
Object > Pattern > Tile Edge Color... picks the colour of the tile edge
(a layer-colour preset or a custom colour), stored in the preference
patternTileEdgeColor and passed to the renderer. Pattern Options gains
Show Swatch Bounds: a dashed outline of the part of the tiling the swatch
repeats (the period of brick and hex tilings).

Commands: prefs.set {patternTileEdgeColor}, pattern.options
{showSwatchBounds}, ui.tileEdgeColor. Model: PatternDef.show_swatch_bounds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 01:50:25 +07:00

70 lines
3.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Pattern editing mode: the tile edge in the Tile Edge Color, and Show Swatch Bounds.
use super::*;
use vectorcraft_color::{Color, Paint};
use vectorcraft_doc::pattern::{PatternDef, PatternEdit, TileType};
use vectorcraft_doc::{Appearance, Node};
use vectorcraft_geom::shapes;
/// A document editing a 20×20 pattern tile of type `tt` (a red 10×10 square in its corner, no
/// preview copies), its tile edge and swatch bounds shown as asked.
fn editing(tt: TileType, edge: bool, bounds: bool) -> Document {
let mut d = Document::new(200.0, 200.0);
let id = d.alloc_id();
let red = Node::path(
id,
shapes::rectangle(Rect::new(0.0, 0.0, 10.0, 10.0)),
Appearance::basic(Paint::solid(Color::rgb(1.0, 0.0, 0.0)), Paint::None, 0.0),
);
let mut def = PatternDef::new("Checks", vec![Arc::new(red.clone())]);
def.tile = Rect::new(0.0, 0.0, 20.0, 20.0);
(def.tile_type, def.copies, def.show_tile_edge, def.show_swatch_bounds) = (tt, 1, edge, bounds);
d.patterns.push(def);
let layer = d.add_layer(Some("Pattern Editing Mode"));
d.insert(Some(layer), 0, red).unwrap();
d.pattern_edit = Some(PatternEdit { pattern: "Checks".into(), layer, original: None });
d
}
/// `d` at 1:1 with the tile's corner at the centre of pixel (50, 50), on white.
fn render(d: &Document, tile_edge: Option<[u8; 3]>) -> Rendered {
let opts = RenderOptions { background: Some([255; 4]), tile_edge: tile_edge.unwrap_or(RenderOptions::default().tile_edge), ..Default::default() };
Renderer::new().render(d, 120, 120, Affine::translate((50.5, 50.5)), &opts)
}
fn is_white(p: [u8; 4]) -> bool {
p[0] > 245 && p[1] > 245 && p[2] > 245
}
#[test]
fn the_tile_edge_takes_the_tile_edge_color() {
let green = render(&editing(TileType::Grid, true, false), Some([0, 200, 0]));
// The left edge below the red square, and the bottom edge.
for (x, y) in [(50, 65), (60, 70), (70, 55)] {
let p = green.pixel(x, y);
assert!(p[1] > 150 && p[0] < 100 && p[2] < 100, "({x},{y}) {p:?}");
}
assert!(is_white(green.pixel(65, 65)), "inside the tile");
// The default is the first layer colour (light blue).
let [r, g, b] = RenderOptions::default().tile_edge;
let p = render(&editing(TileType::Grid, true, false), None).pixel(50, 65);
assert!(p[0].abs_diff(r) < 30 && p[1].abs_diff(g) < 30 && p[2].abs_diff(b) < 30, "{p:?}");
// Hidden: nothing there.
assert!(is_white(render(&editing(TileType::Grid, false, false), Some([0, 200, 0])).pixel(50, 65)));
}
#[test]
fn swatch_bounds_outline_the_period_dashed() {
// Brick by row repeats every two rows: the swatch is 20×40 from the tile's corner.
let tt = TileType::BrickByRow { offset: 0.5 };
let on = render(&editing(tt, false, true), Some([0, 200, 0]));
let green = |p: [u8; 4]| p[1] > 150 && p[0] < 100 && p[2] < 100;
let bottom: Vec<bool> = (51..70).map(|x| green(on.pixel(x, 90))).collect();
assert!(bottom.iter().any(|g| *g) && bottom.iter().any(|g| !*g), "dashed: {bottom:?}");
assert!((51..90).any(|y| green(on.pixel(70, y))), "right side");
assert!(!(51..70).any(|x| green(on.pixel(x, 70))), "the tile edge itself stays hidden");
// Off: no outline.
let off = render(&editing(tt, false, false), Some([0, 200, 0]));
assert!((51..70).all(|x| is_white(off.pixel(x, 90))));
}