revert hackfix in GeneralBlitMethod. fix CustomMouseCursor rendering

at this point i am 99% certain that the previous issues i was having
with making GeneralBlitMethod generic over the bitmap PixelType was
because i was trying to specify a constant PixelType value in generic
code (CustomMouseCursor).

whether this was actually the problem or not i think is besides the
point however because while thinking about this i suddenly realized this
was incorrect anyway!

making CustomMouseCursor generic via GeneralBitmap means that specifying
constant colours was not going to produce expected results (e.g. '255'
has a very different meaning for indexed colour rendering versus for
32-bit RGBA colour format).

so, CustomMouseCursor now figures out the correct transparent colour
to use from the DefaultMouseCursorBitmaps implementation.

this allows us to make GeneralBlitMethod be generic over a bitmap's
PixelType again and i'm sure we won't have that previous issue again as
long as we don't try to specify constant colour values in our generic
rendering code ... which we should never be doing anyway!
This commit is contained in:
Gered 2023-03-09 14:51:01 -05:00
parent 696ed0bfb3
commit f3d213130d
2 changed files with 32 additions and 21 deletions

View file

@ -13,13 +13,10 @@ use num_traits::{PrimInt, Unsigned};
use crate::graphics::indexed;
use crate::math::Rect;
// HACK: enum variant color arguments are sized to the max possible pixel type used across all supported bitmap variants
// right now. for some reason, making this enum generic (e.g. `GeneralBlitMethod<PixelType: PrimInt + Unsigned>`)
// resulted in some E0308 compile errors when trying to create enum variant values that contained args of the
// generic type. i could not find a solution to this. so i'll just do this hack approach for now. ugh.
pub enum GeneralBlitMethod {
#[derive(Clone, PartialEq)]
pub enum GeneralBlitMethod<PixelType: PrimInt + Unsigned> {
Solid,
Transparent(u32),
Transparent(PixelType),
}
/// Trait that provides "bit-depth-agnostic" access to bitmap drawing operations. This is useful for implementing
@ -83,14 +80,14 @@ pub trait GeneralBitmap: Sized {
fn blit_region(
&mut self,
method: GeneralBlitMethod,
method: GeneralBlitMethod<Self::PixelType>,
src: &Self,
src_region: &Rect,
dest_x: i32,
dest_y: i32
);
fn blit(&mut self, method: GeneralBlitMethod, src: &Self, x: i32, y: i32) {
fn blit(&mut self, method: GeneralBlitMethod<Self::PixelType>, src: &Self, x: i32, y: i32) {
let src_region = Rect::new(0, 0, src.width(), src.height());
self.blit_region(method, src, &src_region, x, y);
}
@ -171,16 +168,15 @@ impl GeneralBitmap for indexed::Bitmap {
fn blit_region(
&mut self,
method: GeneralBlitMethod,
method: GeneralBlitMethod<Self::PixelType>,
src: &Self,
src_region: &Rect,
dest_x: i32,
dest_y: i32
) {
// HACK: pixel/color value downcasting. see "HACK" comment above GeneralBlitMethod type def
let blit_method = match method {
GeneralBlitMethod::Solid => indexed::BlitMethod::Solid,
GeneralBlitMethod::Transparent(color) => indexed::BlitMethod::Transparent(color as u8),
GeneralBlitMethod::Transparent(color) => indexed::BlitMethod::Transparent(color),
};
self.blit_region(blit_method, src, src_region, dest_x, dest_y)
}

View file

@ -13,7 +13,7 @@ pub trait DefaultMouseCursorBitmaps<BitmapType>
where
BitmapType: GeneralBitmap
{
fn get_default() -> BitmapType;
fn get_default() -> (BitmapType, BitmapType::PixelType);
}
/// Provides custom mouse cursor rendering functionality via application provided [`Bitmap`]s (or falling back
@ -30,6 +30,7 @@ where
cursor_hotspot_x: u32,
cursor_hotspot_y: u32,
cursor_enabled: bool,
cursor_transparent_color: BitmapType::PixelType,
}
impl<BitmapType> CustomMouseCursor<BitmapType>
@ -38,7 +39,13 @@ where
BitmapType: GeneralBitmap
{
pub fn new() -> Self {
let (cursor, cursor_background, cursor_hotspot_x, cursor_hotspot_y) = Self::get_default_mouse_cursor();
let (
cursor,
cursor_background,
cursor_hotspot_x,
cursor_hotspot_y,
cursor_transparent_color,
) = Self::get_default_mouse_cursor();
CustomMouseCursor {
last_x: 0,
@ -48,6 +55,7 @@ where
cursor_hotspot_x,
cursor_hotspot_y,
cursor_enabled: false,
cursor_transparent_color,
}
}
@ -89,20 +97,22 @@ where
/// * `cursor`: the bitmap to be used to display the mouse cursor on screen
/// * `hotspot_x`: the "hotspot" x coordinate
/// * `hotspot_y`: the "hotspot" y coordinate.
pub fn set_mouse_cursor(&mut self, cursor: BitmapType, hotspot_x: u32, hotspot_y: u32) {
pub fn set_mouse_cursor(&mut self, cursor: BitmapType, transparent_color: BitmapType::PixelType, hotspot_x: u32, hotspot_y: u32) {
self.cursor = cursor;
self.cursor_background = BitmapType::new(self.cursor.width(), self.cursor.height()).unwrap();
self.cursor_hotspot_x = hotspot_x;
self.cursor_hotspot_y = hotspot_y;
self.cursor_transparent_color = transparent_color;
}
/// Resets the mouse cursor bitmap and "hotspot" coordinate back to the default settings.
pub fn set_default_mouse_cursor(&mut self) {
let (cursor, background, hotspot_x, hotspot_y) = Self::get_default_mouse_cursor();
let (cursor, background, hotspot_x, hotspot_y, transparent_color) = Self::get_default_mouse_cursor();
self.cursor = cursor;
self.cursor_background = background;
self.cursor_hotspot_x = hotspot_x;
self.cursor_hotspot_y = hotspot_y;
self.cursor_transparent_color = transparent_color;
}
#[inline]
@ -141,8 +151,12 @@ where
0,
);
let color = 255;
dest.blit(GeneralBlitMethod::Transparent(color), &self.cursor, x, y);
dest.blit(
GeneralBlitMethod::Transparent(self.cursor_transparent_color),
&self.cursor,
x,
y
);
}
/// Restores the original destination bitmap contents where the mouse cursor bitmap was
@ -175,8 +189,8 @@ where
self.last_y = mouse.y;
}
fn get_default_mouse_cursor() -> (BitmapType, BitmapType, u32, u32) {
let cursor = Self::get_default();
fn get_default_mouse_cursor() -> (BitmapType, BitmapType, u32, u32, BitmapType::PixelType) {
let (cursor, transparent_color) = Self::get_default();
let cursor_background = BitmapType::new(cursor.width(), cursor.height()).unwrap();
(
@ -184,12 +198,13 @@ where
cursor_background,
DEFAULT_MOUSE_CURSOR_HOTSPOT_X,
DEFAULT_MOUSE_CURSOR_HOTSPOT_Y,
transparent_color,
)
}
}
impl DefaultMouseCursorBitmaps<indexed::Bitmap> for CustomMouseCursor<indexed::Bitmap> {
fn get_default() -> Bitmap {
fn get_default() -> (Bitmap, u8) {
#[rustfmt::skip]
const CURSOR_PIXELS: [u8; DEFAULT_MOUSE_CURSOR_WIDTH * DEFAULT_MOUSE_CURSOR_HEIGHT] = [
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@ -215,7 +230,7 @@ impl DefaultMouseCursorBitmaps<indexed::Bitmap> for CustomMouseCursor<indexed::B
DEFAULT_MOUSE_CURSOR_HEIGHT as u32,
).unwrap();
cursor.pixels_mut().copy_from_slice(&CURSOR_PIXELS);
cursor
(cursor, 255)
}
}