mirror of
https://github.com/cccb/servicepoint.git
synced 2025-01-18 18:10:14 +01:00
u16 only in implementation details to remove need to cast for user
This commit is contained in:
parent
8adf563320
commit
b21040c1f3
|
@ -9,7 +9,7 @@
|
||||||
/**
|
/**
|
||||||
* pixel count on whole screen
|
* pixel count on whole screen
|
||||||
*/
|
*/
|
||||||
#define sp2_PIXEL_COUNT ((size_t)sp2_PIXEL_WIDTH * (size_t)sp2_PIXEL_HEIGHT)
|
#define sp2_PIXEL_COUNT (sp2_PIXEL_WIDTH * sp2_PIXEL_HEIGHT)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* screen height in pixels
|
* screen height in pixels
|
||||||
|
@ -111,7 +111,7 @@ typedef struct sp2_CByteSlice {
|
||||||
/**
|
/**
|
||||||
* Type alias for documenting the meaning of the u16 in enum values
|
* Type alias for documenting the meaning of the u16 in enum values
|
||||||
*/
|
*/
|
||||||
typedef uint16_t sp2_Offset;
|
typedef size_t sp2_Offset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type alias for documenting the meaning of the u16 in enum values
|
* Type alias for documenting the meaning of the u16 in enum values
|
||||||
|
@ -282,8 +282,8 @@ struct sp2_Command *sp2_command_bitmap_linear_or(sp2_Offset offset,
|
||||||
* Allocates a new `Command::BitmapLinearWin` instance.
|
* Allocates a new `Command::BitmapLinearWin` instance.
|
||||||
* The passed `PixelGrid` gets deallocated in the process.
|
* The passed `PixelGrid` gets deallocated in the process.
|
||||||
*/
|
*/
|
||||||
struct sp2_Command *sp2_command_bitmap_linear_win(uint16_t x,
|
struct sp2_Command *sp2_command_bitmap_linear_win(size_t x,
|
||||||
uint16_t y,
|
size_t y,
|
||||||
struct sp2_PixelGrid *byte_grid,
|
struct sp2_PixelGrid *byte_grid,
|
||||||
sp2_CompressionCode compression_code);
|
sp2_CompressionCode compression_code);
|
||||||
|
|
||||||
|
@ -304,8 +304,8 @@ struct sp2_Command *sp2_command_brightness(sp2_Brightness brightness);
|
||||||
* Allocates a new `Command::CharBrightness` instance.
|
* Allocates a new `Command::CharBrightness` instance.
|
||||||
* The passed `ByteGrid` gets deallocated in the process.
|
* The passed `ByteGrid` gets deallocated in the process.
|
||||||
*/
|
*/
|
||||||
struct sp2_Command *sp2_command_char_brightness(uint16_t x,
|
struct sp2_Command *sp2_command_char_brightness(size_t x,
|
||||||
uint16_t y,
|
size_t y,
|
||||||
struct sp2_ByteGrid *byte_grid);
|
struct sp2_ByteGrid *byte_grid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -322,8 +322,8 @@ struct sp2_Command *sp2_command_clone(const struct sp2_Command *original);
|
||||||
* Allocates a new `Command::Cp437Data` instance.
|
* Allocates a new `Command::Cp437Data` instance.
|
||||||
* The passed `ByteGrid` gets deallocated in the process.
|
* The passed `ByteGrid` gets deallocated in the process.
|
||||||
*/
|
*/
|
||||||
struct sp2_Command *sp2_command_cp437_data(uint16_t x,
|
struct sp2_Command *sp2_command_cp437_data(size_t x,
|
||||||
uint16_t y,
|
size_t y,
|
||||||
struct sp2_ByteGrid *byte_grid);
|
struct sp2_ByteGrid *byte_grid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -125,31 +125,31 @@ namespace ServicePoint2.BindGen
|
||||||
|
|
||||||
/// <summary>Allocates a new `Command::CharBrightness` instance. The passed `ByteGrid` gets deallocated in the process.</summary>
|
/// <summary>Allocates a new `Command::CharBrightness` instance. The passed `ByteGrid` gets deallocated in the process.</summary>
|
||||||
[DllImport(__DllName, EntryPoint = "sp2_command_char_brightness", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "sp2_command_char_brightness", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern Command* sp2_command_char_brightness(ushort x, ushort y, ByteGrid* byte_grid);
|
public static extern Command* sp2_command_char_brightness(nuint x, nuint y, ByteGrid* byte_grid);
|
||||||
|
|
||||||
/// <summary>Allocates a new `Command::BitmapLinear` instance. The passed `BitVec` gets deallocated in the process.</summary>
|
/// <summary>Allocates a new `Command::BitmapLinear` instance. The passed `BitVec` gets deallocated in the process.</summary>
|
||||||
[DllImport(__DllName, EntryPoint = "sp2_command_bitmap_linear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "sp2_command_bitmap_linear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern Command* sp2_command_bitmap_linear(ushort offset, BitVec* bit_vec, CompressionCode compression);
|
public static extern Command* sp2_command_bitmap_linear(nuint offset, BitVec* bit_vec, CompressionCode compression);
|
||||||
|
|
||||||
/// <summary>Allocates a new `Command::BitmapLinearAnd` instance. The passed `BitVec` gets deallocated in the process.</summary>
|
/// <summary>Allocates a new `Command::BitmapLinearAnd` instance. The passed `BitVec` gets deallocated in the process.</summary>
|
||||||
[DllImport(__DllName, EntryPoint = "sp2_command_bitmap_linear_and", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "sp2_command_bitmap_linear_and", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern Command* sp2_command_bitmap_linear_and(ushort offset, BitVec* bit_vec, CompressionCode compression);
|
public static extern Command* sp2_command_bitmap_linear_and(nuint offset, BitVec* bit_vec, CompressionCode compression);
|
||||||
|
|
||||||
/// <summary>Allocates a new `Command::BitmapLinearOr` instance. The passed `BitVec` gets deallocated in the process.</summary>
|
/// <summary>Allocates a new `Command::BitmapLinearOr` instance. The passed `BitVec` gets deallocated in the process.</summary>
|
||||||
[DllImport(__DllName, EntryPoint = "sp2_command_bitmap_linear_or", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "sp2_command_bitmap_linear_or", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern Command* sp2_command_bitmap_linear_or(ushort offset, BitVec* bit_vec, CompressionCode compression);
|
public static extern Command* sp2_command_bitmap_linear_or(nuint offset, BitVec* bit_vec, CompressionCode compression);
|
||||||
|
|
||||||
/// <summary>Allocates a new `Command::BitmapLinearXor` instance. The passed `BitVec` gets deallocated in the process.</summary>
|
/// <summary>Allocates a new `Command::BitmapLinearXor` instance. The passed `BitVec` gets deallocated in the process.</summary>
|
||||||
[DllImport(__DllName, EntryPoint = "sp2_command_bitmap_linear_xor", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "sp2_command_bitmap_linear_xor", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern Command* sp2_command_bitmap_linear_xor(ushort offset, BitVec* bit_vec, CompressionCode compression);
|
public static extern Command* sp2_command_bitmap_linear_xor(nuint offset, BitVec* bit_vec, CompressionCode compression);
|
||||||
|
|
||||||
/// <summary>Allocates a new `Command::Cp437Data` instance. The passed `ByteGrid` gets deallocated in the process.</summary>
|
/// <summary>Allocates a new `Command::Cp437Data` instance. The passed `ByteGrid` gets deallocated in the process.</summary>
|
||||||
[DllImport(__DllName, EntryPoint = "sp2_command_cp437_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "sp2_command_cp437_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern Command* sp2_command_cp437_data(ushort x, ushort y, ByteGrid* byte_grid);
|
public static extern Command* sp2_command_cp437_data(nuint x, nuint y, ByteGrid* byte_grid);
|
||||||
|
|
||||||
/// <summary>Allocates a new `Command::BitmapLinearWin` instance. The passed `PixelGrid` gets deallocated in the process.</summary>
|
/// <summary>Allocates a new `Command::BitmapLinearWin` instance. The passed `PixelGrid` gets deallocated in the process.</summary>
|
||||||
[DllImport(__DllName, EntryPoint = "sp2_command_bitmap_linear_win", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "sp2_command_bitmap_linear_win", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern Command* sp2_command_bitmap_linear_win(ushort x, ushort y, PixelGrid* byte_grid, CompressionCode compression_code);
|
public static extern Command* sp2_command_bitmap_linear_win(nuint x, nuint y, PixelGrid* byte_grid, CompressionCode compression_code);
|
||||||
|
|
||||||
/// <summary>Deallocates a `Command`. Note that connection_send does this implicitly, so you only need to do this if you use the library for parsing commands.</summary>
|
/// <summary>Deallocates a `Command`. Note that connection_send does this implicitly, so you only need to do this if you use the library for parsing commands.</summary>
|
||||||
[DllImport(__DllName, EntryPoint = "sp2_command_dealloc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(__DllName, EntryPoint = "sp2_command_dealloc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::DataRef;
|
use crate::DataRef;
|
||||||
|
|
||||||
/// A vector of bits
|
/// A vector of bits
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct BitVec {
|
pub struct BitVec {
|
||||||
size: usize,
|
size: usize,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
|
@ -15,6 +15,11 @@ impl BitVec {
|
||||||
/// * `size`: size in bits. Must be dividable by 8.
|
/// * `size`: size in bits. Must be dividable by 8.
|
||||||
///
|
///
|
||||||
/// returns: bit vector with all bits set to false.
|
/// returns: bit vector with all bits set to false.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// When size is not a multiple of 8.
|
||||||
|
#[must_use]
|
||||||
pub fn new(size: usize) -> BitVec {
|
pub fn new(size: usize) -> BitVec {
|
||||||
assert_eq!(size % 8, 0);
|
assert_eq!(size % 8, 0);
|
||||||
Self {
|
Self {
|
||||||
|
@ -53,6 +58,7 @@ impl BitVec {
|
||||||
/// * `index`: the bit index to read
|
/// * `index`: the bit index to read
|
||||||
///
|
///
|
||||||
/// returns: value of the bit
|
/// returns: value of the bit
|
||||||
|
#[must_use]
|
||||||
pub fn get(&self, index: usize) -> bool {
|
pub fn get(&self, index: usize) -> bool {
|
||||||
let (byte_index, bit_mask) = self.get_indexes(index);
|
let (byte_index, bit_mask) = self.get_indexes(index);
|
||||||
self.data[byte_index] & bit_mask != 0
|
self.data[byte_index] & bit_mask != 0
|
||||||
|
@ -76,23 +82,24 @@ impl BitVec {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the length in bits
|
/// Gets the length in bits
|
||||||
|
#[must_use]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.size
|
self.size
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns true if length is 0.
|
/// returns true if length is 0.
|
||||||
|
#[must_use]
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.data.is_empty()
|
self.data.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the byte index and bitmask for a specific bit in the vector
|
/// Calculates the byte index and bitmask for a specific bit in the vector
|
||||||
fn get_indexes(&self, bit_index: usize) -> (usize, u8) {
|
fn get_indexes(&self, bit_index: usize) -> (usize, u8) {
|
||||||
if bit_index >= self.size {
|
assert!(
|
||||||
panic!(
|
bit_index < self.size,
|
||||||
"bit index {bit_index} is outside of range 0..<{}",
|
"bit index {bit_index} is outside of range 0..<{}",
|
||||||
self.size
|
self.size
|
||||||
)
|
);
|
||||||
}
|
|
||||||
|
|
||||||
let byte_index = bit_index / 8;
|
let byte_index = bit_index / 8;
|
||||||
let bit_in_byte_index = 7 - bit_index % 8;
|
let bit_in_byte_index = 7 - bit_index % 8;
|
||||||
|
@ -128,16 +135,6 @@ impl From<&[u8]> for BitVec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for BitVec {
|
|
||||||
/// Formats a `BitVec` for debug. The manual implementation includes the length of the instance.
|
|
||||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
fmt.debug_struct("BitVec")
|
|
||||||
.field("len", &self.len())
|
|
||||||
.field("data", &self.data)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "c_api")]
|
#[cfg(feature = "c_api")]
|
||||||
pub mod c_api {
|
pub mod c_api {
|
||||||
use crate::{BitVec, CByteSlice, DataRef};
|
use crate::{BitVec, CByteSlice, DataRef};
|
||||||
|
|
|
@ -9,13 +9,14 @@ pub struct ByteGrid {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ByteGrid {
|
impl ByteGrid {
|
||||||
/// Loads a byte grid with the specified dimensions from the provided data.
|
/// Loads a `ByteGrid` with the specified dimensions from the provided data.
|
||||||
///
|
///
|
||||||
/// returns: ByteGrid that contains a copy of the provided data
|
/// returns: `ByteGrid` that contains a copy of the provided data
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// - when the dimensions and data size do not match exactly.
|
/// - when the dimensions and data size do not match exactly.
|
||||||
|
#[must_use]
|
||||||
pub fn load(width: usize, height: usize, data: &[u8]) -> Self {
|
pub fn load(width: usize, height: usize, data: &[u8]) -> Self {
|
||||||
assert_eq!(width * height, data.len());
|
assert_eq!(width * height, data.len());
|
||||||
Self {
|
Self {
|
||||||
|
@ -26,19 +27,23 @@ impl ByteGrid {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_indexes(&self, x: usize, y: usize) {
|
fn check_indexes(&self, x: usize, y: usize) {
|
||||||
if x >= self.width {
|
assert!(
|
||||||
panic!("cannot access byte {x}-{y} because x is outside of bounds 0..{}", self.width)
|
x < self.width,
|
||||||
}
|
"cannot access byte {x}-{y} because x is outside of bounds 0..{}",
|
||||||
if y >= self.height {
|
self.width
|
||||||
panic!("cannot access byte {x}-{y} because y is outside of bounds 0..{}", self.height)
|
);
|
||||||
}
|
assert!(
|
||||||
|
y < self.height,
|
||||||
|
"cannot access byte {x}-{y} because y is outside of bounds 0..{}",
|
||||||
|
self.height
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Grid<u8> for ByteGrid {
|
impl Grid<u8> for ByteGrid {
|
||||||
/// Creates a new byte grid with the specified dimensions.
|
/// Creates a new `ByteGrid` with the specified dimensions.
|
||||||
///
|
///
|
||||||
/// returns: ByteGrid initialized to 0.
|
/// returns: `ByteGrid` initialized to 0.
|
||||||
fn new(width: usize, height: usize) -> Self {
|
fn new(width: usize, height: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
data: vec![0; width * height],
|
data: vec![0; width * height],
|
||||||
|
@ -61,7 +66,7 @@ impl Grid<u8> for ByteGrid {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill(&mut self, value: u8) {
|
fn fill(&mut self, value: u8) {
|
||||||
self.data.fill(value)
|
self.data.fill(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn width(&self) -> usize {
|
fn width(&self) -> usize {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
|
|
||||||
/// An origin marks the top left position of a window sent to the display.
|
/// An origin marks the top left position of a window sent to the display.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct Origin(pub u16, pub u16);
|
pub struct Origin(pub usize, pub usize);
|
||||||
|
|
||||||
impl std::ops::Add<Origin> for Origin {
|
impl std::ops::Add<Origin> for Origin {
|
||||||
type Output = Origin;
|
type Output = Origin;
|
||||||
|
@ -19,12 +19,8 @@ impl std::ops::Add<Origin> for Origin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Size defines the width and height of a window
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct Size(pub u16, pub u16);
|
|
||||||
|
|
||||||
/// Type alias for documenting the meaning of the u16 in enum values
|
/// Type alias for documenting the meaning of the u16 in enum values
|
||||||
pub type Offset = u16;
|
pub type Offset = usize;
|
||||||
|
|
||||||
/// Type alias for documenting the meaning of the u16 in enum values
|
/// Type alias for documenting the meaning of the u16 in enum values
|
||||||
pub type Brightness = u8;
|
pub type Brightness = u8;
|
||||||
|
@ -46,16 +42,16 @@ pub enum Command {
|
||||||
/// Legacy command code, gets ignored by the real display.
|
/// Legacy command code, gets ignored by the real display.
|
||||||
BitmapLegacy,
|
BitmapLegacy,
|
||||||
/// Set pixel data starting at the offset.
|
/// Set pixel data starting at the offset.
|
||||||
/// The contained BitVec is always uncompressed.
|
/// The contained `BitVec` is always uncompressed.
|
||||||
BitmapLinear(Offset, BitVec, CompressionCode),
|
BitmapLinear(Offset, BitVec, CompressionCode),
|
||||||
/// Set pixel data according to an and-mask starting at the offset.
|
/// Set pixel data according to an and-mask starting at the offset.
|
||||||
/// The contained BitVec is always uncompressed.
|
/// The contained `BitVec` is always uncompressed.
|
||||||
BitmapLinearAnd(Offset, BitVec, CompressionCode),
|
BitmapLinearAnd(Offset, BitVec, CompressionCode),
|
||||||
/// Set pixel data according to an or-mask starting at the offset.
|
/// Set pixel data according to an or-mask starting at the offset.
|
||||||
/// The contained BitVec is always uncompressed.
|
/// The contained `BitVec` is always uncompressed.
|
||||||
BitmapLinearOr(Offset, BitVec, CompressionCode),
|
BitmapLinearOr(Offset, BitVec, CompressionCode),
|
||||||
/// Set pixel data according to an xor-mask starting at the offset.
|
/// Set pixel data according to a xor-mask starting at the offset.
|
||||||
/// The contained BitVec is always uncompressed.
|
/// The contained `BitVec` is always uncompressed.
|
||||||
BitmapLinearXor(Offset, BitVec, CompressionCode),
|
BitmapLinearXor(Offset, BitVec, CompressionCode),
|
||||||
/// Show text on the screen. Note that the byte data has to be CP437 encoded.
|
/// Show text on the screen. Note that the byte data has to be CP437 encoded.
|
||||||
Cp437Data(Origin, ByteGrid),
|
Cp437Data(Origin, ByteGrid),
|
||||||
|
@ -65,6 +61,7 @@ pub enum Command {
|
||||||
|
|
||||||
impl From<Command> for Packet {
|
impl From<Command> for Packet {
|
||||||
/// Move the `Command` into a `Packet` instance for sending.
|
/// Move the `Command` into a `Packet` instance for sending.
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
fn from(value: Command) -> Self {
|
fn from(value: Command) -> Self {
|
||||||
match value {
|
match value {
|
||||||
Command::Clear => Command::command_code_only(CommandCode::Clear),
|
Command::Clear => Command::command_code_only(CommandCode::Clear),
|
||||||
|
@ -81,8 +78,8 @@ impl From<Command> for Packet {
|
||||||
Command::CharBrightness(Origin(x, y), grid) => Packet(
|
Command::CharBrightness(Origin(x, y), grid) => Packet(
|
||||||
Header(
|
Header(
|
||||||
CommandCode::CharBrightness.into(),
|
CommandCode::CharBrightness.into(),
|
||||||
x,
|
x as u16,
|
||||||
y,
|
y as u16,
|
||||||
grid.width() as u16,
|
grid.width() as u16,
|
||||||
grid.height() as u16,
|
grid.height() as u16,
|
||||||
),
|
),
|
||||||
|
@ -98,36 +95,8 @@ impl From<Command> for Packet {
|
||||||
),
|
),
|
||||||
vec![brightness],
|
vec![brightness],
|
||||||
),
|
),
|
||||||
Command::BitmapLinearWin(
|
Command::BitmapLinearWin(origin, pixels, compression) => {
|
||||||
Origin(pixel_x, pixel_y),
|
bitmap_win_into_packet(origin, pixels, compression)
|
||||||
pixels,
|
|
||||||
compression,
|
|
||||||
) => {
|
|
||||||
debug_assert_eq!(pixel_x % 8, 0);
|
|
||||||
debug_assert_eq!(pixels.width() % 8, 0);
|
|
||||||
|
|
||||||
let tile_x = pixel_x / TILE_SIZE;
|
|
||||||
let tile_w = pixels.width() as u16 / TILE_SIZE;
|
|
||||||
let pixel_h = pixels.height() as u16;
|
|
||||||
let payload = into_compressed(compression, pixels.into());
|
|
||||||
let command = match compression {
|
|
||||||
CompressionCode::Uncompressed => {
|
|
||||||
CommandCode::BitmapLinearWinUncompressed
|
|
||||||
}
|
|
||||||
#[cfg(feature = "compression_zlib")]
|
|
||||||
CompressionCode::Zlib => CommandCode::BitmapLinearWinZlib,
|
|
||||||
#[cfg(feature = "compression_bzip2")]
|
|
||||||
CompressionCode::Bzip2 => CommandCode::BitmapLinearWinBzip2,
|
|
||||||
#[cfg(feature = "compression_lzma")]
|
|
||||||
CompressionCode::Lzma => CommandCode::BitmapLinearWinLzma,
|
|
||||||
#[cfg(feature = "compression_zstd")]
|
|
||||||
CompressionCode::Zstd => CommandCode::BitmapLinearWinZstd,
|
|
||||||
};
|
|
||||||
|
|
||||||
Packet(
|
|
||||||
Header(command.into(), tile_x, pixel_y, tile_w, pixel_h),
|
|
||||||
payload,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Command::BitmapLinear(offset, bits, compression) => {
|
Command::BitmapLinear(offset, bits, compression) => {
|
||||||
Command::bitmap_linear_into_packet(
|
Command::bitmap_linear_into_packet(
|
||||||
|
@ -164,8 +133,8 @@ impl From<Command> for Packet {
|
||||||
Command::Cp437Data(Origin(x, y), grid) => Packet(
|
Command::Cp437Data(Origin(x, y), grid) => Packet(
|
||||||
Header(
|
Header(
|
||||||
CommandCode::Cp437Data.into(),
|
CommandCode::Cp437Data.into(),
|
||||||
x,
|
x as u16,
|
||||||
y,
|
y as u16,
|
||||||
grid.width() as u16,
|
grid.width() as u16,
|
||||||
grid.height() as u16,
|
grid.height() as u16,
|
||||||
),
|
),
|
||||||
|
@ -175,6 +144,40 @@ impl From<Command> for Packet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
fn bitmap_win_into_packet(
|
||||||
|
origin: Origin,
|
||||||
|
pixels: PixelGrid,
|
||||||
|
compression: CompressionCode,
|
||||||
|
) -> Packet {
|
||||||
|
let Origin(pixel_x, pixel_y) = origin;
|
||||||
|
debug_assert_eq!(pixel_x % 8, 0);
|
||||||
|
debug_assert_eq!(pixels.width() % 8, 0);
|
||||||
|
|
||||||
|
let tile_x = (pixel_x / TILE_SIZE) as u16;
|
||||||
|
let tile_w = (pixels.width() / TILE_SIZE) as u16;
|
||||||
|
let pixel_h = pixels.height() as u16;
|
||||||
|
let payload = into_compressed(compression, pixels.into());
|
||||||
|
let command = match compression {
|
||||||
|
CompressionCode::Uncompressed => {
|
||||||
|
CommandCode::BitmapLinearWinUncompressed
|
||||||
|
}
|
||||||
|
#[cfg(feature = "compression_zlib")]
|
||||||
|
CompressionCode::Zlib => CommandCode::BitmapLinearWinZlib,
|
||||||
|
#[cfg(feature = "compression_bzip2")]
|
||||||
|
CompressionCode::Bzip2 => CommandCode::BitmapLinearWinBzip2,
|
||||||
|
#[cfg(feature = "compression_lzma")]
|
||||||
|
CompressionCode::Lzma => CommandCode::BitmapLinearWinLzma,
|
||||||
|
#[cfg(feature = "compression_zstd")]
|
||||||
|
CompressionCode::Zstd => CommandCode::BitmapLinearWinZstd,
|
||||||
|
};
|
||||||
|
|
||||||
|
Packet(
|
||||||
|
Header(command.into(), tile_x, pixel_y as u16, tile_w, pixel_h),
|
||||||
|
payload,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// Err values for `Command::try_from`.
|
/// Err values for `Command::try_from`.
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
@ -200,7 +203,7 @@ impl TryFrom<Packet> for Command {
|
||||||
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
||||||
let Packet(Header(command_u16, a, b, c, d), _) = packet;
|
let Packet(Header(command_u16, a, b, c, d), _) = packet;
|
||||||
let command_code = match CommandCode::try_from(command_u16) {
|
let command_code = match CommandCode::try_from(command_u16) {
|
||||||
Err(_) => {
|
Err(()) => {
|
||||||
return Err(TryFromPacketError::InvalidCommand(command_u16));
|
return Err(TryFromPacketError::InvalidCommand(command_u16));
|
||||||
}
|
}
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
|
@ -238,14 +241,14 @@ impl TryFrom<Packet> for Command {
|
||||||
CommandCode::Cp437Data => {
|
CommandCode::Cp437Data => {
|
||||||
let Packet(_, payload) = packet;
|
let Packet(_, payload) = packet;
|
||||||
Ok(Command::Cp437Data(
|
Ok(Command::Cp437Data(
|
||||||
Origin(a, b),
|
Origin(a as usize, b as usize),
|
||||||
ByteGrid::load(c as usize, d as usize, &payload),
|
ByteGrid::load(c as usize, d as usize, &payload),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
CommandCode::CharBrightness => {
|
CommandCode::CharBrightness => {
|
||||||
let Packet(_, payload) = packet;
|
let Packet(_, payload) = packet;
|
||||||
Ok(Command::CharBrightness(
|
Ok(Command::CharBrightness(
|
||||||
Origin(a, b),
|
Origin(a as usize, b as usize),
|
||||||
ByteGrid::load(c as usize, d as usize, &payload),
|
ByteGrid::load(c as usize, d as usize, &payload),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -254,22 +257,22 @@ impl TryFrom<Packet> for Command {
|
||||||
CommandCode::BitmapLinear => {
|
CommandCode::BitmapLinear => {
|
||||||
let (vec, compression) =
|
let (vec, compression) =
|
||||||
Self::packet_into_linear_bitmap(packet)?;
|
Self::packet_into_linear_bitmap(packet)?;
|
||||||
Ok(Command::BitmapLinear(a, vec, compression))
|
Ok(Command::BitmapLinear(a as Offset, vec, compression))
|
||||||
}
|
}
|
||||||
CommandCode::BitmapLinearAnd => {
|
CommandCode::BitmapLinearAnd => {
|
||||||
let (vec, compression) =
|
let (vec, compression) =
|
||||||
Self::packet_into_linear_bitmap(packet)?;
|
Self::packet_into_linear_bitmap(packet)?;
|
||||||
Ok(Command::BitmapLinearAnd(a, vec, compression))
|
Ok(Command::BitmapLinearAnd(a as Offset, vec, compression))
|
||||||
}
|
}
|
||||||
CommandCode::BitmapLinearOr => {
|
CommandCode::BitmapLinearOr => {
|
||||||
let (vec, compression) =
|
let (vec, compression) =
|
||||||
Self::packet_into_linear_bitmap(packet)?;
|
Self::packet_into_linear_bitmap(packet)?;
|
||||||
Ok(Command::BitmapLinearOr(a, vec, compression))
|
Ok(Command::BitmapLinearOr(a as Offset, vec, compression))
|
||||||
}
|
}
|
||||||
CommandCode::BitmapLinearXor => {
|
CommandCode::BitmapLinearXor => {
|
||||||
let (vec, compression) =
|
let (vec, compression) =
|
||||||
Self::packet_into_linear_bitmap(packet)?;
|
Self::packet_into_linear_bitmap(packet)?;
|
||||||
Ok(Command::BitmapLinearXor(a, vec, compression))
|
Ok(Command::BitmapLinearXor(a as Offset, vec, compression))
|
||||||
}
|
}
|
||||||
CommandCode::BitmapLinearWinUncompressed => {
|
CommandCode::BitmapLinearWinUncompressed => {
|
||||||
Self::packet_into_bitmap_win(
|
Self::packet_into_bitmap_win(
|
||||||
|
@ -311,9 +314,9 @@ impl Command {
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Command::BitmapLinearWin(
|
Ok(Command::BitmapLinearWin(
|
||||||
Origin(tiles_x * TILE_SIZE, pixels_y),
|
Origin(tiles_x as usize * TILE_SIZE, pixels_y as usize),
|
||||||
PixelGrid::load(
|
PixelGrid::load(
|
||||||
tile_w as usize * TILE_SIZE as usize,
|
tile_w as usize * TILE_SIZE,
|
||||||
pixel_h as usize,
|
pixel_h as usize,
|
||||||
&payload,
|
&payload,
|
||||||
),
|
),
|
||||||
|
@ -321,7 +324,8 @@ impl Command {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper method for BitMapLinear*-Commands into Packet
|
/// Helper method for `BitMapLinear*`-Commands into `Packet`
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
fn bitmap_linear_into_packet(
|
fn bitmap_linear_into_packet(
|
||||||
command: CommandCode,
|
command: CommandCode,
|
||||||
offset: Offset,
|
offset: Offset,
|
||||||
|
@ -331,7 +335,13 @@ impl Command {
|
||||||
let length = payload.len() as u16;
|
let length = payload.len() as u16;
|
||||||
let payload = into_compressed(compression, payload);
|
let payload = into_compressed(compression, payload);
|
||||||
Packet(
|
Packet(
|
||||||
Header(command.into(), offset, length, compression.into(), 0),
|
Header(
|
||||||
|
command.into(),
|
||||||
|
offset as u16,
|
||||||
|
length,
|
||||||
|
compression.into(),
|
||||||
|
0,
|
||||||
|
),
|
||||||
payload,
|
payload,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -353,7 +363,7 @@ impl Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper method for Packets into BitMapLinear*-Commands
|
/// Helper method for Packets into `BitMapLinear*`-Commands
|
||||||
fn packet_into_linear_bitmap(
|
fn packet_into_linear_bitmap(
|
||||||
packet: Packet,
|
packet: Packet,
|
||||||
) -> Result<(BitVec, CompressionCode), TryFromPacketError> {
|
) -> Result<(BitVec, CompressionCode), TryFromPacketError> {
|
||||||
|
@ -362,7 +372,7 @@ impl Command {
|
||||||
return Err(TryFromPacketError::ExtraneousHeaderValues);
|
return Err(TryFromPacketError::ExtraneousHeaderValues);
|
||||||
}
|
}
|
||||||
let sub = match CompressionCode::try_from(sub) {
|
let sub = match CompressionCode::try_from(sub) {
|
||||||
Err(_) => {
|
Err(()) => {
|
||||||
return Err(TryFromPacketError::InvalidCompressionCode(sub));
|
return Err(TryFromPacketError::InvalidCompressionCode(sub));
|
||||||
}
|
}
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
|
@ -442,8 +452,8 @@ pub mod c_api {
|
||||||
/// The passed `ByteGrid` gets deallocated in the process.
|
/// The passed `ByteGrid` gets deallocated in the process.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sp2_command_char_brightness(
|
pub unsafe extern "C" fn sp2_command_char_brightness(
|
||||||
x: u16,
|
x: usize,
|
||||||
y: u16,
|
y: usize,
|
||||||
byte_grid: *mut ByteGrid,
|
byte_grid: *mut ByteGrid,
|
||||||
) -> *mut Command {
|
) -> *mut Command {
|
||||||
let byte_grid = *Box::from_raw(byte_grid);
|
let byte_grid = *Box::from_raw(byte_grid);
|
||||||
|
@ -521,8 +531,8 @@ pub mod c_api {
|
||||||
/// The passed `ByteGrid` gets deallocated in the process.
|
/// The passed `ByteGrid` gets deallocated in the process.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sp2_command_cp437_data(
|
pub unsafe extern "C" fn sp2_command_cp437_data(
|
||||||
x: u16,
|
x: usize,
|
||||||
y: u16,
|
y: usize,
|
||||||
byte_grid: *mut ByteGrid,
|
byte_grid: *mut ByteGrid,
|
||||||
) -> *mut Command {
|
) -> *mut Command {
|
||||||
let byte_grid = *Box::from_raw(byte_grid);
|
let byte_grid = *Box::from_raw(byte_grid);
|
||||||
|
@ -533,8 +543,8 @@ pub mod c_api {
|
||||||
/// The passed `PixelGrid` gets deallocated in the process.
|
/// The passed `PixelGrid` gets deallocated in the process.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sp2_command_bitmap_linear_win(
|
pub unsafe extern "C" fn sp2_command_bitmap_linear_win(
|
||||||
x: u16,
|
x: usize,
|
||||||
y: u16,
|
y: usize,
|
||||||
byte_grid: *mut PixelGrid,
|
byte_grid: *mut PixelGrid,
|
||||||
compression_code: CompressionCode,
|
compression_code: CompressionCode,
|
||||||
) -> *mut Command {
|
) -> *mut Command {
|
||||||
|
|
|
@ -37,39 +37,61 @@ impl TryFrom<u16> for CommandCode {
|
||||||
|
|
||||||
/// Returns the enum value for the specified `u16` or `Error` if the code is unknown.
|
/// Returns the enum value for the specified `u16` or `Error` if the code is unknown.
|
||||||
fn try_from(value: u16) -> Result<Self, Self::Error> {
|
fn try_from(value: u16) -> Result<Self, Self::Error> {
|
||||||
use CommandCode::*;
|
|
||||||
|
|
||||||
match value {
|
match value {
|
||||||
value if value == Clear as u16 => Ok(Clear),
|
value if value == CommandCode::Clear as u16 => {
|
||||||
value if value == Cp437Data as u16 => Ok(Cp437Data),
|
Ok(CommandCode::Clear)
|
||||||
value if value == CharBrightness as u16 => Ok(CharBrightness),
|
}
|
||||||
value if value == Brightness as u16 => Ok(Brightness),
|
value if value == CommandCode::Cp437Data as u16 => {
|
||||||
value if value == HardReset as u16 => Ok(HardReset),
|
Ok(CommandCode::Cp437Data)
|
||||||
value if value == FadeOut as u16 => Ok(FadeOut),
|
}
|
||||||
#[allow(deprecated)]
|
value if value == CommandCode::CharBrightness as u16 => {
|
||||||
value if value == BitmapLegacy as u16 => Ok(BitmapLegacy),
|
Ok(CommandCode::CharBrightness)
|
||||||
value if value == BitmapLinear as u16 => Ok(BitmapLinear),
|
}
|
||||||
value if value == BitmapLinearWinUncompressed as u16 => {
|
value if value == CommandCode::Brightness as u16 => {
|
||||||
Ok(BitmapLinearWinUncompressed)
|
Ok(CommandCode::Brightness)
|
||||||
|
}
|
||||||
|
value if value == CommandCode::HardReset as u16 => {
|
||||||
|
Ok(CommandCode::HardReset)
|
||||||
|
}
|
||||||
|
value if value == CommandCode::FadeOut as u16 => {
|
||||||
|
Ok(CommandCode::FadeOut)
|
||||||
|
}
|
||||||
|
#[allow(deprecated)]
|
||||||
|
value if value == CommandCode::BitmapLegacy as u16 => {
|
||||||
|
Ok(CommandCode::BitmapLegacy)
|
||||||
|
}
|
||||||
|
value if value == CommandCode::BitmapLinear as u16 => {
|
||||||
|
Ok(CommandCode::BitmapLinear)
|
||||||
|
}
|
||||||
|
value
|
||||||
|
if value == CommandCode::BitmapLinearWinUncompressed as u16 =>
|
||||||
|
{
|
||||||
|
Ok(CommandCode::BitmapLinearWinUncompressed)
|
||||||
|
}
|
||||||
|
value if value == CommandCode::BitmapLinearAnd as u16 => {
|
||||||
|
Ok(CommandCode::BitmapLinearAnd)
|
||||||
|
}
|
||||||
|
value if value == CommandCode::BitmapLinearOr as u16 => {
|
||||||
|
Ok(CommandCode::BitmapLinearOr)
|
||||||
|
}
|
||||||
|
value if value == CommandCode::BitmapLinearXor as u16 => {
|
||||||
|
Ok(CommandCode::BitmapLinearXor)
|
||||||
}
|
}
|
||||||
value if value == BitmapLinearAnd as u16 => Ok(BitmapLinearAnd),
|
|
||||||
value if value == BitmapLinearOr as u16 => Ok(BitmapLinearOr),
|
|
||||||
value if value == BitmapLinearXor as u16 => Ok(BitmapLinearXor),
|
|
||||||
#[cfg(feature = "compression_zstd")]
|
#[cfg(feature = "compression_zstd")]
|
||||||
value if value == BitmapLinearWinZstd as u16 => {
|
value if value == CommandCode::BitmapLinearWinZstd as u16 => {
|
||||||
Ok(BitmapLinearWinZstd)
|
Ok(CommandCode::BitmapLinearWinZstd)
|
||||||
}
|
}
|
||||||
#[cfg(feature = "compression_lzma")]
|
#[cfg(feature = "compression_lzma")]
|
||||||
value if value == BitmapLinearWinLzma as u16 => {
|
value if value == CommandCode::BitmapLinearWinLzma as u16 => {
|
||||||
Ok(BitmapLinearWinLzma)
|
Ok(CommandCode::BitmapLinearWinLzma)
|
||||||
}
|
}
|
||||||
#[cfg(feature = "compression_zlib")]
|
#[cfg(feature = "compression_zlib")]
|
||||||
value if value == BitmapLinearWinZlib as u16 => {
|
value if value == CommandCode::BitmapLinearWinZlib as u16 => {
|
||||||
Ok(BitmapLinearWinZlib)
|
Ok(CommandCode::BitmapLinearWinZlib)
|
||||||
}
|
}
|
||||||
#[cfg(feature = "compression_bzip2")]
|
#[cfg(feature = "compression_bzip2")]
|
||||||
value if value == BitmapLinearWinBzip2 as u16 => {
|
value if value == CommandCode::BitmapLinearWinBzip2 as u16 => {
|
||||||
Ok(BitmapLinearWinBzip2)
|
Ok(CommandCode::BitmapLinearWinBzip2)
|
||||||
}
|
}
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use CompressionCode::*;
|
|
||||||
|
|
||||||
/// Specifies the kind of compression to use. Availability depends on features.
|
/// Specifies the kind of compression to use. Availability depends on features.
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
@ -26,15 +24,25 @@ impl TryFrom<u16> for CompressionCode {
|
||||||
|
|
||||||
fn try_from(value: u16) -> Result<Self, Self::Error> {
|
fn try_from(value: u16) -> Result<Self, Self::Error> {
|
||||||
match value {
|
match value {
|
||||||
value if value == Uncompressed as u16 => Ok(Uncompressed),
|
value if value == CompressionCode::Uncompressed as u16 => {
|
||||||
|
Ok(CompressionCode::Uncompressed)
|
||||||
|
}
|
||||||
#[cfg(feature = "compression_zlib")]
|
#[cfg(feature = "compression_zlib")]
|
||||||
value if value == Zlib as u16 => Ok(Zlib),
|
value if value == CompressionCode::Zlib as u16 => {
|
||||||
|
Ok(CompressionCode::Zlib)
|
||||||
|
}
|
||||||
#[cfg(feature = "compression_bzip2")]
|
#[cfg(feature = "compression_bzip2")]
|
||||||
value if value == Bzip2 as u16 => Ok(Bzip2),
|
value if value == CompressionCode::Bzip2 as u16 => {
|
||||||
|
Ok(CompressionCode::Bzip2)
|
||||||
|
}
|
||||||
#[cfg(feature = "compression_lzma")]
|
#[cfg(feature = "compression_lzma")]
|
||||||
value if value == Lzma as u16 => Ok(Lzma),
|
value if value == CompressionCode::Lzma as u16 => {
|
||||||
|
Ok(CompressionCode::Lzma)
|
||||||
|
}
|
||||||
#[cfg(feature = "compression_zstd")]
|
#[cfg(feature = "compression_zstd")]
|
||||||
value if value == Zstd as u16 => Ok(Zstd),
|
value if value == CompressionCode::Zstd as u16 => {
|
||||||
|
Ok(CompressionCode::Zstd)
|
||||||
|
}
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,10 @@ impl Connection {
|
||||||
///
|
///
|
||||||
/// Note that this is UDP, which means that the open call can succeed even if the display is unreachable.
|
/// Note that this is UDP, which means that the open call can succeed even if the display is unreachable.
|
||||||
///
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Any errors resulting from binding the udp socket.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let connection = servicepoint2::Connection::open("172.23.42.29:2342")
|
/// let connection = servicepoint2::Connection::open("172.23.42.29:2342")
|
||||||
|
@ -35,6 +39,10 @@ impl Connection {
|
||||||
///
|
///
|
||||||
/// returns: Ok if packet was sent, otherwise socket error
|
/// returns: Ok if packet was sent, otherwise socket error
|
||||||
///
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Any errors produced while sending using the underlying socket.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pub trait Grid<T> {
|
pub trait Grid<T> {
|
||||||
|
#[must_use]
|
||||||
fn new(width: usize, height: usize) -> Self;
|
fn new(width: usize, height: usize) -> Self;
|
||||||
|
|
||||||
/// Sets the value at the specified position
|
/// Sets the value at the specified position
|
||||||
|
@ -47,5 +48,6 @@ pub trait Grid<T> {
|
||||||
///
|
///
|
||||||
/// let (l, r) = split(ByteGrid::new(9, 5));
|
/// let (l, r) = split(ByteGrid::new(9, 5));
|
||||||
/// ```
|
/// ```
|
||||||
|
#[must_use]
|
||||||
fn window(&self, x: usize, y: usize, w: usize, h: usize) -> Self;
|
fn window(&self, x: usize, y: usize, w: usize, h: usize) -> Self;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
pub use crate::bit_vec::BitVec;
|
pub use crate::bit_vec::BitVec;
|
||||||
pub use crate::byte_grid::ByteGrid;
|
pub use crate::byte_grid::ByteGrid;
|
||||||
pub use crate::command::{Brightness, Command, Offset, Origin, Size};
|
#[cfg(feature = "c_api")]
|
||||||
|
pub use crate::c_slice::CByteSlice;
|
||||||
|
pub use crate::command::{Brightness, Command, Offset, Origin};
|
||||||
pub use crate::compression_code::CompressionCode;
|
pub use crate::compression_code::CompressionCode;
|
||||||
pub use crate::connection::Connection;
|
pub use crate::connection::Connection;
|
||||||
pub use crate::data_ref::DataRef;
|
pub use crate::data_ref::DataRef;
|
||||||
pub use crate::grid::Grid;
|
pub use crate::grid::Grid;
|
||||||
pub use crate::packet::{Header, Packet, Payload};
|
pub use crate::packet::{Header, Packet, Payload};
|
||||||
pub use crate::pixel_grid::PixelGrid;
|
pub use crate::pixel_grid::PixelGrid;
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
#[cfg(feature = "c_api")]
|
|
||||||
pub use crate::c_slice::CByteSlice;
|
|
||||||
|
|
||||||
mod bit_vec;
|
mod bit_vec;
|
||||||
mod byte_grid;
|
mod byte_grid;
|
||||||
|
@ -26,22 +26,22 @@ mod packet;
|
||||||
mod pixel_grid;
|
mod pixel_grid;
|
||||||
|
|
||||||
/// size of a single tile in one dimension
|
/// size of a single tile in one dimension
|
||||||
pub const TILE_SIZE: u16 = 8;
|
pub const TILE_SIZE: usize = 8;
|
||||||
|
|
||||||
/// tile count in the x-direction
|
/// tile count in the x-direction
|
||||||
pub const TILE_WIDTH: u16 = 56;
|
pub const TILE_WIDTH: usize = 56;
|
||||||
|
|
||||||
/// tile count in the y-direction
|
/// tile count in the y-direction
|
||||||
pub const TILE_HEIGHT: u16 = 20;
|
pub const TILE_HEIGHT: usize = 20;
|
||||||
|
|
||||||
/// screen width in pixels
|
/// screen width in pixels
|
||||||
pub const PIXEL_WIDTH: u16 = TILE_WIDTH * TILE_SIZE;
|
pub const PIXEL_WIDTH: usize = TILE_WIDTH * TILE_SIZE;
|
||||||
|
|
||||||
/// screen height in pixels
|
/// screen height in pixels
|
||||||
pub const PIXEL_HEIGHT: u16 = TILE_HEIGHT * TILE_SIZE;
|
pub const PIXEL_HEIGHT: usize = TILE_HEIGHT * TILE_SIZE;
|
||||||
|
|
||||||
/// pixel count on whole screen
|
/// pixel count on whole screen
|
||||||
pub const PIXEL_COUNT: usize = PIXEL_WIDTH as usize * PIXEL_HEIGHT as usize;
|
pub const PIXEL_COUNT: usize = PIXEL_WIDTH * PIXEL_HEIGHT;
|
||||||
|
|
||||||
/// Actual hardware limit is around 28-29ms/frame. Rounded up for less dropped packets.
|
/// Actual hardware limit is around 28-29ms/frame. Rounded up for less dropped packets.
|
||||||
pub const FRAME_PACING: Duration = Duration::from_millis(30);
|
pub const FRAME_PACING: Duration = Duration::from_millis(30);
|
||||||
|
|
|
@ -10,23 +10,25 @@ pub struct PixelGrid {
|
||||||
|
|
||||||
impl PixelGrid {
|
impl PixelGrid {
|
||||||
/// Creates a new pixel grid with the size of the whole screen.
|
/// Creates a new pixel grid with the size of the whole screen.
|
||||||
|
#[must_use]
|
||||||
pub fn max_sized() -> Self {
|
pub fn max_sized() -> Self {
|
||||||
Self::new(PIXEL_WIDTH as usize, PIXEL_HEIGHT as usize)
|
Self::new(PIXEL_WIDTH, PIXEL_HEIGHT)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads a pixel grid with the specified dimensions from the provided data.
|
/// Loads a `PixelGrid` with the specified dimensions from the provided data.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `width`: size in pixels in x-direction
|
/// * `width`: size in pixels in x-direction
|
||||||
/// * `height`: size in pixels in y-direction
|
/// * `height`: size in pixels in y-direction
|
||||||
///
|
///
|
||||||
/// returns: PixelGrid that contains a copy of the provided data
|
/// returns: `PixelGrid` that contains a copy of the provided data
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// - when the dimensions and data size do not match exactly.
|
/// - when the dimensions and data size do not match exactly.
|
||||||
/// - when the width is not dividable by 8
|
/// - when the width is not dividable by 8
|
||||||
|
#[must_use]
|
||||||
pub fn load(width: usize, height: usize, data: &[u8]) -> Self {
|
pub fn load(width: usize, height: usize, data: &[u8]) -> Self {
|
||||||
assert_eq!(width % 8, 0);
|
assert_eq!(width % 8, 0);
|
||||||
assert_eq!(data.len(), height * width / 8);
|
assert_eq!(data.len(), height * width / 8);
|
||||||
|
@ -38,24 +40,28 @@ impl PixelGrid {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_indexes(&self, x: usize, y: usize) {
|
fn check_indexes(&self, x: usize, y: usize) {
|
||||||
if x >= self.width {
|
assert!(
|
||||||
panic!("cannot access pixel {x}-{y} because x is outside of bounds 0..{}", self.width)
|
x < self.width,
|
||||||
}
|
"cannot access pixel {x}-{y} because x is outside of bounds 0..{}",
|
||||||
if y >= self.height {
|
self.width
|
||||||
panic!("cannot access pixel {x}-{y} because y is outside of bounds 0..{}", self.height)
|
);
|
||||||
}
|
assert!(
|
||||||
|
y < self.height,
|
||||||
|
"cannot access pixel {x}-{y} because y is outside of bounds 0..{}",
|
||||||
|
self.height
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Grid<bool> for PixelGrid {
|
impl Grid<bool> for PixelGrid {
|
||||||
/// Creates a new pixel grid with the specified dimensions.
|
/// Creates a new `PixelGrid` with the specified dimensions.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `width`: size in pixels in x-direction
|
/// * `width`: size in pixels in x-direction
|
||||||
/// * `height`: size in pixels in y-direction
|
/// * `height`: size in pixels in y-direction
|
||||||
///
|
///
|
||||||
/// returns: PixelGrid initialized to all pixels off
|
/// returns: `PixelGrid` initialized to all pixels off
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in a new issue