mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-19 10:05:25 +02:00
* Add Pattern Stamp as a Clone Stamp flyout sibling Introduce paint.patternStamp to paint the current pattern through a brush stroke. Aligned strokes keep a document-space tile origin; unaligned strokes restart at the first point; Impressionist jitters each dab with a seeded RNG. Empty patterns and strokes larger than 4096² pixels return an error instead of allocating. * Record Pattern Stamp on the tools scorecard Allow the aligned stamp helper's argument count under clippy. * Pattern Stamp: raise the stroke cap to 8192² so a 24 MP diagonal fits The 4096² bounding-box cap refused a corner-to-corner stroke on a 6016x4000 canvas (~24M px). Unit test covers that diagonal and a still-rejected 9000² box; the hostile-input test uses a footprint above the new cap. Scorecard note labels Impressionist as an approximation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * i18n(pl): translate the Pattern Stamp strings The Polish catalog landed on main after this PR was written; the translation-coverage tests need every language to carry new UI strings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tool::ALL holds 51 tools now that Red Eye and Pattern Stamp both landed The rebase onto main (with #1084's Red Eye tool) leaves Tool::ALL one entry longer; bump the array length and the count test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Flyout test: qualify egui::Vec2 (panels.rs no longer imports Vec2) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
58 lines
1.9 KiB
Rust
58 lines
1.9 KiB
Rust
//! Timing: Pattern Stamp on a 24 MP (6016×4000) RGBA8 document.
|
||
//!
|
||
//! ```sh
|
||
//! cargo run --release -p photocraft-engine --example bench_pattern_stamp
|
||
//! ```
|
||
//!
|
||
//! One aligned, hard 200 px stroke along y=2000 from x=100 to x=5900, impressionist off, then
|
||
//! optionally the same stroke with impressionist on.
|
||
|
||
use std::time::Instant;
|
||
|
||
use photocraft_engine::Session;
|
||
use serde_json::json;
|
||
|
||
fn main() {
|
||
let mut s = Session::new();
|
||
if let Err(e) = s.execute("file.new", json!({"width": 6016, "height": 4000, "depth": 8, "mode": "rgb"})) {
|
||
eprintln!("file.new: {e}");
|
||
std::process::exit(1);
|
||
}
|
||
println!("document 6016x4000, 8-bit RGB (24.06 MP)");
|
||
let stroke = json!({
|
||
"points": [[100, 2000], [5900, 2000]],
|
||
"size": 200,
|
||
"hardness": 100,
|
||
"pattern": "Checkerboard",
|
||
"scale": 100,
|
||
"aligned": true,
|
||
"impressionist": false,
|
||
});
|
||
let t = Instant::now();
|
||
match s.execute("paint.patternStamp", stroke.clone()) {
|
||
Ok(r) => {
|
||
let ms = t.elapsed().as_secs_f64() * 1000.0;
|
||
println!("patternStamp aligned hardness 100 size 200, 5800 px stroke: {ms:.1} ms");
|
||
println!("damage={}", r.get("damage").unwrap_or(&json!(null)));
|
||
}
|
||
Err(e) => {
|
||
eprintln!("paint.patternStamp: {e}");
|
||
std::process::exit(1);
|
||
}
|
||
}
|
||
let mut impressionist = stroke;
|
||
impressionist["impressionist"] = json!(true);
|
||
impressionist["points"] = json!([[100, 2400], [5900, 2400]]);
|
||
let t = Instant::now();
|
||
match s.execute("paint.patternStamp", impressionist) {
|
||
Ok(_) => {
|
||
let ms = t.elapsed().as_secs_f64() * 1000.0;
|
||
println!("patternStamp impressionist hardness 100 size 200, 5800 px stroke: {ms:.1} ms");
|
||
}
|
||
Err(e) => {
|
||
eprintln!("paint.patternStamp impressionist: {e}");
|
||
std::process::exit(1);
|
||
}
|
||
}
|
||
}
|