mod host;
pub mod surface;
pub(crate) use host::required_end;
pub use host::{copy_rows, instance, SurfaceGeometry, BACKEND_NAME, FAMILY};
pub use surface::FrameBuffer;
#[cfg(test)]
mod tests {
use super::*;
use crate::compat::Vec;
use crate::platform::types::Platform;
#[test]
fn tight_geometry_packs_rows() {
assert_eq!(SurfaceGeometry::tight(0, 0).stride, 0);
assert_eq!(SurfaceGeometry::tight(64, 48).stride, 64 * 4);
assert_eq!(SurfaceGeometry::tight(64, 48).width, 64);
assert_eq!(SurfaceGeometry::tight(64, 48).height, 48);
}
#[test]
fn instance_reports_the_portable_identity() {
let host = instance();
assert_eq!(host.backend_name(), BACKEND_NAME);
assert_eq!(host.family(), FAMILY);
}
#[test]
fn the_portable_host_can_display_a_printed_widget() {
use crate::core::Rect;
use crate::platform::Platform;
let host = instance();
assert!(
host.supports_surfaces(),
"supplying a surface is what this host is for, so the flag must be true"
);
let window = host.create_window("portable", 0, 0, 320, 240);
let rect = Rect::new(0, 0, 40, 20);
assert!(host.mount_surface(window, window, rect), "a known id mounts");
assert!(host.resize_surface(window, Rect::new(0, 0, 64, 32)), "a mounted id resizes");
assert!(host.unmount_surface(window), "and unmounts");
assert!(host.invalidate_surface(window));
assert_eq!(
host.take_pending_repaint(),
Some(window),
"the host must be able to learn which widget went stale"
);
assert_eq!(host.take_pending_repaint(), None, "and draining empties the queue");
assert!(
!host.mount_surface(window, 0xDEAD_BEEF, rect),
"an unknown id must be refused, not silently recorded"
);
}
#[test]
fn copy_rows_moves_a_tightly_packed_frame() {
let geometry = SurfaceGeometry::tight(2, 2);
let src: Vec<u8> = (0..16).collect();
let mut dst = vec![0u8; 16];
assert!(copy_rows(&src, &mut dst, geometry));
assert_eq!(dst, src);
}
#[test]
fn copy_rows_honours_a_padded_stride() {
let geometry = SurfaceGeometry { width: 2, height: 2, stride: 12 };
let src = vec![1u8; 12 * 2];
let mut dst = vec![0u8; 12 * 2];
assert!(copy_rows(&src, &mut dst, geometry));
assert_eq!(dst[..8], [1u8; 8]);
assert_eq!(dst[8..12], [0u8; 4], "padding must not be written");
assert_eq!(dst[16..20], [1u8; 4]);
}
#[test]
fn copy_rows_refuses_a_region_that_does_not_fit() {
let geometry = SurfaceGeometry::tight(4, 4);
let src = vec![0u8; 16];
let mut dst = vec![0u8; 64];
assert!(!copy_rows(&src, &mut dst, geometry), "short source must be refused");
let src = vec![0u8; 64];
let mut dst = vec![0u8; 16];
assert!(!copy_rows(&src, &mut dst, geometry), "short destination must be refused");
}
#[test]
fn copy_rows_refuses_a_stride_narrower_than_a_row() {
let geometry = SurfaceGeometry { width: 4, height: 1, stride: 8 };
let src = vec![0u8; 16];
let mut dst = vec![0u8; 16];
assert!(!copy_rows(&src, &mut dst, geometry), "overlapping rows must be refused");
}
#[test]
fn copy_rows_treats_a_zero_sized_surface_as_a_no_op() {
let geometry = SurfaceGeometry { width: 0, height: 8, stride: 0 };
assert!(copy_rows(&[], &mut [], geometry));
let geometry = SurfaceGeometry { width: 8, height: 0, stride: 32 };
assert!(copy_rows(&[], &mut [], geometry));
}
}