diff --git a/src/graphics/image.rs b/src/graphics/image.rs index 408b2365..757345da 100644 --- a/src/graphics/image.rs +++ b/src/graphics/image.rs @@ -1,3 +1,5 @@ +use std::{error::Error, fmt}; + use { crate::{ ffi::graphics as ffi, @@ -186,10 +188,37 @@ impl Image { /// This function doesn't check the validity of the pixel /// coordinates, using out-of-range values will result in /// an undefined behaviour. - pub unsafe fn set_pixel(&mut self, x: u32, y: u32, color: Color) { + pub unsafe fn set_pixel_unchecked(&mut self, x: u32, y: u32, color: Color) { ffi::sfImage_setPixel(self.image, x, y, color) } + /// Change the color of a pixel in an image + /// + /// # Arguments + /// * x - X coordinate of pixel to change + /// * y - Y coordinate of pixel to change + /// * color - New color of the pixel + pub fn set_pixel(&mut self, x: u32, y: u32, color: Color) -> Result<(), SetPixelError> { + let image_size = self.size(); + if x >= image_size.x { + return Err(SetPixelError::XTooLarge { + x, + width: image_size.x - 1, + }); + } + if y >= image_size.y { + return Err(SetPixelError::YTooLarge { + y, + height: image_size.y - 1, + }); + } + + // Since we check for index validity before setting the pixel, it is safe unless the + // image has been unloaded, but I doubt you can even do that. + unsafe { ffi::sfImage_setPixel(self.image, x, y, color) } + Ok(()) + } + /// Get the color of a pixel in an image /// /// # Arguments @@ -204,10 +233,29 @@ impl Image { /// coordinates, using out-of-range values will result in /// an undefined behaviour. #[must_use] - pub unsafe fn pixel_at(&self, x: u32, y: u32) -> Color { + pub unsafe fn pixel_at_unchecked(&self, x: u32, y: u32) -> Color { ffi::sfImage_getPixel(self.image, x, y) } + /// Get the color of a pixel in an image + /// + /// # Arguments + /// * x - X coordinate of pixel to get + /// * y - Y coordinate of pixel to get + /// + /// Return the Color of the pixel at coordinates (x, y) + #[must_use] + pub fn pixel_at(&self, x: u32, y: u32) -> Option { + let image_size = self.size(); + if image_size.x <= x || image_size.y <= y { + return None; + } + + // Since we check for index validity before getting the pixel, it is safe unless the + // image has been unloaded, but I doubt you can even do that. + unsafe { Some(ffi::sfImage_getPixel(self.image, x, y)) } + } + /// Return the memory buffer of this image. #[must_use] pub fn pixel_data(&self) -> &[u8] { @@ -293,3 +341,24 @@ impl Drop for Image { unsafe { ffi::sfImage_destroy(self.image) } } } + +#[derive(Debug, Copy, Clone)] +pub enum SetPixelError { + XTooLarge { x: u32, width: u32 }, + YTooLarge { y: u32, height: u32 }, +} + +impl Error for SetPixelError {} + +impl fmt::Display for SetPixelError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::XTooLarge { x, width } => { + write!(f, "x index out of bounds. x:{} width:{}", x, width) + } + Self::YTooLarge { y, height } => { + write!(f, "y index out of bounds. y:{} height:{}", y, height) + } + } + } +} diff --git a/src/window/context.rs b/src/window/context.rs index a18a71f8..98e311ec 100644 --- a/src/window/context.rs +++ b/src/window/context.rs @@ -69,8 +69,8 @@ impl Context { /// Get the address of an OpenGL function. /// # Arguments /// * name - Name of the function to get the address of - /// - /// Returns the address of the OpenGL function, 0 on failure + /// + /// Returns the address of the OpenGL function, 0 on failure pub unsafe fn get_function(name: &CStr) -> *const std::ffi::c_void { unsafe { ffi::sfContext_getFunction(name.as_ptr()) } }