update IndexedBitmap blended primitives to use new generic functions
This commit is contained in:
parent
a667a657d2
commit
3864f36706
|
@ -1,8 +1,5 @@
|
||||||
use std::mem::swap;
|
|
||||||
|
|
||||||
use crate::graphics::bitmap::indexed::IndexedBitmap;
|
use crate::graphics::bitmap::indexed::IndexedBitmap;
|
||||||
use crate::graphics::blendmap::BlendMap;
|
use crate::graphics::blendmap::BlendMap;
|
||||||
use crate::math::rect::Rect;
|
|
||||||
|
|
||||||
impl IndexedBitmap {
|
impl IndexedBitmap {
|
||||||
/// Sets the pixel at the given coordinates using a blended color via the specified blend map,
|
/// Sets the pixel at the given coordinates using a blended color via the specified blend map,
|
||||||
|
@ -10,14 +7,16 @@ impl IndexedBitmap {
|
||||||
/// coordinates lie outside of the bitmaps clipping region, no pixels will be changed.
|
/// coordinates lie outside of the bitmaps clipping region, no pixels will be changed.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_blended_pixel(&mut self, x: i32, y: i32, color: u8, blend_map: &BlendMap) {
|
pub fn set_blended_pixel(&mut self, x: i32, y: i32, color: u8, blend_map: &BlendMap) {
|
||||||
if let Some(pixels) = self.pixels_at_mut(x, y) {
|
self.set_custom_pixel(
|
||||||
let dest_color = pixels[0];
|
x, y,
|
||||||
if let Some(blended_color) = blend_map.blend(color, dest_color) {
|
|dest_color| {
|
||||||
pixels[0] = blended_color;
|
if let Some(blended_color) = blend_map.blend(color, dest_color) {
|
||||||
} else {
|
blended_color
|
||||||
pixels[0] = color;
|
} else {
|
||||||
|
color
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the pixel at the given coordinates using a blended color via the specified blend map,
|
/// Sets the pixel at the given coordinates using a blended color via the specified blend map,
|
||||||
|
@ -26,77 +25,28 @@ impl IndexedBitmap {
|
||||||
/// bounds of the bitmap.
|
/// bounds of the bitmap.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn set_blended_pixel_unchecked(&mut self, x: i32, y: i32, color: u8, blend_map: &BlendMap) {
|
pub unsafe fn set_blended_pixel_unchecked(&mut self, x: i32, y: i32, color: u8, blend_map: &BlendMap) {
|
||||||
let p = self.pixels_at_mut_ptr_unchecked(x, y);
|
self.set_custom_pixel_unchecked(
|
||||||
if let Some(blended_color) = blend_map.blend(color, *p) {
|
x, y,
|
||||||
*p = blended_color;
|
|dest_color| {
|
||||||
} else {
|
if let Some(blended_color) = blend_map.blend(color, dest_color) {
|
||||||
*p = color;
|
blended_color
|
||||||
}
|
} else {
|
||||||
|
color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draws a line from x1,y1 to x2,y2 by blending the drawn pixels using the given blend map,
|
/// Draws a line from x1,y1 to x2,y2 by blending the drawn pixels using the given blend map,
|
||||||
/// or the color specified if the blend map does not include this color.
|
/// or the color specified if the blend map does not include this color.
|
||||||
pub fn blended_line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: u8, blend_map: &BlendMap) {
|
pub fn blended_line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: u8, blend_map: &BlendMap) {
|
||||||
if let Some(blend_mapping) = blend_map.get_mapping(color) {
|
if let Some(blend_mapping) = blend_map.get_mapping(color) {
|
||||||
let mut dx = x1;
|
self.line_custom(
|
||||||
let mut dy = y1;
|
x1, y1, x2, y2,
|
||||||
let delta_x = x2 - x1;
|
|dest_color| {
|
||||||
let delta_y = y2 - y1;
|
blend_mapping[dest_color as usize]
|
||||||
let delta_x_abs = delta_x.abs();
|
|
||||||
let delta_y_abs = delta_y.abs();
|
|
||||||
let delta_x_sign = delta_x.signum();
|
|
||||||
let delta_y_sign = delta_y.signum();
|
|
||||||
let mut x = delta_x_abs / 2;
|
|
||||||
let mut y = delta_y_abs / 2;
|
|
||||||
let offset_x_inc = delta_x_sign;
|
|
||||||
let offset_y_inc = delta_y_sign * self.width as i32;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
// safety: while we are blindly getting a pointer to this x/y coordinate, we don't
|
|
||||||
// write to it unless we know the coordinates are in bounds.
|
|
||||||
// TODO: should be ok ... ? or am i making too many assumptions about memory layout?
|
|
||||||
let mut dest = self.pixels_at_mut_ptr_unchecked(x1, y1);
|
|
||||||
|
|
||||||
if self.is_xy_visible(dx, dy) {
|
|
||||||
*dest = blend_mapping[*dest as usize];
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
if delta_x_abs >= delta_y_abs {
|
|
||||||
for _ in 0..delta_x_abs {
|
|
||||||
y += delta_y_abs;
|
|
||||||
|
|
||||||
if y >= delta_x_abs {
|
|
||||||
y -= delta_x_abs;
|
|
||||||
dy += delta_y_sign;
|
|
||||||
dest = dest.offset(offset_y_inc as isize);
|
|
||||||
}
|
|
||||||
|
|
||||||
dx += delta_x_sign;
|
|
||||||
dest = dest.offset(offset_x_inc as isize);
|
|
||||||
|
|
||||||
if self.is_xy_visible(dx, dy) {
|
|
||||||
*dest = blend_mapping[*dest as usize];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _ in 0..delta_y_abs {
|
|
||||||
x += delta_x_abs;
|
|
||||||
|
|
||||||
if x >= delta_y_abs {
|
|
||||||
x -= delta_y_abs;
|
|
||||||
dx += delta_x_sign;
|
|
||||||
dest = dest.offset(offset_x_inc as isize);
|
|
||||||
}
|
|
||||||
|
|
||||||
dy += delta_y_sign;
|
|
||||||
dest = dest.offset(offset_y_inc as isize);
|
|
||||||
|
|
||||||
if self.is_xy_visible(dx, dy) {
|
|
||||||
*dest = blend_mapping[*dest as usize];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.line(x1, y1, x2, y2, color);
|
self.line(x1, y1, x2, y2, color);
|
||||||
}
|
}
|
||||||
|
@ -106,15 +56,12 @@ impl IndexedBitmap {
|
||||||
/// blend map, or the color specified if the blend map does not include this color.
|
/// blend map, or the color specified if the blend map does not include this color.
|
||||||
pub fn blended_horiz_line(&mut self, x1: i32, x2: i32, y: i32, color: u8, blend_map: &BlendMap) {
|
pub fn blended_horiz_line(&mut self, x1: i32, x2: i32, y: i32, color: u8, blend_map: &BlendMap) {
|
||||||
if let Some(blend_mapping) = blend_map.get_mapping(color) {
|
if let Some(blend_mapping) = blend_map.get_mapping(color) {
|
||||||
let mut region = Rect::from_coords(x1, y, x2, y);
|
self.horiz_line_custom(
|
||||||
if region.clamp_to(&self.clip_region) {
|
x1, x2, y,
|
||||||
unsafe {
|
|dest_color| {
|
||||||
let dest = self.pixels_at_mut_unchecked(region.x, region.y);
|
blend_mapping[dest_color as usize]
|
||||||
for x in 0..region.width as usize {
|
|
||||||
dest[x] = blend_mapping[dest[x] as usize];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
} else {
|
} else {
|
||||||
self.horiz_line(x1, x2, y, color);
|
self.horiz_line(x1, x2, y, color);
|
||||||
}
|
}
|
||||||
|
@ -124,16 +71,12 @@ impl IndexedBitmap {
|
||||||
/// map, or the color specified if the blend map does not include this color.
|
/// map, or the color specified if the blend map does not include this color.
|
||||||
pub fn blended_vert_line(&mut self, x: i32, y1: i32, y2: i32, color: u8, blend_map: &BlendMap) {
|
pub fn blended_vert_line(&mut self, x: i32, y1: i32, y2: i32, color: u8, blend_map: &BlendMap) {
|
||||||
if let Some(blend_mapping) = blend_map.get_mapping(color) {
|
if let Some(blend_mapping) = blend_map.get_mapping(color) {
|
||||||
let mut region = Rect::from_coords(x, y1, x, y2);
|
self.vert_line_custom(
|
||||||
if region.clamp_to(&self.clip_region) {
|
x, y1, y2,
|
||||||
unsafe {
|
|dest_color| {
|
||||||
let mut dest = self.pixels_at_mut_ptr_unchecked(region.x, region.y);
|
blend_mapping[dest_color as usize]
|
||||||
for _ in 0..region.height {
|
|
||||||
*dest = blend_mapping[*dest as usize];
|
|
||||||
dest = dest.add(self.width as usize);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
} else {
|
} else {
|
||||||
self.vert_line(x, y1, y2, color);
|
self.vert_line(x, y1, y2, color);
|
||||||
}
|
}
|
||||||
|
@ -143,75 +86,14 @@ impl IndexedBitmap {
|
||||||
/// drawn, assuming they are specifying the top-left and bottom-right corners respectively.
|
/// drawn, assuming they are specifying the top-left and bottom-right corners respectively.
|
||||||
/// The box is drawn by blending the drawn pixels using the given blend map, or the color
|
/// The box is drawn by blending the drawn pixels using the given blend map, or the color
|
||||||
/// specified if the blend map does not include this color.
|
/// specified if the blend map does not include this color.
|
||||||
pub fn blended_rect(&mut self, mut x1: i32, mut y1: i32, mut x2: i32, mut y2: i32, color: u8, blend_map: &BlendMap) {
|
pub fn blended_rect(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: u8, blend_map: &BlendMap) {
|
||||||
if let Some(blend_mapping) = blend_map.get_mapping(color) {
|
if let Some(blend_mapping) = blend_map.get_mapping(color) {
|
||||||
// note: need to manually do all this instead of just relying on Rect::from_coords (which
|
self.rect_custom(
|
||||||
// could otherwise figure all this out for us) mainly just because we need the post-swap
|
x1, y1, x2, y2,
|
||||||
// x1,y1,x2,y2 values for post-region-clamping comparison purposes ...
|
|dest_color| {
|
||||||
if x2 < x1 {
|
blend_mapping[dest_color as usize]
|
||||||
swap(&mut x1, &mut x2);
|
|
||||||
}
|
|
||||||
if y2 < y1 {
|
|
||||||
swap(&mut y1, &mut y2);
|
|
||||||
}
|
|
||||||
let mut region = Rect {
|
|
||||||
x: x1,
|
|
||||||
y: y1,
|
|
||||||
width: (x2 - x1 + 1) as u32,
|
|
||||||
height: (y2 - y1 + 1) as u32,
|
|
||||||
};
|
|
||||||
if !region.clamp_to(&self.clip_region) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// note that since we're performing a blend based on the existing destination pixel,
|
|
||||||
// we need to make sure that we don't draw any overlapping corner pixels (where we
|
|
||||||
// would end up blending with the edge of a previously drawn line).
|
|
||||||
// to solve this issue, we just cut off the left-most and right-most pixels for the
|
|
||||||
// two horizontal lines drawn. those corner pixels will be drawn during the vertical
|
|
||||||
// line drawing instead.
|
|
||||||
|
|
||||||
// top line, only if y1 was originally within bounds
|
|
||||||
if y1 == region.y {
|
|
||||||
unsafe {
|
|
||||||
let dest = self.pixels_at_mut_unchecked(region.x, region.y);
|
|
||||||
for x in 1..(region.width - 1) as usize {
|
|
||||||
dest[x] = blend_mapping[dest[x] as usize];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
|
|
||||||
// bottom line, only if y2 was originally within bounds
|
|
||||||
if y2 == region.bottom() {
|
|
||||||
unsafe {
|
|
||||||
let dest = self.pixels_at_mut_unchecked(region.x, region.bottom());
|
|
||||||
for x in 1..(region.width - 1) as usize {
|
|
||||||
dest[x] = blend_mapping[dest[x] as usize];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// left line, only if x1 was originally within bounds
|
|
||||||
if x1 == region.x {
|
|
||||||
unsafe {
|
|
||||||
let mut dest = self.pixels_at_mut_ptr_unchecked(region.x, region.y);
|
|
||||||
for _ in 0..region.height {
|
|
||||||
*dest = blend_mapping[*dest as usize];
|
|
||||||
dest = dest.add(self.width as usize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// right line, only if x2 was originally within bounds
|
|
||||||
if x2 == region.right() {
|
|
||||||
unsafe {
|
|
||||||
let mut dest = self.pixels_at_mut_ptr_unchecked(region.right(), region.y);
|
|
||||||
for _ in 0..region.height {
|
|
||||||
*dest = blend_mapping[*dest as usize];
|
|
||||||
dest = dest.add(self.width as usize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.rect(x1, y1, x2, y2, color);
|
self.rect(x1, y1, x2, y2, color);
|
||||||
}
|
}
|
||||||
|
@ -223,19 +105,12 @@ impl IndexedBitmap {
|
||||||
/// specified if the blend map does not include this color.
|
/// specified if the blend map does not include this color.
|
||||||
pub fn blended_filled_rect(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: u8, blend_map: &BlendMap) {
|
pub fn blended_filled_rect(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: u8, blend_map: &BlendMap) {
|
||||||
if let Some(blend_mapping) = blend_map.get_mapping(color) {
|
if let Some(blend_mapping) = blend_map.get_mapping(color) {
|
||||||
let mut region = Rect::from_coords(x1, y1, x2, y2);
|
self.filled_rect_custom(
|
||||||
if region.clamp_to(&self.clip_region) {
|
x1, y1, x2, y2,
|
||||||
unsafe {
|
|dest_color| {
|
||||||
let mut dest = self.pixels_at_mut_ptr_unchecked(region.x, region.y);
|
blend_mapping[dest_color as usize]
|
||||||
for _ in 0..region.height {
|
|
||||||
for x in 0..region.width as usize {
|
|
||||||
let dest_x = dest.offset(x as isize);
|
|
||||||
*dest_x = blend_mapping[*dest_x as usize];
|
|
||||||
}
|
|
||||||
dest = dest.add(self.width as usize);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
} else {
|
} else {
|
||||||
self.filled_rect(x1, y1, x2, y2, color);
|
self.filled_rect(x1, y1, x2, y2, color);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue