rename PixelGrid to Bitmap

This commit is contained in:
Vinzenz Schroeter 2024-10-14 22:42:45 +02:00
parent f64ce6e57e
commit bd0ecd77d2
23 changed files with 1037 additions and 1042 deletions

View file

@ -15,7 +15,7 @@ fn main() {
let connection = Connection::open(cli.destination)
.expect("could not connect to display");
let mut pixels = PixelGrid::max_sized();
let mut pixels = Bitmap::max_sized();
pixels.fill(true);
let command = Command::BitmapLinearWin(

View file

@ -34,7 +34,7 @@ fn main() {
}
}
fn iteration(field: PixelGrid) -> PixelGrid {
fn iteration(field: Bitmap) -> Bitmap {
let mut next = field.clone();
for x in 0..field.width() {
for y in 0..field.height() {
@ -51,7 +51,7 @@ fn iteration(field: PixelGrid) -> PixelGrid {
next
}
fn count_neighbors(field: &PixelGrid, x: i32, y: i32) -> i32 {
fn count_neighbors(field: &Bitmap, x: i32, y: i32) -> i32 {
let mut count = 0;
for nx in x - 1..=x + 1 {
for ny in y - 1..=y + 1 {
@ -78,8 +78,8 @@ fn count_neighbors(field: &PixelGrid, x: i32, y: i32) -> i32 {
count
}
fn make_random_field(probability: f64) -> PixelGrid {
let mut field = PixelGrid::max_sized();
fn make_random_field(probability: f64) -> Bitmap {
let mut field = Bitmap::max_sized();
let mut rng = rand::thread_rng();
let d = distributions::Bernoulli::new(probability).unwrap();
for x in 0..field.width() {

View file

@ -16,7 +16,7 @@ fn main() {
let connection = Connection::open(Cli::parse().destination)
.expect("could not connect to display");
let mut pixels = PixelGrid::max_sized();
let mut pixels = Bitmap::max_sized();
for x_offset in 0..usize::MAX {
pixels.fill(false);

View file

@ -28,7 +28,7 @@ fn main() {
// put all pixels in on state
if cli.enable_all {
let mut filled_grid = PixelGrid::max_sized();
let mut filled_grid = Bitmap::max_sized();
filled_grid.fill(true);
let command = BitmapLinearWin(

View file

@ -1,7 +1,7 @@
//! Example for how to use the WebSocket connection
use servicepoint::{
Command, CompressionCode, Connection, Grid, Origin, PixelGrid,
Command, CompressionCode, Connection, Grid, Origin, Bitmap,
};
fn main() {
@ -13,7 +13,7 @@ fn main() {
// use send_mut instead of send
connection.send_mut(Command::Clear).unwrap();
let mut pixels = PixelGrid::max_sized();
let mut pixels = Bitmap::max_sized();
pixels.fill(true);
// use send_mut instead of send

View file

@ -25,7 +25,7 @@ fn main() {
let connection = Connection::open(cli.destination)
.expect("could not connect to display");
let mut enabled_pixels = PixelGrid::new(PIXEL_WIDTH, PIXEL_HEIGHT);
let mut enabled_pixels = Bitmap::new(PIXEL_WIDTH, PIXEL_HEIGHT);
enabled_pixels.fill(true);
for x_offset in 0..PIXEL_WIDTH {

View file

@ -6,21 +6,21 @@ use crate::{BitVec, DataRef, Grid, SpBitVec, PIXEL_HEIGHT, PIXEL_WIDTH};
/// A grid of pixels stored in packed bytes.
#[derive(Debug, Clone, PartialEq)]
pub struct PixelGrid {
pub struct Bitmap {
width: usize,
height: usize,
bit_vec: SpBitVec,
}
impl PixelGrid {
/// Creates a new [PixelGrid] with the specified dimensions.
impl Bitmap {
/// Creates a new [Bitmap] with the specified dimensions.
///
/// # Arguments
///
/// - `width`: size in pixels in x-direction
/// - `height`: size in pixels in y-direction
///
/// returns: [PixelGrid] initialized to all pixels off
/// returns: [Bitmap] initialized to all pixels off
///
/// # Panics
///
@ -40,14 +40,14 @@ impl PixelGrid {
Self::new(PIXEL_WIDTH, PIXEL_HEIGHT)
}
/// Loads a [PixelGrid] with the specified dimensions from the provided data.
/// Loads a [Bitmap] with the specified dimensions from the provided data.
///
/// # Arguments
///
/// - `width`: size in pixels in x-direction
/// - `height`: size in pixels in y-direction
///
/// returns: [PixelGrid] that contains a copy of the provided data
/// returns: [Bitmap] that contains a copy of the provided data
///
/// # Panics
///
@ -64,12 +64,12 @@ impl PixelGrid {
}
}
/// Iterate over all cells in [PixelGrid].
/// Iterate over all cells in [Bitmap].
///
/// Order is equivalent to the following loop:
/// ```
/// # use servicepoint::{PixelGrid, Grid};
/// # let grid = PixelGrid::new(8,2);
/// # use servicepoint::{Bitmap, Grid};
/// # let grid = Bitmap::new(8,2);
/// for y in 0..grid.height() {
/// for x in 0..grid.width() {
/// grid.get(x, y);
@ -80,12 +80,12 @@ impl PixelGrid {
self.bit_vec.iter().by_refs()
}
/// Iterate over all cells in [PixelGrid] mutably.
/// Iterate over all cells in [Bitmap] mutably.
///
/// Order is equivalent to the following loop:
/// ```
/// # use servicepoint::{PixelGrid, Grid};
/// # let mut grid = PixelGrid::new(8,2);
/// # use servicepoint::{Bitmap, Grid};
/// # let mut grid = Bitmap::new(8,2);
/// # let value = false;
/// for y in 0..grid.height() {
/// for x in 0..grid.width() {
@ -96,8 +96,8 @@ impl PixelGrid {
///
/// # Example
/// ```
/// # use servicepoint::{PixelGrid, Grid};
/// # let mut grid = PixelGrid::new(8,2);
/// # use servicepoint::{Bitmap, Grid};
/// # let mut grid = Bitmap::new(8,2);
/// # let value = false;
/// for (index, mut pixel) in grid.iter_mut().enumerate() {
/// pixel.set(index % 2 == 0)
@ -107,17 +107,17 @@ impl PixelGrid {
self.bit_vec.iter_mut()
}
/// Iterate over all rows in [PixelGrid] top to bottom.
/// Iterate over all rows in [Bitmap] top to bottom.
pub fn iter_rows(&self) -> IterRows {
IterRows {
pixel_grid: self,
bitmap: self,
row: 0,
}
}
}
impl Grid<bool> for PixelGrid {
/// Sets the value of the specified position in the [PixelGrid].
impl Grid<bool> for Bitmap {
/// Sets the value of the specified position in the [Bitmap].
///
/// # Arguments
///
@ -139,7 +139,7 @@ impl Grid<bool> for PixelGrid {
self.bit_vec[x + y * self.width]
}
/// Sets the state of all pixels in the [PixelGrid].
/// Sets the state of all pixels in the [Bitmap].
///
/// # Arguments
///
@ -158,7 +158,7 @@ impl Grid<bool> for PixelGrid {
}
}
impl DataRef<u8> for PixelGrid {
impl DataRef<u8> for Bitmap {
fn data_ref_mut(&mut self) -> &mut [u8] {
self.bit_vec.as_raw_mut_slice()
}
@ -168,15 +168,15 @@ impl DataRef<u8> for PixelGrid {
}
}
impl From<PixelGrid> for Vec<u8> {
/// Turns a [PixelGrid] into the underlying [`Vec<u8>`].
fn from(value: PixelGrid) -> Self {
impl From<Bitmap> for Vec<u8> {
/// Turns a [Bitmap] into the underlying [`Vec<u8>`].
fn from(value: Bitmap) -> Self {
value.bit_vec.into()
}
}
pub struct IterRows<'t> {
pixel_grid: &'t PixelGrid,
bitmap: &'t Bitmap,
row: usize,
}
@ -184,24 +184,24 @@ impl<'t> Iterator for IterRows<'t> {
type Item = &'t BitSlice<u8, Msb0>;
fn next(&mut self) -> Option<Self::Item> {
if self.row >= self.pixel_grid.height {
if self.row >= self.bitmap.height {
return None;
}
let start = self.row * self.pixel_grid.width;
let end = start + self.pixel_grid.width;
let start = self.row * self.bitmap.width;
let end = start + self.bitmap.width;
self.row += 1;
Some(&self.pixel_grid.bit_vec[start..end])
Some(&self.bitmap.bit_vec[start..end])
}
}
#[cfg(test)]
mod tests {
use crate::{DataRef, Grid, PixelGrid};
use crate::{DataRef, Grid, Bitmap};
#[test]
fn fill() {
let mut grid = PixelGrid::new(8, 2);
let mut grid = Bitmap::new(8, 2);
assert_eq!(grid.data_ref(), [0x00, 0x00]);
grid.fill(true);
@ -213,7 +213,7 @@ mod tests {
#[test]
fn get_set() {
let mut grid = PixelGrid::new(8, 2);
let mut grid = Bitmap::new(8, 2);
assert!(!grid.get(0, 0));
assert!(!grid.get(1, 1));
@ -228,7 +228,7 @@ mod tests {
#[test]
fn load() {
let mut grid = PixelGrid::new(8, 3);
let mut grid = Bitmap::new(8, 3);
for x in 0..grid.width {
for y in 0..grid.height {
grid.set(x, y, (x + y) % 2 == 0);
@ -239,33 +239,33 @@ mod tests {
let data: Vec<u8> = grid.into();
let grid = PixelGrid::load(8, 3, &data);
let grid = Bitmap::load(8, 3, &data);
assert_eq!(grid.data_ref(), [0xAA, 0x55, 0xAA]);
}
#[test]
#[should_panic]
fn out_of_bounds_x() {
let vec = PixelGrid::new(8, 2);
let vec = Bitmap::new(8, 2);
vec.get(8, 1);
}
#[test]
#[should_panic]
fn out_of_bounds_y() {
let mut vec = PixelGrid::new(8, 2);
let mut vec = Bitmap::new(8, 2);
vec.set(1, 2, false);
}
#[test]
fn iter() {
let grid = PixelGrid::new(8, 2);
let grid = Bitmap::new(8, 2);
assert_eq!(16, grid.iter().count())
}
#[test]
fn iter_rows() {
let grid = PixelGrid::load(8, 2, &[0x04, 0x40]);
let grid = Bitmap::load(8, 2, &[0x04, 0x40]);
let mut iter = grid.iter_rows();
assert_eq!(iter.next().unwrap().count_ones(), 1);
@ -275,7 +275,7 @@ mod tests {
#[test]
fn iter_mut() {
let mut grid = PixelGrid::new(8, 2);
let mut grid = Bitmap::new(8, 2);
for (index, mut pixel) in grid.iter_mut().enumerate() {
pixel.set(index % 2 == 0);
}
@ -284,7 +284,7 @@ mod tests {
#[test]
fn data_ref_mut() {
let mut grid = PixelGrid::new(8, 2);
let mut grid = Bitmap::new(8, 2);
let data = grid.data_ref_mut();
data[1] = 0x0F;
assert!(grid.get(7, 1));

View file

@ -4,7 +4,7 @@ use crate::{
command_code::CommandCode,
compression::into_decompressed,
packet::{Header, Packet},
Brightness, BrightnessGrid, CompressionCode, Cp437Grid, Origin, PixelGrid,
Brightness, BrightnessGrid, CompressionCode, Cp437Grid, Origin, Bitmap,
Pixels, PrimitiveGrid, SpBitVec, Tiles, TILE_SIZE,
};
@ -105,10 +105,10 @@ pub enum Command {
/// # Examples
///
/// ```rust
/// # use servicepoint::{Command, CompressionCode, Grid, PixelGrid};
/// # use servicepoint::{Command, CompressionCode, Grid, Bitmap};
/// # let connection = servicepoint::Connection::Fake;
/// #
/// let mut pixels = PixelGrid::max_sized();
/// let mut pixels = Bitmap::max_sized();
/// // draw something to the pixels here
/// # pixels.set(2, 5, true);
///
@ -121,7 +121,7 @@ pub enum Command {
///
/// connection.send(command).expect("send failed");
/// ```
BitmapLinearWin(Origin<Pixels>, PixelGrid, CompressionCode),
BitmapLinearWin(Origin<Pixels>, Bitmap, CompressionCode),
/// Set the brightness of all tiles to the same value.
///
@ -337,7 +337,7 @@ impl Command {
Ok(Command::BitmapLinearWin(
Origin::new(tiles_x as usize * TILE_SIZE, pixels_y as usize),
PixelGrid::load(
Bitmap::load(
tile_w as usize * TILE_SIZE,
pixel_h as usize,
&payload,
@ -371,7 +371,7 @@ impl Command {
}
}
/// Helper method for Packets into `BitMapLinear*`-Commands
/// Helper method for Packets into `BitmapLinear*`-Commands
fn packet_into_linear_bitmap(
packet: Packet,
) -> Result<(SpBitVec, CompressionCode), TryFromPacketError> {
@ -496,7 +496,7 @@ mod tests {
origin::Pixels,
packet::{Header, Packet},
Brightness, BrightnessGrid, Command, CompressionCode, Origin,
PixelGrid, PrimitiveGrid,
Bitmap, PrimitiveGrid,
};
fn round_trip(original: Command) {
@ -589,7 +589,7 @@ mod tests {
));
round_trip(Command::BitmapLinearWin(
Origin::new(0, 0),
PixelGrid::max_sized(),
Bitmap::max_sized(),
compression,
));
}
@ -714,7 +714,7 @@ mod tests {
for compression in all_compressions().to_owned() {
let p: Packet = Command::BitmapLinearWin(
Origin::new(16, 8),
PixelGrid::new(8, 8),
Bitmap::new(8, 8),
compression,
)
.into();

View file

@ -3,13 +3,13 @@
/// # Examples
///
/// ```rust
/// # use servicepoint::{Command, CompressionCode, Origin, PixelGrid};
/// # use servicepoint::{Command, CompressionCode, Origin, Bitmap};
/// // create command without payload compression
/// # let pixels = PixelGrid::max_sized();
/// # let pixels = Bitmap::max_sized();
/// _ = Command::BitmapLinearWin(Origin::new(0, 0), pixels, CompressionCode::Uncompressed);
///
/// // create command with payload compressed with lzma and appropriate header flags
/// # let pixels = PixelGrid::max_sized();
/// # let pixels = Bitmap::max_sized();
/// _ = Command::BitmapLinearWin(Origin::new(0, 0), pixels, CompressionCode::Lzma);
/// ```
#[repr(u16)]

View file

@ -7,7 +7,7 @@
//! # Examples
//!
//! ```rust
//! use servicepoint::{Command, CompressionCode, Grid, PixelGrid};
//! use servicepoint::{Command, CompressionCode, Grid, Bitmap};
//!
//! let connection = servicepoint::Connection::open("127.0.0.1:2342")
//! .expect("connection failed");
@ -18,10 +18,10 @@
//! ```
//!
//! ```rust
//! # use servicepoint::{Command, CompressionCode, Grid, PixelGrid};
//! # use servicepoint::{Command, CompressionCode, Grid, Bitmap};
//! # let connection = servicepoint::Connection::open("127.0.0.1:2342").expect("connection failed");
//! // turn on all pixels in a grid
//! let mut pixels = PixelGrid::max_sized();
//! let mut pixels = Bitmap::max_sized();
//! pixels.fill(true);
//!
//! // create command to send pixels
@ -48,7 +48,7 @@ pub use crate::cp437::{CharGrid, Cp437Grid};
pub use crate::data_ref::DataRef;
pub use crate::grid::Grid;
pub use crate::origin::{Origin, Pixels, Tiles};
pub use crate::pixel_grid::PixelGrid;
pub use crate::bitmap::Bitmap;
pub use crate::primitive_grid::PrimitiveGrid;
type SpBitVec = BitVec<u8, Msb0>;
@ -64,7 +64,7 @@ mod data_ref;
mod grid;
mod origin;
pub mod packet;
mod pixel_grid;
mod bitmap;
mod primitive_grid;
/// size of a single tile in one dimension
@ -95,8 +95,8 @@ pub const TILE_HEIGHT: usize = 20;
/// # Examples
///
/// ```rust
/// # use servicepoint::{PIXEL_HEIGHT, PIXEL_WIDTH, PixelGrid};
/// let grid = PixelGrid::new(PIXEL_WIDTH, PIXEL_HEIGHT);
/// # use servicepoint::{PIXEL_HEIGHT, PIXEL_WIDTH, Bitmap};
/// let grid = Bitmap::new(PIXEL_WIDTH, PIXEL_HEIGHT);
/// ```
pub const PIXEL_WIDTH: usize = TILE_WIDTH * TILE_SIZE;
@ -105,8 +105,8 @@ pub const PIXEL_WIDTH: usize = TILE_WIDTH * TILE_SIZE;
/// # Examples
///
/// ```rust
/// # use servicepoint::{PIXEL_HEIGHT, PIXEL_WIDTH, PixelGrid};
/// let grid = PixelGrid::new(PIXEL_WIDTH, PIXEL_HEIGHT);
/// # use servicepoint::{PIXEL_HEIGHT, PIXEL_WIDTH, Bitmap};
/// let grid = Bitmap::new(PIXEL_WIDTH, PIXEL_HEIGHT);
/// ```
pub const PIXEL_HEIGHT: usize = TILE_HEIGHT * TILE_SIZE;
@ -119,10 +119,10 @@ pub const PIXEL_COUNT: usize = PIXEL_WIDTH * PIXEL_HEIGHT;
///
/// ```rust
/// # use std::time::Instant;
/// # use servicepoint::{Command, CompressionCode, FRAME_PACING, Origin, PixelGrid};
/// # use servicepoint::{Command, CompressionCode, FRAME_PACING, Origin, Bitmap};
/// # let connection = servicepoint::Connection::open("172.23.42.29:2342")
/// # .expect("connection failed");
/// # let pixels = PixelGrid::max_sized();
/// # let pixels = Bitmap::max_sized();
/// loop {
/// let start = Instant::now();
///

View file

@ -28,7 +28,7 @@ use std::mem::size_of;
use crate::compression::into_compressed;
use crate::{
command_code::CommandCode, Command, CompressionCode, Grid, Offset, Origin,
PixelGrid, Pixels, Tiles, TILE_SIZE,
Bitmap, Pixels, Tiles, TILE_SIZE,
};
/// A raw header.
@ -214,7 +214,7 @@ impl From<Command> for Packet {
}
impl Packet {
/// Helper method for `BitMapLinear*`-Commands into [Packet]
/// Helper method for `BitmapLinear*`-Commands into [Packet]
#[allow(clippy::cast_possible_truncation)]
fn bitmap_linear_into_packet(
command: CommandCode,
@ -239,7 +239,7 @@ impl Packet {
#[allow(clippy::cast_possible_truncation)]
fn bitmap_win_into_packet(
origin: Origin<Pixels>,
pixels: PixelGrid,
pixels: Bitmap,
compression: CompressionCode,
) -> Packet {
debug_assert_eq!(origin.x % 8, 0);

View file

@ -21,8 +21,8 @@ int main(void) {
if (connection == NULL)
return 1;
SPPixelGrid *pixels = sp_pixel_grid_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT);
sp_pixel_grid_fill(pixels, true);
SPBitmap *pixels = sp_bitmap_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT);
sp_bitmap_fill(pixels, true);
SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed);
while (sp_connection_send_command(connection, sp_command_clone(command)));

View file

@ -83,6 +83,20 @@ typedef uint16_t SPCompressionCode;
*/
typedef struct SPBitVec SPBitVec;
/**
* A grid of pixels.
*
* # Examples
*
* ```C
* Cp437Grid grid = sp_bitmap_new(8, 3);
* sp_bitmap_fill(grid, true);
* sp_bitmap_set(grid, 0, 0, false);
* sp_bitmap_free(grid);
* ```
*/
typedef struct SPBitmap SPBitmap;
/**
* A grid containing brightness values.
*
@ -152,20 +166,6 @@ typedef struct SPCp437Grid SPCp437Grid;
*/
typedef struct SPPacket SPPacket;
/**
* A grid of pixels.
*
* # Examples
*
* ```C
* Cp437Grid grid = sp_pixel_grid_new(8, 3);
* sp_pixel_grid_fill(grid, true);
* sp_pixel_grid_set(grid, 0, 0, false);
* sp_pixel_grid_free(grid);
* ```
*/
typedef struct SPPixelGrid SPPixelGrid;
/**
* Represents a span of memory (`&mut [u8]` ) as a struct usable by C code.
*
@ -403,6 +403,219 @@ void sp_bit_vec_set(struct SPBitVec *bit_vec, size_t index, bool value);
*/
struct SPByteSlice sp_bit_vec_unsafe_data_ref(struct SPBitVec *bit_vec);
/**
* Clones a [SPBitmap].
*
* Will never return NULL.
*
* # Panics
*
* - when `bitmap` is NULL
*
* # Safety
*
* The caller has to make sure that:
*
* - `bitmap` points to a valid [SPBitmap]
* - `bitmap` is not written to concurrently
* - the returned instance is freed in some way, either by using a consuming function or
* by explicitly calling `sp_bitmap_free`.
*/
struct SPBitmap *sp_bitmap_clone(const struct SPBitmap *bitmap);
/**
* Sets the state of all pixels in the [SPBitmap].
*
* # Arguments
*
* - `bitmap`: instance to write to
* - `value`: the value to set all pixels to
*
* # Panics
*
* - when `bitmap` is NULL
*
* # Safety
*
* The caller has to make sure that:
*
* - `bitmap` points to a valid [SPBitmap]
* - `bitmap` is not written to or read from concurrently
*/
void sp_bitmap_fill(struct SPBitmap *bitmap, bool value);
/**
* Deallocates a [SPBitmap].
*
* # Panics
*
* - when `bitmap` is NULL
*
* # Safety
*
* The caller has to make sure that:
*
* - `bitmap` points to a valid [SPBitmap]
* - `bitmap` is not used concurrently or after bitmap call
* - `bitmap` was not passed to another consuming function, e.g. to create a [SPCommand]
*/
void sp_bitmap_free(struct SPBitmap *bitmap);
/**
* Gets the current value at the specified position in the [SPBitmap].
*
* # Arguments
*
* - `bitmap`: instance to read from
* - `x` and `y`: position of the cell to read
*
* # Panics
*
* - when `bitmap` is NULL
* - when accessing `x` or `y` out of bounds
*
* # Safety
*
* The caller has to make sure that:
*
* - `bitmap` points to a valid [SPBitmap]
* - `bitmap` is not written to concurrently
*/
bool sp_bitmap_get(const struct SPBitmap *bitmap, size_t x, size_t y);
/**
* Gets the height in pixels of the [SPBitmap] instance.
*
* # Arguments
*
* - `bitmap`: instance to read from
*
* # Panics
*
* - when `bitmap` is NULL
*
* # Safety
*
* The caller has to make sure that:
*
* - `bitmap` points to a valid [SPBitmap]
*/
size_t sp_bitmap_height(const struct SPBitmap *bitmap);
/**
* Loads a [SPBitmap] with the specified dimensions from the provided data.
*
* # Arguments
*
* - `width`: size in pixels in x-direction
* - `height`: size in pixels in y-direction
*
* returns: [SPBitmap] that contains a copy of the provided data. Will never return NULL.
*
* # Panics
*
* - when `data` is NULL
* - when the dimensions and data size do not match exactly.
* - when the width is not dividable by 8
*
* # Safety
*
* The caller has to make sure that:
*
* - `data` points to a valid memory location of at least `data_length` bytes in size.
* - the returned instance is freed in some way, either by using a consuming function or
* by explicitly calling `sp_bitmap_free`.
*/
struct SPBitmap *sp_bitmap_load(size_t width,
size_t height,
const uint8_t *data,
size_t data_length);
/**
* Creates a new [SPBitmap] with the specified dimensions.
*
* # Arguments
*
* - `width`: size in pixels in x-direction
* - `height`: size in pixels in y-direction
*
* returns: [SPBitmap] initialized to all pixels off. Will never return NULL.
*
* # Panics
*
* - when the width is not dividable by 8
*
* # Safety
*
* The caller has to make sure that:
*
* - the returned instance is freed in some way, either by using a consuming function or
* by explicitly calling `sp_bitmap_free`.
*/
struct SPBitmap *sp_bitmap_new(size_t width,
size_t height);
/**
* Sets the value of the specified position in the [SPBitmap].
*
* # Arguments
*
* - `bitmap`: instance to write to
* - `x` and `y`: position of the cell
* - `value`: the value to write to the cell
*
* returns: old value of the cell
*
* # Panics
*
* - when `bitmap` is NULL
* - when accessing `x` or `y` out of bounds
*
* # Safety
*
* The caller has to make sure that:
*
* - `bitmap` points to a valid [SPBitmap]
* - `bitmap` is not written to or read from concurrently
*/
void sp_bitmap_set(struct SPBitmap *bitmap, size_t x, size_t y, bool value);
/**
* Gets an unsafe reference to the data of the [SPBitmap] instance.
*
* # Panics
*
* - when `bitmap` is NULL
*
* # Safety
*
* The caller has to make sure that:
*
* - `bitmap` points to a valid [SPBitmap]
* - the returned memory range is never accessed after the passed [SPBitmap] has been freed
* - the returned memory range is never accessed concurrently, either via the [SPBitmap] or directly
*/
struct SPByteSlice sp_bitmap_unsafe_data_ref(struct SPBitmap *bitmap);
/**
* Gets the width in pixels of the [SPBitmap] instance.
*
* # Arguments
*
* - `bitmap`: instance to read from
*
* # Panics
*
* - when `bitmap` is NULL
*
* # Safety
*
* The caller has to make sure that:
*
* - `bitmap` points to a valid [SPBitmap]
*/
size_t sp_bitmap_width(const struct SPBitmap *bitmap);
/**
* Clones a [SPBrightnessGrid].
*
@ -726,28 +939,28 @@ struct SPCommand *sp_command_bitmap_linear_or(size_t offset,
/**
* Sets a window of pixels to the specified values.
*
* The passed [SPPixelGrid] gets consumed.
* The passed [SPBitmap] gets consumed.
*
* Returns: a new [Command::BitmapLinearWin] instance. Will never return NULL.
*
* # Panics
*
* - when `pixel_grid` is null
* - when `bitmap` is null
* - when `compression_code` is not a valid value
*
* # Safety
*
* The caller has to make sure that:
*
* - `pixel_grid` points to a valid instance of [SPPixelGrid]
* - `pixel_grid` is not used concurrently or after this call
* - `bitmap` points to a valid instance of [SPBitmap]
* - `bitmap` is not used concurrently or after this call
* - `compression` matches one of the allowed enum values
* - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
* by explicitly calling `sp_command_free`.
*/
struct SPCommand *sp_command_bitmap_linear_win(size_t x,
size_t y,
struct SPPixelGrid *pixel_grid,
struct SPBitmap *bitmap,
SPCompressionCode compression_code);
/**
@ -1330,224 +1543,6 @@ struct SPPacket *sp_packet_from_command(struct SPCommand *command);
struct SPPacket *sp_packet_try_load(const uint8_t *data,
size_t length);
/**
* Clones a [SPPixelGrid].
*
* Will never return NULL.
*
* # Panics
*
* - when `pixel_grid` is NULL
*
* # Safety
*
* The caller has to make sure that:
*
* - `pixel_grid` points to a valid [SPPixelGrid]
* - `pixel_grid` is not written to concurrently
* - the returned instance is freed in some way, either by using a consuming function or
* by explicitly calling `sp_pixel_grid_free`.
*/
struct SPPixelGrid *sp_pixel_grid_clone(const struct SPPixelGrid *pixel_grid);
/**
* Sets the state of all pixels in the [SPPixelGrid].
*
* # Arguments
*
* - `pixel_grid`: instance to write to
* - `value`: the value to set all pixels to
*
* # Panics
*
* - when `pixel_grid` is NULL
*
* # Safety
*
* The caller has to make sure that:
*
* - `pixel_grid` points to a valid [SPPixelGrid]
* - `pixel_grid` is not written to or read from concurrently
*/
void sp_pixel_grid_fill(struct SPPixelGrid *pixel_grid, bool value);
/**
* Deallocates a [SPPixelGrid].
*
* # Panics
*
* - when `pixel_grid` is NULL
*
* # Safety
*
* The caller has to make sure that:
*
* - `pixel_grid` points to a valid [SPPixelGrid]
* - `pixel_grid` is not used concurrently or after pixel_grid call
* - `pixel_grid` was not passed to another consuming function, e.g. to create a [SPCommand]
*/
void sp_pixel_grid_free(struct SPPixelGrid *pixel_grid);
/**
* Gets the current value at the specified position in the [SPPixelGrid].
*
* # Arguments
*
* - `pixel_grid`: instance to read from
* - `x` and `y`: position of the cell to read
*
* # Panics
*
* - when `pixel_grid` is NULL
* - when accessing `x` or `y` out of bounds
*
* # Safety
*
* The caller has to make sure that:
*
* - `pixel_grid` points to a valid [SPPixelGrid]
* - `pixel_grid` is not written to concurrently
*/
bool sp_pixel_grid_get(const struct SPPixelGrid *pixel_grid,
size_t x,
size_t y);
/**
* Gets the height in pixels of the [SPPixelGrid] instance.
*
* # Arguments
*
* - `pixel_grid`: instance to read from
*
* # Panics
*
* - when `pixel_grid` is NULL
*
* # Safety
*
* The caller has to make sure that:
*
* - `pixel_grid` points to a valid [SPPixelGrid]
*/
size_t sp_pixel_grid_height(const struct SPPixelGrid *pixel_grid);
/**
* Loads a [SPPixelGrid] with the specified dimensions from the provided data.
*
* # Arguments
*
* - `width`: size in pixels in x-direction
* - `height`: size in pixels in y-direction
*
* returns: [SPPixelGrid] that contains a copy of the provided data. Will never return NULL.
*
* # Panics
*
* - when `data` is NULL
* - when the dimensions and data size do not match exactly.
* - when the width is not dividable by 8
*
* # Safety
*
* The caller has to make sure that:
*
* - `data` points to a valid memory location of at least `data_length` bytes in size.
* - the returned instance is freed in some way, either by using a consuming function or
* by explicitly calling `sp_pixel_grid_free`.
*/
struct SPPixelGrid *sp_pixel_grid_load(size_t width,
size_t height,
const uint8_t *data,
size_t data_length);
/**
* Creates a new [SPPixelGrid] with the specified dimensions.
*
* # Arguments
*
* - `width`: size in pixels in x-direction
* - `height`: size in pixels in y-direction
*
* returns: [SPPixelGrid] initialized to all pixels off. Will never return NULL.
*
* # Panics
*
* - when the width is not dividable by 8
*
* # Safety
*
* The caller has to make sure that:
*
* - the returned instance is freed in some way, either by using a consuming function or
* by explicitly calling `sp_pixel_grid_free`.
*/
struct SPPixelGrid *sp_pixel_grid_new(size_t width,
size_t height);
/**
* Sets the value of the specified position in the [SPPixelGrid].
*
* # Arguments
*
* - `pixel_grid`: instance to write to
* - `x` and `y`: position of the cell
* - `value`: the value to write to the cell
*
* returns: old value of the cell
*
* # Panics
*
* - when `pixel_grid` is NULL
* - when accessing `x` or `y` out of bounds
*
* # Safety
*
* The caller has to make sure that:
*
* - `pixel_grid` points to a valid [SPPixelGrid]
* - `pixel_grid` is not written to or read from concurrently
*/
void sp_pixel_grid_set(struct SPPixelGrid *pixel_grid,
size_t x,
size_t y,
bool value);
/**
* Gets an unsafe reference to the data of the [SPPixelGrid] instance.
*
* # Panics
*
* - when `pixel_grid` is NULL
*
* # Safety
*
* The caller has to make sure that:
*
* - `pixel_grid` points to a valid [SPPixelGrid]
* - the returned memory range is never accessed after the passed [SPPixelGrid] has been freed
* - the returned memory range is never accessed concurrently, either via the [SPPixelGrid] or directly
*/
struct SPByteSlice sp_pixel_grid_unsafe_data_ref(struct SPPixelGrid *pixel_grid);
/**
* Gets the width in pixels of the [SPPixelGrid] instance.
*
* # Arguments
*
* - `pixel_grid`: instance to read from
*
* # Panics
*
* - when `pixel_grid` is NULL
*
* # Safety
*
* The caller has to make sure that:
*
* - `pixel_grid` points to a valid [SPPixelGrid]
*/
size_t sp_pixel_grid_width(const struct SPPixelGrid *pixel_grid);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

View file

@ -6,8 +6,8 @@ int main(void) {
if (connection == NULL)
return 1;
SPPixelGrid *pixels = sp_pixel_grid_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT);
sp_pixel_grid_fill(pixels, true);
SPBitmap *pixels = sp_bitmap_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT);
sp_bitmap_fill(pixels, true);
SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, SP_COMPRESSION_CODE_UNCOMPRESSED);
while (sp_connection_send_command(connection, sp_command_clone(command)));

View file

@ -0,0 +1,290 @@
//! C functions for interacting with [SPBitmap]s
//!
//! prefix `sp_bitmap_`
use servicepoint::{DataRef, Grid};
use crate::byte_slice::SPByteSlice;
/// A grid of pixels.
///
/// # Examples
///
/// ```C
/// Cp437Grid grid = sp_bitmap_new(8, 3);
/// sp_bitmap_fill(grid, true);
/// sp_bitmap_set(grid, 0, 0, false);
/// sp_bitmap_free(grid);
/// ```
pub struct SPBitmap(pub(crate) servicepoint::Bitmap);
/// Creates a new [SPBitmap] with the specified dimensions.
///
/// # Arguments
///
/// - `width`: size in pixels in x-direction
/// - `height`: size in pixels in y-direction
///
/// returns: [SPBitmap] initialized to all pixels off. Will never return NULL.
///
/// # Panics
///
/// - when the width is not dividable by 8
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_bitmap_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_bitmap_new(
width: usize,
height: usize,
) -> *mut SPBitmap {
let result = Box::into_raw(Box::new(SPBitmap(servicepoint::Bitmap::new(
width, height,
))));
assert!(!result.is_null());
result
}
/// Loads a [SPBitmap] with the specified dimensions from the provided data.
///
/// # Arguments
///
/// - `width`: size in pixels in x-direction
/// - `height`: size in pixels in y-direction
///
/// returns: [SPBitmap] that contains a copy of the provided data. Will never return NULL.
///
/// # Panics
///
/// - when `data` is NULL
/// - when the dimensions and data size do not match exactly.
/// - when the width is not dividable by 8
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `data` points to a valid memory location of at least `data_length` bytes in size.
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_bitmap_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_bitmap_load(
width: usize,
height: usize,
data: *const u8,
data_length: usize,
) -> *mut SPBitmap {
assert!(!data.is_null());
let data = std::slice::from_raw_parts(data, data_length);
let result = Box::into_raw(Box::new(SPBitmap(servicepoint::Bitmap::load(
width, height, data,
))));
assert!(!result.is_null());
result
}
/// Clones a [SPBitmap].
///
/// Will never return NULL.
///
/// # Panics
///
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [SPBitmap]
/// - `bitmap` is not written to concurrently
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_bitmap_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_bitmap_clone(
bitmap: *const SPBitmap,
) -> *mut SPBitmap {
assert!(!bitmap.is_null());
let result = Box::into_raw(Box::new(SPBitmap((*bitmap).0.clone())));
assert!(!result.is_null());
result
}
/// Deallocates a [SPBitmap].
///
/// # Panics
///
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [SPBitmap]
/// - `bitmap` is not used concurrently or after bitmap call
/// - `bitmap` was not passed to another consuming function, e.g. to create a [SPCommand]
#[no_mangle]
pub unsafe extern "C" fn sp_bitmap_free(bitmap: *mut SPBitmap) {
assert!(!bitmap.is_null());
_ = Box::from_raw(bitmap);
}
/// Gets the current value at the specified position in the [SPBitmap].
///
/// # Arguments
///
/// - `bitmap`: instance to read from
/// - `x` and `y`: position of the cell to read
///
/// # Panics
///
/// - when `bitmap` is NULL
/// - when accessing `x` or `y` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [SPBitmap]
/// - `bitmap` is not written to concurrently
#[no_mangle]
pub unsafe extern "C" fn sp_bitmap_get(
bitmap: *const SPBitmap,
x: usize,
y: usize,
) -> bool {
assert!(!bitmap.is_null());
(*bitmap).0.get(x, y)
}
/// Sets the value of the specified position in the [SPBitmap].
///
/// # Arguments
///
/// - `bitmap`: instance to write to
/// - `x` and `y`: position of the cell
/// - `value`: the value to write to the cell
///
/// returns: old value of the cell
///
/// # Panics
///
/// - when `bitmap` is NULL
/// - when accessing `x` or `y` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [SPBitmap]
/// - `bitmap` is not written to or read from concurrently
#[no_mangle]
pub unsafe extern "C" fn sp_bitmap_set(
bitmap: *mut SPBitmap,
x: usize,
y: usize,
value: bool,
) {
assert!(!bitmap.is_null());
(*bitmap).0.set(x, y, value);
}
/// Sets the state of all pixels in the [SPBitmap].
///
/// # Arguments
///
/// - `bitmap`: instance to write to
/// - `value`: the value to set all pixels to
///
/// # Panics
///
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [SPBitmap]
/// - `bitmap` is not written to or read from concurrently
#[no_mangle]
pub unsafe extern "C" fn sp_bitmap_fill(
bitmap: *mut SPBitmap,
value: bool,
) {
assert!(!bitmap.is_null());
(*bitmap).0.fill(value);
}
/// Gets the width in pixels of the [SPBitmap] instance.
///
/// # Arguments
///
/// - `bitmap`: instance to read from
///
/// # Panics
///
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [SPBitmap]
#[no_mangle]
pub unsafe extern "C" fn sp_bitmap_width(
bitmap: *const SPBitmap,
) -> usize {
assert!(!bitmap.is_null());
(*bitmap).0.width()
}
/// Gets the height in pixels of the [SPBitmap] instance.
///
/// # Arguments
///
/// - `bitmap`: instance to read from
///
/// # Panics
///
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [SPBitmap]
#[no_mangle]
pub unsafe extern "C" fn sp_bitmap_height(
bitmap: *const SPBitmap,
) -> usize {
assert!(!bitmap.is_null());
(*bitmap).0.height()
}
/// Gets an unsafe reference to the data of the [SPBitmap] instance.
///
/// # Panics
///
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid [SPBitmap]
/// - the returned memory range is never accessed after the passed [SPBitmap] has been freed
/// - the returned memory range is never accessed concurrently, either via the [SPBitmap] or directly
#[no_mangle]
pub unsafe extern "C" fn sp_bitmap_unsafe_data_ref(
bitmap: *mut SPBitmap,
) -> SPByteSlice {
assert!(!bitmap.is_null());
let data = (*bitmap).0.data_ref_mut();
SPByteSlice {
start: data.as_mut_ptr_range().start,
length: data.len(),
}
}

View file

@ -8,7 +8,7 @@ use servicepoint::{Brightness, Origin};
use crate::{
SPBitVec, SPBrightnessGrid, SPCompressionCode, SPCp437Grid, SPPacket,
SPPixelGrid,
SPBitmap,
};
/// A low-level display command.
@ -413,21 +413,21 @@ pub unsafe extern "C" fn sp_command_cp437_data(
/// Sets a window of pixels to the specified values.
///
/// The passed [SPPixelGrid] gets consumed.
/// The passed [SPBitmap] gets consumed.
///
/// Returns: a new [Command::BitmapLinearWin] instance. Will never return NULL.
///
/// # Panics
///
/// - when `pixel_grid` is null
/// - when `bitmap` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid instance of [SPPixelGrid]
/// - `pixel_grid` is not used concurrently or after this call
/// - `bitmap` points to a valid instance of [SPBitmap]
/// - `bitmap` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
@ -435,11 +435,11 @@ pub unsafe extern "C" fn sp_command_cp437_data(
pub unsafe extern "C" fn sp_command_bitmap_linear_win(
x: usize,
y: usize,
pixel_grid: *mut SPPixelGrid,
bitmap: *mut SPBitmap,
compression_code: SPCompressionCode,
) -> *mut SPCommand {
assert!(!pixel_grid.is_null());
let byte_grid = (*Box::from_raw(pixel_grid)).0;
assert!(!bitmap.is_null());
let byte_grid = (*Box::from_raw(bitmap)).0;
let result = Box::into_raw(Box::new(SPCommand(servicepoint::Command::BitmapLinearWin(
Origin::new(x, y),
byte_grid,

View file

@ -13,8 +13,8 @@
//! if (connection == NULL)
//! return 1;
//!
//! SPPixelGrid *pixels = sp_pixel_grid_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT);
//! sp_pixel_grid_fill(pixels, true);
//! SPBitmap *pixels = sp_bitmap_new(SP_PIXEL_WIDTH, SP_PIXEL_HEIGHT);
//! sp_bitmap_fill(pixels, true);
//!
//! SPCommand *command = sp_command_bitmap_linear_win(0, 0, pixels, Uncompressed);
//! while (sp_connection_send_command(connection, sp_command_clone(command)));
@ -33,7 +33,7 @@ pub use crate::connection::*;
pub use crate::constants::*;
pub use crate::cp437_grid::*;
pub use crate::packet::*;
pub use crate::pixel_grid::*;
pub use crate::bitmap::*;
mod bit_vec;
mod brightness_grid;
@ -43,4 +43,4 @@ mod connection;
mod constants;
mod cp437_grid;
mod packet;
mod pixel_grid;
mod bitmap;

View file

@ -1,290 +0,0 @@
//! C functions for interacting with [SPPixelGrid]s
//!
//! prefix `sp_pixel_grid_`
use servicepoint::{DataRef, Grid};
use crate::byte_slice::SPByteSlice;
/// A grid of pixels.
///
/// # Examples
///
/// ```C
/// Cp437Grid grid = sp_pixel_grid_new(8, 3);
/// sp_pixel_grid_fill(grid, true);
/// sp_pixel_grid_set(grid, 0, 0, false);
/// sp_pixel_grid_free(grid);
/// ```
pub struct SPPixelGrid(pub(crate) servicepoint::PixelGrid);
/// Creates a new [SPPixelGrid] with the specified dimensions.
///
/// # Arguments
///
/// - `width`: size in pixels in x-direction
/// - `height`: size in pixels in y-direction
///
/// returns: [SPPixelGrid] initialized to all pixels off. Will never return NULL.
///
/// # Panics
///
/// - when the width is not dividable by 8
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_pixel_grid_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_pixel_grid_new(
width: usize,
height: usize,
) -> *mut SPPixelGrid {
let result = Box::into_raw(Box::new(SPPixelGrid(servicepoint::PixelGrid::new(
width, height,
))));
assert!(!result.is_null());
result
}
/// Loads a [SPPixelGrid] with the specified dimensions from the provided data.
///
/// # Arguments
///
/// - `width`: size in pixels in x-direction
/// - `height`: size in pixels in y-direction
///
/// returns: [SPPixelGrid] that contains a copy of the provided data. Will never return NULL.
///
/// # Panics
///
/// - when `data` is NULL
/// - when the dimensions and data size do not match exactly.
/// - when the width is not dividable by 8
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `data` points to a valid memory location of at least `data_length` bytes in size.
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_pixel_grid_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_pixel_grid_load(
width: usize,
height: usize,
data: *const u8,
data_length: usize,
) -> *mut SPPixelGrid {
assert!(!data.is_null());
let data = std::slice::from_raw_parts(data, data_length);
let result = Box::into_raw(Box::new(SPPixelGrid(servicepoint::PixelGrid::load(
width, height, data,
))));
assert!(!result.is_null());
result
}
/// Clones a [SPPixelGrid].
///
/// Will never return NULL.
///
/// # Panics
///
/// - when `pixel_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - `pixel_grid` is not written to concurrently
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_pixel_grid_free`.
#[no_mangle]
pub unsafe extern "C" fn sp_pixel_grid_clone(
pixel_grid: *const SPPixelGrid,
) -> *mut SPPixelGrid {
assert!(!pixel_grid.is_null());
let result = Box::into_raw(Box::new(SPPixelGrid((*pixel_grid).0.clone())));
assert!(!result.is_null());
result
}
/// Deallocates a [SPPixelGrid].
///
/// # Panics
///
/// - when `pixel_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - `pixel_grid` is not used concurrently or after pixel_grid call
/// - `pixel_grid` was not passed to another consuming function, e.g. to create a [SPCommand]
#[no_mangle]
pub unsafe extern "C" fn sp_pixel_grid_free(pixel_grid: *mut SPPixelGrid) {
assert!(!pixel_grid.is_null());
_ = Box::from_raw(pixel_grid);
}
/// Gets the current value at the specified position in the [SPPixelGrid].
///
/// # Arguments
///
/// - `pixel_grid`: instance to read from
/// - `x` and `y`: position of the cell to read
///
/// # Panics
///
/// - when `pixel_grid` is NULL
/// - when accessing `x` or `y` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - `pixel_grid` is not written to concurrently
#[no_mangle]
pub unsafe extern "C" fn sp_pixel_grid_get(
pixel_grid: *const SPPixelGrid,
x: usize,
y: usize,
) -> bool {
assert!(!pixel_grid.is_null());
(*pixel_grid).0.get(x, y)
}
/// Sets the value of the specified position in the [SPPixelGrid].
///
/// # Arguments
///
/// - `pixel_grid`: instance to write to
/// - `x` and `y`: position of the cell
/// - `value`: the value to write to the cell
///
/// returns: old value of the cell
///
/// # Panics
///
/// - when `pixel_grid` is NULL
/// - when accessing `x` or `y` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - `pixel_grid` is not written to or read from concurrently
#[no_mangle]
pub unsafe extern "C" fn sp_pixel_grid_set(
pixel_grid: *mut SPPixelGrid,
x: usize,
y: usize,
value: bool,
) {
assert!(!pixel_grid.is_null());
(*pixel_grid).0.set(x, y, value);
}
/// Sets the state of all pixels in the [SPPixelGrid].
///
/// # Arguments
///
/// - `pixel_grid`: instance to write to
/// - `value`: the value to set all pixels to
///
/// # Panics
///
/// - when `pixel_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - `pixel_grid` is not written to or read from concurrently
#[no_mangle]
pub unsafe extern "C" fn sp_pixel_grid_fill(
pixel_grid: *mut SPPixelGrid,
value: bool,
) {
assert!(!pixel_grid.is_null());
(*pixel_grid).0.fill(value);
}
/// Gets the width in pixels of the [SPPixelGrid] instance.
///
/// # Arguments
///
/// - `pixel_grid`: instance to read from
///
/// # Panics
///
/// - when `pixel_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
#[no_mangle]
pub unsafe extern "C" fn sp_pixel_grid_width(
pixel_grid: *const SPPixelGrid,
) -> usize {
assert!(!pixel_grid.is_null());
(*pixel_grid).0.width()
}
/// Gets the height in pixels of the [SPPixelGrid] instance.
///
/// # Arguments
///
/// - `pixel_grid`: instance to read from
///
/// # Panics
///
/// - when `pixel_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
#[no_mangle]
pub unsafe extern "C" fn sp_pixel_grid_height(
pixel_grid: *const SPPixelGrid,
) -> usize {
assert!(!pixel_grid.is_null());
(*pixel_grid).0.height()
}
/// Gets an unsafe reference to the data of the [SPPixelGrid] instance.
///
/// # Panics
///
/// - when `pixel_grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - the returned memory range is never accessed after the passed [SPPixelGrid] has been freed
/// - the returned memory range is never accessed concurrently, either via the [SPPixelGrid] or directly
#[no_mangle]
pub unsafe extern "C" fn sp_pixel_grid_unsafe_data_ref(
pixel_grid: *mut SPPixelGrid,
) -> SPByteSlice {
assert!(!pixel_grid.is_null());
let data = (*pixel_grid).0.data_ref_mut();
SPByteSlice {
start: data.as_mut_ptr_range().start,
length: data.len(),
}
}

View file

@ -11,7 +11,7 @@ using ServicePoint;
// using statement calls Dispose() on scope exit, which frees unmanaged instances
using var connection = Connection.Open("127.0.0.1:2342");
using var pixels = PixelGrid.New(Constants.PixelWidth, Constants.PixelHeight);
using var pixels = Bitmap.New(Constants.PixelWidth, Constants.PixelHeight);
while (true)
{

View file

@ -464,341 +464,6 @@ namespace ServicePoint.BindGen
[DllImport(__DllName, EntryPoint = "sp_brightness_grid_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ByteSlice sp_brightness_grid_unsafe_data_ref(BrightnessGrid* brightness_grid);
/// <summary>
/// Tries to turn a [SPPacket] into a [SPCommand].
///
/// The packet is deallocated in the process.
///
/// Returns: pointer to new [SPCommand] instance or NULL if parsing failed.
///
/// # Panics
///
/// - when `packet` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - [SPPacket] points to a valid instance of [SPPacket]
/// - [SPPacket] is not used concurrently or after this call
/// - the result is checked for NULL
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_try_from_packet", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_try_from_packet(Packet* packet);
/// <summary>
/// Clones a [SPCommand] instance.
///
/// returns: new [SPCommand] instance. Will never return NULL.
///
/// # Panics
///
/// - when `command` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `command` points to a valid instance of [SPCommand]
/// - `command` is not written to concurrently
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_clone(Command* command);
/// <summary>
/// Set all pixels to the off state.
///
/// Does not affect brightness.
///
/// Returns: a new [Command::Clear] instance. Will never return NULL.
///
/// # Examples
///
/// ```C
/// sp_connection_send_command(connection, sp_command_clear());
/// ```
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_clear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_clear();
/// <summary>
/// Kills the udp daemon on the display, which usually results in a restart.
///
/// Please do not send this in your normal program flow.
///
/// Returns: a new [Command::HardReset] instance. Will never return NULL.
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_hard_reset", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_hard_reset();
/// <summary>
/// A yet-to-be-tested command.
///
/// Returns: a new `Command::FadeOut` instance. Will never return NULL.
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_fade_out", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_fade_out();
/// <summary>
/// Set the brightness of all tiles to the same value.
///
/// Returns: a new [Command::Brightness] instance. Will never return NULL.
///
/// # Panics
///
/// - When the provided brightness value is out of range (0-11).
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_brightness", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_brightness(byte brightness);
/// <summary>
/// Set the brightness of individual tiles in a rectangular area of the display.
///
/// The passed [SPBrightnessGrid] gets consumed.
///
/// Returns: a new [Command::CharBrightness] instance. Will never return NULL.
///
/// # Panics
///
/// - when `grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `grid` points to a valid instance of [SPBrightnessGrid]
/// - `grid` is not used concurrently or after this call
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_char_brightness", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_char_brightness(nuint x, nuint y, BrightnessGrid* grid);
/// <summary>
/// Set pixel data starting at the pixel offset on screen.
///
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
/// once the starting row is full, overwriting will continue on column 0.
///
/// The contained [SPBitVec] is always uncompressed.
///
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new [Command::BitmapLinear] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear(nuint offset, BitVec* bit_vec, CompressionCode compression);
/// <summary>
/// Set pixel data according to an and-mask starting at the offset.
///
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
/// once the starting row is full, overwriting will continue on column 0.
///
/// The contained [SPBitVec] is always uncompressed.
///
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new [Command::BitmapLinearAnd] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_and", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_and(nuint offset, BitVec* bit_vec, CompressionCode compression);
/// <summary>
/// Set pixel data according to an or-mask starting at the offset.
///
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
/// once the starting row is full, overwriting will continue on column 0.
///
/// The contained [SPBitVec] is always uncompressed.
///
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new [Command::BitmapLinearOr] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_or", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_or(nuint offset, BitVec* bit_vec, CompressionCode compression);
/// <summary>
/// Set pixel data according to a xor-mask starting at the offset.
///
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
/// once the starting row is full, overwriting will continue on column 0.
///
/// The contained [SPBitVec] is always uncompressed.
///
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new [Command::BitmapLinearXor] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_xor", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_xor(nuint offset, BitVec* bit_vec, CompressionCode compression);
/// <summary>
/// Show text on the screen.
///
/// The passed [SPCp437Grid] gets consumed.
///
/// Returns: a new [Command::Cp437Data] instance. Will never return NULL.
///
/// # Panics
///
/// - when `grid` is null
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `grid` points to a valid instance of [SPCp437Grid]
/// - `grid` is not used concurrently or after this call
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_cp437_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_cp437_data(nuint x, nuint y, Cp437Grid* grid);
/// <summary>
/// Sets a window of pixels to the specified values.
///
/// The passed [SPPixelGrid] gets consumed.
///
/// Returns: a new [Command::BitmapLinearWin] instance. Will never return NULL.
///
/// # Panics
///
/// - when `pixel_grid` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid instance of [SPPixelGrid]
/// - `pixel_grid` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_win", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_win(nuint x, nuint y, PixelGrid* pixel_grid, CompressionCode compression_code);
/// <summary>
/// Deallocates a [SPCommand].
///
/// # Examples
///
/// ```C
/// SPCommand c = sp_command_clear();
/// sp_command_free(c);
/// ```
///
/// # Panics
///
/// - when `command` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `command` points to a valid [SPCommand]
/// - `command` is not used concurrently or after this call
/// - `command` was not passed to another consuming function, e.g. to create a [SPPacket]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_command_free(Command* command);
/// <summary>
/// Creates a new instance of [SPConnection].
///
@ -1172,14 +837,349 @@ namespace ServicePoint.BindGen
public static extern void sp_packet_free(Packet* packet);
/// <summary>
/// Creates a new [SPPixelGrid] with the specified dimensions.
/// Tries to turn a [SPPacket] into a [SPCommand].
///
/// The packet is deallocated in the process.
///
/// Returns: pointer to new [SPCommand] instance or NULL if parsing failed.
///
/// # Panics
///
/// - when `packet` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - [SPPacket] points to a valid instance of [SPPacket]
/// - [SPPacket] is not used concurrently or after this call
/// - the result is checked for NULL
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_try_from_packet", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_try_from_packet(Packet* packet);
/// <summary>
/// Clones a [SPCommand] instance.
///
/// returns: new [SPCommand] instance. Will never return NULL.
///
/// # Panics
///
/// - when `command` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `command` points to a valid instance of [SPCommand]
/// - `command` is not written to concurrently
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_clone(Command* command);
/// <summary>
/// Set all pixels to the off state.
///
/// Does not affect brightness.
///
/// Returns: a new [Command::Clear] instance. Will never return NULL.
///
/// # Examples
///
/// ```C
/// sp_connection_send_command(connection, sp_command_clear());
/// ```
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_clear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_clear();
/// <summary>
/// Kills the udp daemon on the display, which usually results in a restart.
///
/// Please do not send this in your normal program flow.
///
/// Returns: a new [Command::HardReset] instance. Will never return NULL.
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_hard_reset", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_hard_reset();
/// <summary>
/// A yet-to-be-tested command.
///
/// Returns: a new `Command::FadeOut` instance. Will never return NULL.
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_fade_out", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_fade_out();
/// <summary>
/// Set the brightness of all tiles to the same value.
///
/// Returns: a new [Command::Brightness] instance. Will never return NULL.
///
/// # Panics
///
/// - When the provided brightness value is out of range (0-11).
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_brightness", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_brightness(byte brightness);
/// <summary>
/// Set the brightness of individual tiles in a rectangular area of the display.
///
/// The passed [SPBrightnessGrid] gets consumed.
///
/// Returns: a new [Command::CharBrightness] instance. Will never return NULL.
///
/// # Panics
///
/// - when `grid` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `grid` points to a valid instance of [SPBrightnessGrid]
/// - `grid` is not used concurrently or after this call
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_char_brightness", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_char_brightness(nuint x, nuint y, BrightnessGrid* grid);
/// <summary>
/// Set pixel data starting at the pixel offset on screen.
///
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
/// once the starting row is full, overwriting will continue on column 0.
///
/// The contained [SPBitVec] is always uncompressed.
///
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new [Command::BitmapLinear] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear(nuint offset, BitVec* bit_vec, CompressionCode compression);
/// <summary>
/// Set pixel data according to an and-mask starting at the offset.
///
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
/// once the starting row is full, overwriting will continue on column 0.
///
/// The contained [SPBitVec] is always uncompressed.
///
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new [Command::BitmapLinearAnd] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_and", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_and(nuint offset, BitVec* bit_vec, CompressionCode compression);
/// <summary>
/// Set pixel data according to an or-mask starting at the offset.
///
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
/// once the starting row is full, overwriting will continue on column 0.
///
/// The contained [SPBitVec] is always uncompressed.
///
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new [Command::BitmapLinearOr] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_or", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_or(nuint offset, BitVec* bit_vec, CompressionCode compression);
/// <summary>
/// Set pixel data according to a xor-mask starting at the offset.
///
/// The screen will continuously overwrite more pixel data without regarding the offset, meaning
/// once the starting row is full, overwriting will continue on column 0.
///
/// The contained [SPBitVec] is always uncompressed.
///
/// The passed [SPBitVec] gets consumed.
///
/// Returns: a new [Command::BitmapLinearXor] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bit_vec` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bit_vec` points to a valid instance of [SPBitVec]
/// - `bit_vec` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_xor", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_xor(nuint offset, BitVec* bit_vec, CompressionCode compression);
/// <summary>
/// Show text on the screen.
///
/// The passed [SPCp437Grid] gets consumed.
///
/// Returns: a new [Command::Cp437Data] instance. Will never return NULL.
///
/// # Panics
///
/// - when `grid` is null
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `grid` points to a valid instance of [SPCp437Grid]
/// - `grid` is not used concurrently or after this call
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_cp437_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_cp437_data(nuint x, nuint y, Cp437Grid* grid);
/// <summary>
/// Sets a window of pixels to the specified values.
///
/// The passed [SPBitmap] gets consumed.
///
/// Returns: a new [Command::BitmapLinearWin] instance. Will never return NULL.
///
/// # Panics
///
/// - when `bitmap` is null
/// - when `compression_code` is not a valid value
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `bitmap` points to a valid instance of [SPBitmap]
/// - `bitmap` is not used concurrently or after this call
/// - `compression` matches one of the allowed enum values
/// - the returned [SPCommand] instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_command_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_bitmap_linear_win", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Command* sp_command_bitmap_linear_win(nuint x, nuint y, Bitmap* bitmap, CompressionCode compression_code);
/// <summary>
/// Deallocates a [SPCommand].
///
/// # Examples
///
/// ```C
/// SPCommand c = sp_command_clear();
/// sp_command_free(c);
/// ```
///
/// # Panics
///
/// - when `command` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `command` points to a valid [SPCommand]
/// - `command` is not used concurrently or after this call
/// - `command` was not passed to another consuming function, e.g. to create a [SPPacket]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_command_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_command_free(Command* command);
/// <summary>
/// Creates a new [SPBitmap] with the specified dimensions.
///
/// # Arguments
///
/// - `width`: size in pixels in x-direction
/// - `height`: size in pixels in y-direction
///
/// returns: [SPPixelGrid] initialized to all pixels off. Will never return NULL.
/// returns: [SPBitmap] initialized to all pixels off. Will never return NULL.
///
/// # Panics
///
@ -1190,20 +1190,20 @@ namespace ServicePoint.BindGen
/// The caller has to make sure that:
///
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_pixel_grid_free`.
/// by explicitly calling `sp_bitmap_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_pixel_grid_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern PixelGrid* sp_pixel_grid_new(nuint width, nuint height);
[DllImport(__DllName, EntryPoint = "sp_bitmap_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Bitmap* sp_bitmap_new(nuint width, nuint height);
/// <summary>
/// Loads a [SPPixelGrid] with the specified dimensions from the provided data.
/// Loads a [SPBitmap] with the specified dimensions from the provided data.
///
/// # Arguments
///
/// - `width`: size in pixels in x-direction
/// - `height`: size in pixels in y-direction
///
/// returns: [SPPixelGrid] that contains a copy of the provided data. Will never return NULL.
/// returns: [SPBitmap] that contains a copy of the provided data. Will never return NULL.
///
/// # Panics
///
@ -1217,80 +1217,80 @@ namespace ServicePoint.BindGen
///
/// - `data` points to a valid memory location of at least `data_length` bytes in size.
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_pixel_grid_free`.
/// by explicitly calling `sp_bitmap_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_pixel_grid_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern PixelGrid* sp_pixel_grid_load(nuint width, nuint height, byte* data, nuint data_length);
[DllImport(__DllName, EntryPoint = "sp_bitmap_load", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Bitmap* sp_bitmap_load(nuint width, nuint height, byte* data, nuint data_length);
/// <summary>
/// Clones a [SPPixelGrid].
/// Clones a [SPBitmap].
///
/// Will never return NULL.
///
/// # Panics
///
/// - when `pixel_grid` is NULL
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - `pixel_grid` is not written to concurrently
/// - `bitmap` points to a valid [SPBitmap]
/// - `bitmap` is not written to concurrently
/// - the returned instance is freed in some way, either by using a consuming function or
/// by explicitly calling `sp_pixel_grid_free`.
/// by explicitly calling `sp_bitmap_free`.
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_pixel_grid_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern PixelGrid* sp_pixel_grid_clone(PixelGrid* pixel_grid);
[DllImport(__DllName, EntryPoint = "sp_bitmap_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern Bitmap* sp_bitmap_clone(Bitmap* bitmap);
/// <summary>
/// Deallocates a [SPPixelGrid].
/// Deallocates a [SPBitmap].
///
/// # Panics
///
/// - when `pixel_grid` is NULL
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - `pixel_grid` is not used concurrently or after pixel_grid call
/// - `pixel_grid` was not passed to another consuming function, e.g. to create a [SPCommand]
/// - `bitmap` points to a valid [SPBitmap]
/// - `bitmap` is not used concurrently or after bitmap call
/// - `bitmap` was not passed to another consuming function, e.g. to create a [SPCommand]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_pixel_grid_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_pixel_grid_free(PixelGrid* pixel_grid);
[DllImport(__DllName, EntryPoint = "sp_bitmap_free", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_bitmap_free(Bitmap* bitmap);
/// <summary>
/// Gets the current value at the specified position in the [SPPixelGrid].
/// Gets the current value at the specified position in the [SPBitmap].
///
/// # Arguments
///
/// - `pixel_grid`: instance to read from
/// - `bitmap`: instance to read from
/// - `x` and `y`: position of the cell to read
///
/// # Panics
///
/// - when `pixel_grid` is NULL
/// - when `bitmap` is NULL
/// - when accessing `x` or `y` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - `pixel_grid` is not written to concurrently
/// - `bitmap` points to a valid [SPBitmap]
/// - `bitmap` is not written to concurrently
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_pixel_grid_get", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[DllImport(__DllName, EntryPoint = "sp_bitmap_get", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool sp_pixel_grid_get(PixelGrid* pixel_grid, nuint x, nuint y);
public static extern bool sp_bitmap_get(Bitmap* bitmap, nuint x, nuint y);
/// <summary>
/// Sets the value of the specified position in the [SPPixelGrid].
/// Sets the value of the specified position in the [SPBitmap].
///
/// # Arguments
///
/// - `pixel_grid`: instance to write to
/// - `bitmap`: instance to write to
/// - `x` and `y`: position of the cell
/// - `value`: the value to write to the cell
///
@ -1298,98 +1298,98 @@ namespace ServicePoint.BindGen
///
/// # Panics
///
/// - when `pixel_grid` is NULL
/// - when `bitmap` is NULL
/// - when accessing `x` or `y` out of bounds
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - `pixel_grid` is not written to or read from concurrently
/// - `bitmap` points to a valid [SPBitmap]
/// - `bitmap` is not written to or read from concurrently
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_pixel_grid_set", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_pixel_grid_set(PixelGrid* pixel_grid, nuint x, nuint y, [MarshalAs(UnmanagedType.U1)] bool value);
[DllImport(__DllName, EntryPoint = "sp_bitmap_set", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_bitmap_set(Bitmap* bitmap, nuint x, nuint y, [MarshalAs(UnmanagedType.U1)] bool value);
/// <summary>
/// Sets the state of all pixels in the [SPPixelGrid].
/// Sets the state of all pixels in the [SPBitmap].
///
/// # Arguments
///
/// - `pixel_grid`: instance to write to
/// - `bitmap`: instance to write to
/// - `value`: the value to set all pixels to
///
/// # Panics
///
/// - when `pixel_grid` is NULL
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - `pixel_grid` is not written to or read from concurrently
/// - `bitmap` points to a valid [SPBitmap]
/// - `bitmap` is not written to or read from concurrently
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_pixel_grid_fill", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_pixel_grid_fill(PixelGrid* pixel_grid, [MarshalAs(UnmanagedType.U1)] bool value);
[DllImport(__DllName, EntryPoint = "sp_bitmap_fill", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void sp_bitmap_fill(Bitmap* bitmap, [MarshalAs(UnmanagedType.U1)] bool value);
/// <summary>
/// Gets the width in pixels of the [SPPixelGrid] instance.
/// Gets the width in pixels of the [SPBitmap] instance.
///
/// # Arguments
///
/// - `pixel_grid`: instance to read from
/// - `bitmap`: instance to read from
///
/// # Panics
///
/// - when `pixel_grid` is NULL
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - `bitmap` points to a valid [SPBitmap]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_pixel_grid_width", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint sp_pixel_grid_width(PixelGrid* pixel_grid);
[DllImport(__DllName, EntryPoint = "sp_bitmap_width", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint sp_bitmap_width(Bitmap* bitmap);
/// <summary>
/// Gets the height in pixels of the [SPPixelGrid] instance.
/// Gets the height in pixels of the [SPBitmap] instance.
///
/// # Arguments
///
/// - `pixel_grid`: instance to read from
/// - `bitmap`: instance to read from
///
/// # Panics
///
/// - when `pixel_grid` is NULL
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - `bitmap` points to a valid [SPBitmap]
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_pixel_grid_height", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint sp_pixel_grid_height(PixelGrid* pixel_grid);
[DllImport(__DllName, EntryPoint = "sp_bitmap_height", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern nuint sp_bitmap_height(Bitmap* bitmap);
/// <summary>
/// Gets an unsafe reference to the data of the [SPPixelGrid] instance.
/// Gets an unsafe reference to the data of the [SPBitmap] instance.
///
/// # Panics
///
/// - when `pixel_grid` is NULL
/// - when `bitmap` is NULL
///
/// # Safety
///
/// The caller has to make sure that:
///
/// - `pixel_grid` points to a valid [SPPixelGrid]
/// - the returned memory range is never accessed after the passed [SPPixelGrid] has been freed
/// - the returned memory range is never accessed concurrently, either via the [SPPixelGrid] or directly
/// - `bitmap` points to a valid [SPBitmap]
/// - the returned memory range is never accessed after the passed [SPBitmap] has been freed
/// - the returned memory range is never accessed concurrently, either via the [SPBitmap] or directly
/// </summary>
[DllImport(__DllName, EntryPoint = "sp_pixel_grid_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ByteSlice sp_pixel_grid_unsafe_data_ref(PixelGrid* pixel_grid);
[DllImport(__DllName, EntryPoint = "sp_bitmap_unsafe_data_ref", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ByteSlice sp_bitmap_unsafe_data_ref(Bitmap* bitmap);
}
@ -1411,11 +1411,6 @@ namespace ServicePoint.BindGen
public nuint length;
}
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Command
{
}
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Connection
{
@ -1432,7 +1427,12 @@ namespace ServicePoint.BindGen
}
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct PixelGrid
public unsafe partial struct Command
{
}
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Bitmap
{
}

View file

@ -2,33 +2,33 @@ using ServicePoint.BindGen;
namespace ServicePoint;
public sealed class PixelGrid : SpNativeInstance<BindGen.PixelGrid>
public sealed class Bitmap : SpNativeInstance<BindGen.Bitmap>
{
public static PixelGrid New(int width, int height)
public static Bitmap New(int width, int height)
{
unsafe
{
return new PixelGrid(NativeMethods.sp_pixel_grid_new((nuint)width, (nuint)height));
return new Bitmap(NativeMethods.sp_bitmap_new((nuint)width, (nuint)height));
}
}
public static PixelGrid Load(int width, int height, Span<byte> bytes)
public static Bitmap Load(int width, int height, Span<byte> bytes)
{
unsafe
{
fixed (byte* bytesPtr = bytes)
{
return new PixelGrid(NativeMethods.sp_pixel_grid_load((nuint)width, (nuint)height, bytesPtr,
return new Bitmap(NativeMethods.sp_bitmap_load((nuint)width, (nuint)height, bytesPtr,
(nuint)bytes.Length));
}
}
}
public PixelGrid Clone()
public Bitmap Clone()
{
unsafe
{
return new PixelGrid(NativeMethods.sp_pixel_grid_clone(Instance));
return new Bitmap(NativeMethods.sp_bitmap_clone(Instance));
}
}
@ -38,14 +38,14 @@ public sealed class PixelGrid : SpNativeInstance<BindGen.PixelGrid>
{
unsafe
{
return NativeMethods.sp_pixel_grid_get(Instance, (nuint)x, (nuint)y);
return NativeMethods.sp_bitmap_get(Instance, (nuint)x, (nuint)y);
}
}
set
{
unsafe
{
NativeMethods.sp_pixel_grid_set(Instance, (nuint)x, (nuint)y, value);
NativeMethods.sp_bitmap_set(Instance, (nuint)x, (nuint)y, value);
}
}
}
@ -54,7 +54,7 @@ public sealed class PixelGrid : SpNativeInstance<BindGen.PixelGrid>
{
unsafe
{
NativeMethods.sp_pixel_grid_fill(Instance, value);
NativeMethods.sp_bitmap_fill(Instance, value);
}
}
@ -64,7 +64,7 @@ public sealed class PixelGrid : SpNativeInstance<BindGen.PixelGrid>
{
unsafe
{
return (int)NativeMethods.sp_pixel_grid_width(Instance);
return (int)NativeMethods.sp_bitmap_width(Instance);
}
}
}
@ -75,7 +75,7 @@ public sealed class PixelGrid : SpNativeInstance<BindGen.PixelGrid>
{
unsafe
{
return (int)NativeMethods.sp_pixel_grid_height(Instance);
return (int)NativeMethods.sp_bitmap_height(Instance);
}
}
}
@ -86,15 +86,15 @@ public sealed class PixelGrid : SpNativeInstance<BindGen.PixelGrid>
{
unsafe
{
var slice = NativeMethods.sp_pixel_grid_unsafe_data_ref(Instance);
var slice = NativeMethods.sp_bitmap_unsafe_data_ref(Instance);
return new Span<byte>(slice.start, (int)slice.length);
}
}
}
private unsafe PixelGrid(BindGen.PixelGrid* instance) : base(instance)
private unsafe Bitmap(BindGen.Bitmap* instance) : base(instance)
{
}
private protected override unsafe void Free() => NativeMethods.sp_pixel_grid_free(Instance);
private protected override unsafe void Free() => NativeMethods.sp_bitmap_free(Instance);
}

View file

@ -105,11 +105,11 @@ public sealed class Command : SpNativeInstance<BindGen.Command>
}
}
public static Command BitmapLinearWin(int x, int y, PixelGrid pixelGrid, CompressionCode compression)
public static Command BitmapLinearWin(int x, int y, Bitmap bitmap, CompressionCode compression)
{
unsafe
{
return new Command(NativeMethods.sp_command_bitmap_linear_win((ushort)x, (ushort)y, pixelGrid.Into(), compression));
return new Command(NativeMethods.sp_command_bitmap_linear_win((ushort)x, (ushort)y, bitmap.Into(), compression));
}
}

View file

@ -6,7 +6,7 @@ using var connection = Connection.Open("127.0.0.1:2342");
connection.Send(Command.Clear().IntoPacket());
connection.Send(Command.Brightness(128).IntoPacket());
using var pixels = PixelGrid.New(Constants.PixelWidth, Constants.PixelHeight);
using var pixels = Bitmap.New(Constants.PixelWidth, Constants.PixelHeight);
for (var offset = 0; offset < int.MaxValue; offset++)
{