use super::super::*;
use super::make_global_arrangement;
use crate::ecs::WindowPos;
use crate::ecs::types::Point;
use crate::ecs::widget::bitmap_source::AlphaMask;
use bevy_ecs::world::World;
fn mask_opaque_at_origin() -> AlphaMask {
let pixels = vec![
0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ];
AlphaMask::from_pbgra32(&pixels, 2, 2, 8)
}
fn mask_fully_transparent() -> AlphaMask {
let pixels = vec![0u8; 2 * 2 * 4];
AlphaMask::from_pbgra32(&pixels, 2, 2, 8)
}
fn mask_fully_opaque() -> AlphaMask {
let pixels = vec![
0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, ];
AlphaMask::from_pbgra32(&pixels, 2, 2, 8)
}
fn alpha_mask_resource(mask: AlphaMask) -> AlphaMaskResource {
let mut r = AlphaMaskResource::new();
r.set(mask);
r
}
#[test]
fn test_alpha_mask_resource_present_hit() {
let mut world = World::new();
let entity = world
.spawn((
make_global_arrangement(0.0, 0.0, 2.0, 2.0),
HitTest::alpha_mask(),
alpha_mask_resource(mask_opaque_at_origin()),
))
.id();
let point = PhysicalPoint::new(0.5, 0.5);
assert!(hit_test_entity(&world, entity, point));
}
#[test]
fn test_alpha_mask_resource_present_miss_overrides_rect_fallback() {
let mut world = World::new();
let entity = world
.spawn((
make_global_arrangement(0.0, 0.0, 2.0, 2.0),
HitTest::alpha_mask(),
alpha_mask_resource(mask_fully_transparent()),
))
.id();
let point = PhysicalPoint::new(0.5, 0.5);
assert!(!hit_test_entity(&world, entity, point));
}
#[test]
fn test_alpha_mask_resource_absent_falls_back_to_rect() {
let mut world = World::new();
let entity = world
.spawn((
make_global_arrangement(0.0, 0.0, 2.0, 2.0),
HitTest::alpha_mask(),
))
.id();
let point = PhysicalPoint::new(0.5, 0.5);
assert!(hit_test_entity(&world, entity, point));
}
#[test]
fn test_alpha_mask_resource_outside_bounds_miss() {
let mut world = World::new();
let entity = world
.spawn((
make_global_arrangement(0.0, 0.0, 2.0, 2.0),
HitTest::alpha_mask(),
alpha_mask_resource(mask_fully_opaque()),
))
.id();
let point = PhysicalPoint::new(100.0, 100.0);
assert!(!hit_test_entity(&world, entity, point));
}
#[test]
fn test_alpha_mask_resource_via_window_hit() {
let mut world = World::new();
let window = world
.spawn(WindowPos {
position: Some(Point { x: 0, y: 0 }),
..Default::default()
})
.id();
let surface = world
.spawn((
make_global_arrangement(0.0, 0.0, 2.0, 2.0),
HitTest::alpha_mask(),
alpha_mask_resource(mask_opaque_at_origin()),
))
.id();
world.entity_mut(window).add_children(&[surface]);
let client = PhysicalPoint::new(0.5, 0.5);
assert_eq!(hit_test_in_window(&world, window, client), Some(surface));
}
#[test]
fn test_alpha_mask_resource_via_window_miss_overrides_rect_fallback() {
let mut world = World::new();
let window = world
.spawn(WindowPos {
position: Some(Point { x: 0, y: 0 }),
..Default::default()
})
.id();
let surface = world
.spawn((
make_global_arrangement(0.0, 0.0, 2.0, 2.0),
HitTest::alpha_mask(),
alpha_mask_resource(mask_fully_transparent()),
))
.id();
world.entity_mut(window).add_children(&[surface]);
let client = PhysicalPoint::new(0.5, 0.5);
assert_eq!(hit_test_in_window(&world, window, client), None);
}
fn with_com_initialized<T, F: FnOnce() -> T>(f: F) -> T {
use windows::Win32::System::Com::{COINIT_MULTITHREADED, CoInitializeEx, CoUninitialize};
unsafe {
let _ = CoInitializeEx(None, COINIT_MULTITHREADED);
}
let result = f();
unsafe {
CoUninitialize();
}
result
}
fn make_dummy_wic_source() -> windows::Win32::Graphics::Imaging::IWICBitmapSource {
use crate::com::wic::wic_factory;
use windows::Win32::Graphics::Imaging::{
GUID_WICPixelFormat32bppPBGRA, IWICBitmapSource, WICBitmapCacheOnLoad,
};
use windows_core::Interface;
let factory = wic_factory().expect("wic factory");
let bitmap = unsafe {
factory
.CreateBitmap(2, 2, &GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnLoad)
.expect("create wic bitmap")
};
bitmap.cast::<IWICBitmapSource>().expect("cast to source")
}
#[test]
fn test_alpha_mask_resource_priority_over_bitmap_source_direct() {
use crate::ecs::widget::bitmap_source::BitmapSourceResource;
let result = with_com_initialized(|| {
let mut world = World::new();
let mut bsr = BitmapSourceResource::new(make_dummy_wic_source());
bsr.set_alpha_mask(mask_fully_opaque());
let entity = world
.spawn((
make_global_arrangement(0.0, 0.0, 2.0, 2.0),
HitTest::alpha_mask(),
bsr,
alpha_mask_resource(mask_fully_transparent()),
))
.id();
let point = PhysicalPoint::new(0.5, 0.5);
hit_test_entity(&world, entity, point)
});
assert!(
!result,
"AlphaMaskResource(miss) must take priority over BitmapSourceResource(hit)"
);
}
#[test]
fn test_alpha_mask_resource_priority_over_bitmap_source_via_window() {
use crate::ecs::widget::bitmap_source::BitmapSourceResource;
let result = with_com_initialized(|| {
let mut world = World::new();
let window = world
.spawn(WindowPos {
position: Some(Point { x: 0, y: 0 }),
..Default::default()
})
.id();
let mut bsr = BitmapSourceResource::new(make_dummy_wic_source());
bsr.set_alpha_mask(mask_fully_opaque());
let surface = world
.spawn((
make_global_arrangement(0.0, 0.0, 2.0, 2.0),
HitTest::alpha_mask(),
bsr,
alpha_mask_resource(mask_fully_transparent()),
))
.id();
world.entity_mut(window).add_children(&[surface]);
let client = PhysicalPoint::new(0.5, 0.5);
hit_test_in_window(&world, window, client)
});
assert_eq!(
result, None,
"AlphaMaskResource(miss) must take priority over BitmapSourceResource(hit) via _ex path"
);
}