#[allow(unused_imports)]
use crate::{
graphics::InterpolationMode,
render::{BufferCollision, BufferGetPixel, BufferMetrics, BufferSetPixel},
};
#[allow(clippy::cast_sign_loss)]
#[allow(clippy::cast_precision_loss)]
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_wrap)]
#[cfg(feature = "std")]
pub fn draw_buffer_on_buffer_stretched<
const SAFE: bool,
const TRANSPARENCY: bool,
const TRANSPARENCY_INTERPOLATION: bool,
const NICHE_TRANSPARENCY_CHECK: bool,
>(
canvas: &mut crate::prelude::Buffer,
texture: &crate::prelude::Buffer,
position: (isize, isize),
result_dimensions: (usize, usize),
interpolation_mode: InterpolationMode,
) {
draw_buffer_on_buffer::<
SAFE,
TRANSPARENCY,
TRANSPARENCY_INTERPOLATION,
NICHE_TRANSPARENCY_CHECK,
>(
canvas,
&texture.resize_content(result_dimensions, interpolation_mode),
position,
);
}
#[cfg(feature = "std")]
pub fn draw_buffer_on_buffer_stretched_smart<
const TRANSPARENCY: bool,
const TRANSPARENCY_INTERPOLATION: bool,
const NICHE_TRANSPARENCY_CHECK: bool,
>(
canvas: &mut crate::prelude::Buffer,
texture: &crate::prelude::Buffer,
position: (isize, isize),
result_dimensions: (usize, usize),
interpolation_mode: InterpolationMode,
) {
if core::intrinsics::unlikely(result_dimensions == texture.get_size()) {
draw_buffer_on_buffer_smart::<
TRANSPARENCY,
TRANSPARENCY_INTERPOLATION,
NICHE_TRANSPARENCY_CHECK,
>(canvas, texture, position);
} else {
draw_buffer_on_buffer_smart::<
TRANSPARENCY,
TRANSPARENCY_INTERPOLATION,
NICHE_TRANSPARENCY_CHECK,
>(
canvas,
&texture.resize_content(result_dimensions, interpolation_mode),
position,
);
}
}
pub fn draw_buffer_on_buffer_smart<
const TRANSPARENCY: bool,
const TRANSPARENCY_INTERPOLATION: bool,
const NICHE_TRANSPARENCY_CHECK: bool,
>(
canvas: &mut (impl BufferMetrics
+ BufferGetPixel
+ BufferSetPixel
+ BufferCollision),
texture: &(impl BufferMetrics + BufferGetPixel),
position: (isize, isize),
) {
let Some(collision_big) = canvas.try_to_collision::<false, isize>(position)
else {
return;
};
let Some(collision_small) =
texture.try_to_collision::<false, isize>(position)
else {
return;
};
if core::intrinsics::likely(
collision_big.do_areas_intersect_strict(&collision_small),
) {
if collision_big.does_area_fully_include_other_area(&collision_small) {
draw_buffer_on_buffer::<
false,
TRANSPARENCY,
TRANSPARENCY_INTERPOLATION,
NICHE_TRANSPARENCY_CHECK,
>(canvas, texture, position);
} else {
draw_buffer_on_buffer::<
true,
TRANSPARENCY,
TRANSPARENCY_INTERPOLATION,
NICHE_TRANSPARENCY_CHECK,
>(canvas, texture, position);
}
}
}
#[allow(clippy::cast_possible_wrap)]
#[allow(clippy::cast_sign_loss)]
pub fn draw_buffer_on_buffer<
const SAFE: bool,
const TRANSPARENCY: bool,
const TRANSPARENCY_INTERPOLATION: bool,
const NICHE_TRANSPARENCY_CHECK: bool,
>(
canvas: &mut (impl BufferMetrics + BufferGetPixel + BufferSetPixel),
texture: &(impl BufferMetrics + BufferGetPixel),
position: (isize, isize),
) {
let canvas_start_x = if SAFE {
position.0.max(0)
} else {
position.0
};
let canvas_start_y = if SAFE {
position.1.max(0)
} else {
position.1
};
let canvas_end_x = if SAFE {
(position.0 + texture.width() as isize).min(canvas.width() as isize)
} else {
position.0 + texture.width() as isize
};
let canvas_end_y = if SAFE {
(position.1 + texture.height() as isize).min(canvas.height() as isize)
} else {
position.1 + texture.height() as isize
};
if SAFE
&& (canvas_start_x >= canvas_end_x || canvas_start_y >= canvas_end_y)
{
return;
}
let texture_start_x = (canvas_start_x - position.0) as usize;
let texture_start_y = (canvas_start_y - position.1) as usize;
for canvas_y in canvas_start_y..canvas_end_y {
for canvas_x in canvas_start_x..canvas_end_x {
let texture_x =
texture_start_x + (canvas_x - canvas_start_x) as usize;
let texture_y =
texture_start_y + (canvas_y - canvas_start_y) as usize;
let pixel = texture.get_pixel_unsafe((texture_x, texture_y));
if TRANSPARENCY {
let trans = crate::graphics::get_alpha_of_u32(pixel);
if NICHE_TRANSPARENCY_CHECK && trans == 0 {
continue;
}
let color = if TRANSPARENCY_INTERPOLATION {
if NICHE_TRANSPARENCY_CHECK && trans == 255 {
pixel
} else if NICHE_TRANSPARENCY_CHECK && trans == 0 {
continue;
} else {
crate::graphics::interpolate_color_rgb_u32_f32(
canvas.get_pixel_unsafe((
canvas_x as usize,
canvas_y as usize,
)),
pixel,
trans as f32 / 255.0,
)
}
} else if trans != 0 {
pixel
} else {
canvas.get_pixel_unsafe((
canvas_x as usize,
canvas_y as usize,
))
};
canvas.set_pixel_unsafe(
(canvas_x as usize, canvas_y as usize),
color,
);
} else {
canvas.set_pixel_unsafe(
(canvas_x as usize, canvas_y as usize),
pixel,
);
}
}
}
}