105 lines
4.4 KiB
Rust
105 lines
4.4 KiB
Rust
use hcie_engine_api::Engine;
|
|
|
|
fn count_opaque_pixels(pixels: &[u8]) -> usize {
|
|
pixels.iter().skip(3).step_by(4).filter(|&&a| a > 0).count()
|
|
}
|
|
|
|
fn has_non_black_pixel(pixels: &[u8]) -> bool {
|
|
pixels.chunks_exact(4).any(|px| px[0] > 0 || px[1] > 0 || px[2] > 0 || px[3] > 0)
|
|
}
|
|
|
|
#[test]
|
|
fn test_visibility_toggle_bug_repro() {
|
|
let mut engine = Engine::new(100, 100);
|
|
|
|
// Fill background layer (layer 0) with opaque white
|
|
let bg_id = engine.active_layer_id();
|
|
engine.draw_filled_rect_rgba(0, 0, 100, 100, [255, 255, 255, 255]);
|
|
log::info!("=== AFTER FILL BG: pixels should be white ===");
|
|
let p = engine.get_composite_pixels();
|
|
log::info!(" composite opaque pixels: {}/{}", count_opaque_pixels(&p), 100*100);
|
|
assert_eq!(count_opaque_pixels(&p), 100*100, "background should be fully opaque");
|
|
|
|
// Add a new layer on top
|
|
let top_id = engine.add_layer("Top Layer");
|
|
log::info!("=== AFTER ADD TOP LAYER: id={} ===", top_id);
|
|
let p = engine.get_composite_pixels();
|
|
log::info!(" composite opaque pixels: {}/{} (expected 10000)", count_opaque_pixels(&p), 100*100);
|
|
// After adding layer, composite should still show the background (10000 opaque)
|
|
|
|
// Draw something on the top layer
|
|
engine.draw_filled_rect_rgba(20, 20, 80, 80, [0, 0, 0, 255]);
|
|
log::info!("=== AFTER DRAW ON TOP: black square 60x60 at (20,20) ===");
|
|
let p = engine.get_composite_pixels();
|
|
log::info!(" composite opaque pixels: {}/{} (expected 10000)", count_opaque_pixels(&p), 100*100);
|
|
assert_eq!(count_opaque_pixels(&p), 100*100, "all pixels should still be opaque");
|
|
|
|
// Now hide the BACKGROUND layer
|
|
log::info!("=== HIDE BACKGROUND (id={}) ===", bg_id);
|
|
engine.set_layer_visible(bg_id, false);
|
|
let p = engine.get_composite_pixels();
|
|
log::info!(" composite opaque pixels: {}/{} (expected 3600 = 60*60 black square)", count_opaque_pixels(&p), 100*100);
|
|
log::info!(" has non-black: {}", has_non_black_pixel(&p));
|
|
// After hiding background, only the black square (3600 px) should be visible
|
|
assert!(count_opaque_pixels(&p) > 0, "at least the drawn square should be visible");
|
|
assert!(count_opaque_pixels(&p) <= 3600 + 100, "only drawn square should be visible, got {}", count_opaque_pixels(&p));
|
|
|
|
// Show background again
|
|
log::info!("=== SHOW BACKGROUND (id={}) ===", bg_id);
|
|
engine.set_layer_visible(bg_id, true);
|
|
let p = engine.get_composite_pixels();
|
|
log::info!(" composite opaque pixels: {}/{} (expected 10000)", count_opaque_pixels(&p), 100*100);
|
|
assert_eq!(count_opaque_pixels(&p), 100*100, "all pixels should be opaque again");
|
|
}
|
|
|
|
#[test]
|
|
fn test_visibility_toggle_with_stroke() {
|
|
let mut engine = Engine::new(100, 100);
|
|
|
|
let bg_id = engine.active_layer_id();
|
|
engine.draw_filled_rect_rgba(0, 0, 100, 100, [255, 255, 255, 255]);
|
|
let top_id = engine.add_layer("Top Layer");
|
|
|
|
// Hide background
|
|
log::info!("=== HIDE BG, THEN STROKE ON TOP ===");
|
|
engine.set_layer_visible(bg_id, false);
|
|
|
|
// Begin a stroke on the top layer
|
|
engine.begin_stroke(top_id, 50.0, 50.0);
|
|
engine.stroke_to(top_id, 55.0, 55.0, 1.0);
|
|
engine.stroke_to(top_id, 60.0, 60.0, 1.0);
|
|
engine.end_stroke(top_id);
|
|
|
|
let p = engine.get_composite_pixels();
|
|
let opaque = count_opaque_pixels(&p);
|
|
log::info!(" After stroke with bg hidden: opaque pixels: {}/{}", opaque, 100*100);
|
|
log::info!(" has non-black: {}", has_non_black_pixel(&p));
|
|
// The stroke should be visible
|
|
assert!(opaque > 0, "stroke should be visible even with bg hidden");
|
|
}
|
|
|
|
#[test]
|
|
fn test_visibility_toggle_during_stroke() {
|
|
let mut engine = Engine::new(100, 100);
|
|
|
|
let bg_id = engine.active_layer_id();
|
|
engine.draw_filled_rect_rgba(0, 0, 100, 100, [255, 255, 255, 255]);
|
|
let top_id = engine.add_layer("Top Layer");
|
|
|
|
// Begin a stroke on the top layer
|
|
log::info!("=== STROKE THEN HIDE BG DURING STROKE ===");
|
|
engine.begin_stroke(top_id, 50.0, 50.0);
|
|
engine.stroke_to(top_id, 55.0, 55.0, 1.0);
|
|
|
|
// Hide background mid-stroke
|
|
engine.set_layer_visible(bg_id, false);
|
|
engine.stroke_to(top_id, 60.0, 60.0, 1.0);
|
|
engine.stroke_to(top_id, 65.0, 65.0, 1.0);
|
|
engine.end_stroke(top_id);
|
|
|
|
let p = engine.get_composite_pixels();
|
|
let opaque = count_opaque_pixels(&p);
|
|
log::info!(" After stroke with bg hidden mid-stroke: opaque pixels: {}/{}", opaque, 100*100);
|
|
assert!(opaque > 0, "stroke should be visible even after hiding bg mid-stroke");
|
|
}
|