convert RgbaBitmap to use ARGBu8x4 as its pixel type

This commit is contained in:
Gered 2023-05-04 18:54:37 -04:00
parent cf92d42b84
commit 09dbb913a5
38 changed files with 426 additions and 405 deletions

View file

@ -11,7 +11,7 @@ pub struct CoreContext {
pub delta: f32, pub delta: f32,
pub camera_x: i32, pub camera_x: i32,
pub camera_y: i32, pub camera_y: i32,
pub transparent_color: u32, pub transparent_color: ARGBu8x4,
pub system: System<Standard>, pub system: System<Standard>,
pub palette: Palette, pub palette: Palette,
pub font: BitmaskFont, pub font: BitmaskFont,

View file

@ -63,7 +63,7 @@ impl TileMap {
tiles: &BitmapAtlas<RgbaBitmap>, tiles: &BitmapAtlas<RgbaBitmap>,
camera_x: i32, camera_x: i32,
camera_y: i32, camera_y: i32,
transparent_color: u32, transparent_color: ARGBu8x4,
) { ) {
let xt = camera_x / TILE_WIDTH as i32; let xt = camera_x / TILE_WIDTH as i32;
let yt = camera_y / TILE_HEIGHT as i32; let yt = camera_y / TILE_HEIGHT as i32;

View file

@ -7,7 +7,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let height = 240; let height = 240;
let mut source = IndexedBitmap::new(width, height).unwrap(); let mut source = IndexedBitmap::new(width, height).unwrap();
let mut dest = vec![0u32; (width * height * 4) as usize].into_boxed_slice(); let mut dest = vec![ARGBu8x4::default(); (width * height) as usize].into_boxed_slice();
let palette = Palette::new_vga_palette().unwrap(); let palette = Palette::new_vga_palette().unwrap();
c.bench_function("deindex_bitmap_pixels", |b| b.iter(|| source.copy_as_argb_to(&mut dest, &palette))); c.bench_function("deindex_bitmap_pixels", |b| b.iter(|| source.copy_as_argb_to(&mut dest, &palette)));

View file

@ -6,6 +6,10 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let width = 320; let width = 320;
let height = 240; let height = 240;
const BG_COLOR: ARGBu8x4 = ARGBu8x4::from_rgb([0, 0, 0]);
const SOLID_COLOR: ARGBu8x4 = ARGBu8x4::from_rgb([255, 0, 255]);
const BLEND_COLOR: ARGBu8x4 = ARGBu8x4::from_argb([127, 255, 0, 255]);
let mut dest = RgbaBitmap::new(width, height).unwrap(); let mut dest = RgbaBitmap::new(width, height).unwrap();
// note that none of these are all-inclusive benchmarks that cover all kinds of different scenarios and such // note that none of these are all-inclusive benchmarks that cover all kinds of different scenarios and such
@ -16,140 +20,142 @@ pub fn criterion_benchmark(c: &mut Criterion) {
// as i change other things in the future // as i change other things in the future
c.bench_function("rgbabitmap_primitives_set_pixel", |b| { c.bench_function("rgbabitmap_primitives_set_pixel", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| dest.set_pixel(black_box(100), black_box(100), black_box(0xffff00ff))) b.iter(|| dest.set_pixel(black_box(100), black_box(100), black_box(SOLID_COLOR)))
}); });
c.bench_function("rgbabitmap_primitives_set_blended_pixel", |b| { c.bench_function("rgbabitmap_primitives_set_blended_pixel", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| { b.iter(|| {
dest.set_blended_pixel( dest.set_blended_pixel(
black_box(100), black_box(100),
black_box(100), black_box(100),
black_box(0x7fff00ff), black_box(BLEND_COLOR),
black_box(BlendFunction::Blend), black_box(BlendFunction::Blend),
) )
}) })
}); });
c.bench_function("rgbabitmap_primitives_set_pixel_unchecked", |b| { c.bench_function("rgbabitmap_primitives_set_pixel_unchecked", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| unsafe { dest.set_pixel_unchecked(black_box(100), black_box(100), black_box(0xffff00ff)) }) b.iter(|| unsafe { dest.set_pixel_unchecked(black_box(100), black_box(100), black_box(SOLID_COLOR)) })
}); });
c.bench_function("rgbabitmap_primitives_set_blended_pixel_unchecked", |b| { c.bench_function("rgbabitmap_primitives_set_blended_pixel_unchecked", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| unsafe { b.iter(|| unsafe {
dest.set_blended_pixel_unchecked( dest.set_blended_pixel_unchecked(
black_box(100), black_box(100),
black_box(100), black_box(100),
black_box(0x7fff00ff), black_box(BLEND_COLOR),
black_box(BlendFunction::Blend), black_box(BlendFunction::Blend),
) )
}) })
}); });
c.bench_function("rgbabitmap_primitives_line", |b| { c.bench_function("rgbabitmap_primitives_line", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| dest.line(black_box(10), black_box(50), black_box(310), black_box(120), black_box(0xffff00ff))) b.iter(|| dest.line(black_box(10), black_box(50), black_box(310), black_box(120), black_box(SOLID_COLOR)))
}); });
c.bench_function("rgbabitmap_primitives_blended_line", |b| { c.bench_function("rgbabitmap_primitives_blended_line", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| { b.iter(|| {
dest.blended_line( dest.blended_line(
black_box(10), black_box(10),
black_box(50), black_box(50),
black_box(310), black_box(310),
black_box(120), black_box(120),
black_box(0x7fff00ff), black_box(BLEND_COLOR),
black_box(BlendFunction::Blend), black_box(BlendFunction::Blend),
) )
}) })
}); });
c.bench_function("rgbabitmap_primitives_horiz_line", |b| { c.bench_function("rgbabitmap_primitives_horiz_line", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| dest.horiz_line(black_box(10), black_box(310), black_box(70), black_box(0xffff00ff))) b.iter(|| dest.horiz_line(black_box(10), black_box(310), black_box(70), black_box(SOLID_COLOR)))
}); });
c.bench_function("rgbabitmap_primitives_blended_horiz_line", |b| { c.bench_function("rgbabitmap_primitives_blended_horiz_line", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| { b.iter(|| {
dest.blended_horiz_line( dest.blended_horiz_line(
black_box(10), black_box(10),
black_box(310), black_box(310),
black_box(70), black_box(70),
black_box(0x7fff00ff), black_box(BLEND_COLOR),
black_box(BlendFunction::Blend), black_box(BlendFunction::Blend),
) )
}) })
}); });
c.bench_function("rgbabitmap_primitives_vert_line", |b| { c.bench_function("rgbabitmap_primitives_vert_line", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| dest.vert_line(black_box(90), black_box(10), black_box(230), black_box(0xffff00ff))) b.iter(|| dest.vert_line(black_box(90), black_box(10), black_box(230), black_box(SOLID_COLOR)))
}); });
c.bench_function("rgbabitmap_primitives_blended_vert_line", |b| { c.bench_function("rgbabitmap_primitives_blended_vert_line", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| { b.iter(|| {
dest.blended_vert_line( dest.blended_vert_line(
black_box(90), black_box(90),
black_box(10), black_box(10),
black_box(230), black_box(230),
black_box(0x7fff00ff), black_box(BLEND_COLOR),
black_box(BlendFunction::Blend), black_box(BlendFunction::Blend),
) )
}) })
}); });
c.bench_function("rgbabitmap_primitives_rect", |b| { c.bench_function("rgbabitmap_primitives_rect", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| dest.rect(black_box(10), black_box(10), black_box(310), black_box(230), black_box(0xffff00ff))) b.iter(|| dest.rect(black_box(10), black_box(10), black_box(310), black_box(230), black_box(SOLID_COLOR)))
}); });
c.bench_function("rgbabitmap_primitives_blended_rect", |b| { c.bench_function("rgbabitmap_primitives_blended_rect", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| { b.iter(|| {
dest.blended_rect( dest.blended_rect(
black_box(10), black_box(10),
black_box(10), black_box(10),
black_box(310), black_box(310),
black_box(230), black_box(230),
black_box(0x7fff00ff), black_box(BLEND_COLOR),
black_box(BlendFunction::Blend), black_box(BlendFunction::Blend),
) )
}) })
}); });
c.bench_function("rgbabitmap_primitives_filled_rect", |b| { c.bench_function("rgbabitmap_primitives_filled_rect", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| dest.filled_rect(black_box(10), black_box(10), black_box(310), black_box(230), black_box(0xffff00ff))) b.iter(|| {
dest.filled_rect(black_box(10), black_box(10), black_box(310), black_box(230), black_box(SOLID_COLOR))
})
}); });
c.bench_function("rgbabitmap_primitives_blended_filled_rect", |b| { c.bench_function("rgbabitmap_primitives_blended_filled_rect", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| { b.iter(|| {
dest.blended_filled_rect( dest.blended_filled_rect(
black_box(10), black_box(10),
black_box(10), black_box(10),
black_box(310), black_box(310),
black_box(230), black_box(230),
black_box(0x7fff00ff), black_box(BLEND_COLOR),
black_box(BlendFunction::Blend), black_box(BlendFunction::Blend),
) )
}) })
}); });
c.bench_function("rgbabitmap_primitives_circle", |b| { c.bench_function("rgbabitmap_primitives_circle", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| dest.circle(black_box(160), black_box(120), black_box(80), black_box(0xffff00ff))) b.iter(|| dest.circle(black_box(160), black_box(120), black_box(80), black_box(SOLID_COLOR)))
}); });
c.bench_function("rgbabitmap_primitives_filled_circle", |b| { c.bench_function("rgbabitmap_primitives_filled_circle", |b| {
dest.clear(0xff000000); dest.clear(BG_COLOR);
b.iter(|| dest.filled_circle(black_box(160), black_box(120), black_box(80), black_box(0xffff00ff))) b.iter(|| dest.filled_circle(black_box(160), black_box(120), black_box(80), black_box(SOLID_COLOR)))
}); });
} }

View file

@ -22,19 +22,20 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let texcoord_0_1 = Vector2::new(0.0, 1.0); let texcoord_0_1 = Vector2::new(0.0, 1.0);
let texcoord_1_1 = Vector2::new(1.0, 1.0); let texcoord_1_1 = Vector2::new(1.0, 1.0);
let color_1 = to_argb32([255, 255, 0, 0]); let color = ARGBu8x4::from_rgb([255, 255, 255]);
let color_2 = to_argb32([255, 0, 255, 0]); let color_1 = ARGBu8x4::from_argb([255, 255, 0, 0]);
let color_3 = to_argb32([255, 0, 0, 255]); let color_2 = ARGBu8x4::from_argb([255, 0, 255, 0]);
let color_3 = ARGBu8x4::from_argb([255, 0, 0, 255]);
c.bench_function("rgbabitmap_triangle_2d_solid_color", |b| { c.bench_function("rgbabitmap_triangle_2d_solid_color", |b| {
let triangle = RgbaTriangle2d::Solid { position: [big_v1, big_v2, big_v3], color: 5 }; let triangle = RgbaTriangle2d::Solid { position: [big_v1, big_v2, big_v3], color };
b.iter(|| { b.iter(|| {
dest.triangle_2d(black_box(&triangle)); dest.triangle_2d(black_box(&triangle));
}) })
}); });
c.bench_function("rgbabitmap_triangle_2d_solid_color_small", |b| { c.bench_function("rgbabitmap_triangle_2d_solid_color_small", |b| {
let triangle = RgbaTriangle2d::Solid { position: [small_v1, small_v2, small_v3], color: 5 }; let triangle = RgbaTriangle2d::Solid { position: [small_v1, small_v2, small_v3], color };
b.iter(|| { b.iter(|| {
dest.triangle_2d(black_box(&triangle)); dest.triangle_2d(black_box(&triangle));
}) })

View file

@ -7,7 +7,7 @@
//! Only a subset of the most common Bitmap drawing operations will be provided here. //! Only a subset of the most common Bitmap drawing operations will be provided here.
use crate::graphics::{ use crate::graphics::{
BitmapError, Font, FontRenderOpts, IndexedBitmap, IndexedBlitMethod, Pixel, RgbaBitmap, RgbaBlitMethod, ARGBu8x4, BitmapError, Font, FontRenderOpts, IndexedBitmap, IndexedBlitMethod, Pixel, RgbaBitmap, RgbaBlitMethod,
}; };
use crate::math::Rect; use crate::math::Rect;
@ -220,7 +220,7 @@ impl GeneralBitmap for IndexedBitmap {
} }
impl GeneralBitmap for RgbaBitmap { impl GeneralBitmap for RgbaBitmap {
type PixelType = u32; type PixelType = ARGBu8x4;
#[inline] #[inline]
fn new(width: u32, height: u32) -> Result<Self, BitmapError> { fn new(width: u32, height: u32) -> Result<Self, BitmapError> {

View file

@ -1,6 +1,6 @@
use std::path::Path; use std::path::Path;
use crate::graphics::{Bitmap, BitmapError, Palette, RgbaBitmap}; use crate::graphics::{ARGBu8x4, Bitmap, BitmapError, Palette, RgbaBitmap};
mod blit; mod blit;
mod primitives; mod primitives;
@ -51,7 +51,7 @@ impl IndexedBitmap {
/// ///
/// * `dest`: destination 32-bit ARGB pixel buffer to copy converted pixels to /// * `dest`: destination 32-bit ARGB pixel buffer to copy converted pixels to
/// * `palette`: the 256 colour palette to use during pixel conversion /// * `palette`: the 256 colour palette to use during pixel conversion
pub fn copy_as_argb_to(&self, dest: &mut [u32], palette: &Palette) { pub fn copy_as_argb_to(&self, dest: &mut [ARGBu8x4], palette: &Palette) {
for (src, dest) in self.pixels().iter().zip(dest.iter_mut()) { for (src, dest) in self.pixels().iter().zip(dest.iter_mut()) {
*dest = palette[*src]; *dest = palette[*src];
} }

View file

@ -5,7 +5,7 @@ use std::path::Path;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use thiserror::Error; use thiserror::Error;
use crate::graphics::{from_rgb32, IndexedBitmap, Palette, PaletteError, PaletteFormat, RgbaBitmap}; use crate::graphics::{IndexedBitmap, Palette, PaletteError, PaletteFormat, RgbaBitmap};
use crate::utils::ReadFixedLengthByteArray; use crate::utils::ReadFixedLengthByteArray;
#[derive(Error, Debug)] #[derive(Error, Debug)]
@ -241,11 +241,10 @@ impl IndexedBitmap {
writer.write_u8(0xc)?; writer.write_u8(0xc)?;
for i in 0..=255 { for i in 0..=255 {
let argb = palette[i]; let color = palette[i];
let [r, g, b] = from_rgb32(argb); writer.write_u8(color.r())?;
writer.write_u8(r)?; writer.write_u8(color.g())?;
writer.write_u8(g)?; writer.write_u8(color.b())?;
writer.write_u8(b)?;
} }
Ok(()) Ok(())

View file

@ -7,10 +7,7 @@ use std::path::Path;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use thiserror::Error; use thiserror::Error;
use crate::graphics::{ use crate::graphics::{ARGBu8x4, Bitmap, IndexedBitmap, Palette, PaletteError, PaletteFormat, Pixel, RgbaBitmap};
from_argb32, from_rgb32, to_argb32, to_rgb32, Bitmap, IndexedBitmap, Palette, PaletteError, PaletteFormat, Pixel,
RgbaBitmap,
};
use crate::utils::ReadFixedLengthByteArray; use crate::utils::ReadFixedLengthByteArray;
const PNG_HEADER: [u8; 8] = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]; const PNG_HEADER: [u8; 8] = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
@ -322,8 +319,8 @@ impl ScanlinePixelConverter<u8> for ScanlineBuffer {
} }
} }
impl ScanlinePixelConverter<u32> for ScanlineBuffer { impl ScanlinePixelConverter<ARGBu8x4> for ScanlineBuffer {
fn read_pixel(&mut self, x: usize, palette: &Option<Palette>) -> Result<u32, PngError> { fn read_pixel(&mut self, x: usize, palette: &Option<Palette>) -> Result<ARGBu8x4, PngError> {
let offset = x * self.bpp; let offset = x * self.bpp;
match self.format { match self.format {
ColorFormat::IndexedColor => { ColorFormat::IndexedColor => {
@ -340,35 +337,33 @@ impl ScanlinePixelConverter<u32> for ScanlineBuffer {
let r = self.current[offset]; let r = self.current[offset];
let g = self.current[offset + 1]; let g = self.current[offset + 1];
let b = self.current[offset + 2]; let b = self.current[offset + 2];
Ok(to_rgb32([r, g, b])) Ok(ARGBu8x4::from_rgb([r, g, b]))
} }
ColorFormat::RGBA => { ColorFormat::RGBA => {
let r = self.current[offset]; let r = self.current[offset];
let g = self.current[offset + 1]; let g = self.current[offset + 1];
let b = self.current[offset + 2]; let b = self.current[offset + 2];
let a = self.current[offset + 3]; let a = self.current[offset + 3];
Ok(to_argb32([a, r, g, b])) Ok(ARGBu8x4::from_argb([a, r, g, b]))
} }
_ => Err(PngError::BadFile(format!("Unsupported color format for this PixelReader: {:?}", self.format))), _ => Err(PngError::BadFile(format!("Unsupported color format for this PixelReader: {:?}", self.format))),
} }
} }
fn write_pixel(&mut self, x: usize, pixel: u32) -> Result<(), PngError> { fn write_pixel(&mut self, x: usize, pixel: ARGBu8x4) -> Result<(), PngError> {
let offset = x * self.bpp; let offset = x * self.bpp;
match self.format { match self.format {
ColorFormat::RGB => { ColorFormat::RGB => {
let [r, g, b] = from_rgb32(pixel); self.current[offset] = pixel.r();
self.current[offset] = r; self.current[offset + 1] = pixel.g();
self.current[offset + 1] = g; self.current[offset + 2] = pixel.b();
self.current[offset + 2] = b;
Ok(()) Ok(())
} }
ColorFormat::RGBA => { ColorFormat::RGBA => {
let [a, r, g, b] = from_argb32(pixel); self.current[offset] = pixel.r();
self.current[offset] = r; self.current[offset + 1] = pixel.g();
self.current[offset + 1] = g; self.current[offset + 2] = pixel.b();
self.current[offset + 2] = b; self.current[offset + 3] = pixel.a();
self.current[offset + 3] = a;
Ok(()) Ok(())
} }
_ => Err(PngError::BadFile(format!("Unsupported color format for this PixelReader: {:?}", self.format))), _ => Err(PngError::BadFile(format!("Unsupported color format for this PixelReader: {:?}", self.format))),

View file

@ -1,6 +1,6 @@
use crate::graphics::{ use crate::graphics::{
clip_blit, per_pixel_blit, per_pixel_flipped_blit, per_pixel_rotozoom_blit, tint_argb32, BitmapAtlas, clip_blit, per_pixel_blit, per_pixel_flipped_blit, per_pixel_rotozoom_blit, ARGBu8x4, BitmapAtlas, BlendFunction,
BlendFunction, RgbaBitmap, RgbaBitmap,
}; };
use crate::math::Rect; use crate::math::Rect;
@ -8,7 +8,7 @@ use crate::math::Rect;
pub enum RgbaBlitMethod { pub enum RgbaBlitMethod {
/// Solid blit, no transparency or other per-pixel adjustments. /// Solid blit, no transparency or other per-pixel adjustments.
Solid, Solid,
SolidTinted(u32), SolidTinted(ARGBu8x4),
SolidBlended(BlendFunction), SolidBlended(BlendFunction),
/// Same as [RgbaBlitMethod::Solid] but the drawn image can also be flipped horizontally /// Same as [RgbaBlitMethod::Solid] but the drawn image can also be flipped horizontally
/// and/or vertically. /// and/or vertically.
@ -19,7 +19,7 @@ pub enum RgbaBlitMethod {
SolidFlippedTinted { SolidFlippedTinted {
horizontal_flip: bool, horizontal_flip: bool,
vertical_flip: bool, vertical_flip: bool,
tint_color: u32, tint_color: ARGBu8x4,
}, },
SolidFlippedBlended { SolidFlippedBlended {
horizontal_flip: bool, horizontal_flip: bool,
@ -27,30 +27,30 @@ pub enum RgbaBlitMethod {
blend: BlendFunction, blend: BlendFunction,
}, },
/// Transparent blit, the specified source color pixels are skipped. /// Transparent blit, the specified source color pixels are skipped.
Transparent(u32), Transparent(ARGBu8x4),
TransparentTinted { TransparentTinted {
transparent_color: u32, transparent_color: ARGBu8x4,
tint_color: u32, tint_color: ARGBu8x4,
}, },
TransparentBlended { TransparentBlended {
transparent_color: u32, transparent_color: ARGBu8x4,
blend: BlendFunction, blend: BlendFunction,
}, },
/// Same as [RgbaBlitMethod::Transparent] but the drawn image can also be flipped horizontally /// Same as [RgbaBlitMethod::Transparent] but the drawn image can also be flipped horizontally
/// and/or vertically. /// and/or vertically.
TransparentFlipped { TransparentFlipped {
transparent_color: u32, transparent_color: ARGBu8x4,
horizontal_flip: bool, horizontal_flip: bool,
vertical_flip: bool, vertical_flip: bool,
}, },
TransparentFlippedTinted { TransparentFlippedTinted {
transparent_color: u32, transparent_color: ARGBu8x4,
horizontal_flip: bool, horizontal_flip: bool,
vertical_flip: bool, vertical_flip: bool,
tint_color: u32, tint_color: ARGBu8x4,
}, },
TransparentFlippedBlended { TransparentFlippedBlended {
transparent_color: u32, transparent_color: ARGBu8x4,
horizontal_flip: bool, horizontal_flip: bool,
vertical_flip: bool, vertical_flip: bool,
blend: BlendFunction, blend: BlendFunction,
@ -58,15 +58,15 @@ pub enum RgbaBlitMethod {
/// Same as [RgbaBlitMethod::Transparent] except that the visible pixels on the destination are all /// Same as [RgbaBlitMethod::Transparent] except that the visible pixels on the destination are all
/// drawn using the same color. /// drawn using the same color.
TransparentSingle { TransparentSingle {
transparent_color: u32, transparent_color: ARGBu8x4,
draw_color: u32, draw_color: ARGBu8x4,
}, },
/// Combination of [RgbaBlitMethod::TransparentFlipped] and [RgbaBlitMethod::TransparentSingle]. /// Combination of [RgbaBlitMethod::TransparentFlipped] and [RgbaBlitMethod::TransparentSingle].
TransparentFlippedSingle { TransparentFlippedSingle {
transparent_color: u32, transparent_color: ARGBu8x4,
horizontal_flip: bool, horizontal_flip: bool,
vertical_flip: bool, vertical_flip: bool,
draw_color: u32, draw_color: ARGBu8x4,
}, },
/// Rotozoom blit, works the same as [RgbaBlitMethod::Solid] except that rotation and scaling is /// Rotozoom blit, works the same as [RgbaBlitMethod::Solid] except that rotation and scaling is
/// performed. /// performed.
@ -79,7 +79,7 @@ pub enum RgbaBlitMethod {
angle: f32, angle: f32,
scale_x: f32, scale_x: f32,
scale_y: f32, scale_y: f32,
tint_color: u32, tint_color: ARGBu8x4,
}, },
RotoZoomBlended { RotoZoomBlended {
angle: f32, angle: f32,
@ -92,20 +92,20 @@ pub enum RgbaBlitMethod {
angle: f32, angle: f32,
scale_x: f32, scale_x: f32,
scale_y: f32, scale_y: f32,
transparent_color: u32, transparent_color: ARGBu8x4,
}, },
RotoZoomTransparentTinted { RotoZoomTransparentTinted {
angle: f32, angle: f32,
scale_x: f32, scale_x: f32,
scale_y: f32, scale_y: f32,
transparent_color: u32, transparent_color: ARGBu8x4,
tint_color: u32, tint_color: ARGBu8x4,
}, },
RotoZoomTransparentBlended { RotoZoomTransparentBlended {
angle: f32, angle: f32,
scale_x: f32, scale_x: f32,
scale_y: f32, scale_y: f32,
transparent_color: u32, transparent_color: ARGBu8x4,
blend: BlendFunction, blend: BlendFunction,
}, },
} }
@ -117,7 +117,7 @@ impl RgbaBitmap {
src_region: &Rect, src_region: &Rect,
dest_x: i32, dest_x: i32,
dest_y: i32, dest_y: i32,
tint_color: u32, tint_color: ARGBu8x4,
) { ) {
per_pixel_blit( per_pixel_blit(
self, // self, //
@ -126,7 +126,7 @@ impl RgbaBitmap {
dest_x, dest_x,
dest_y, dest_y,
|src_pixels, dest_pixels| { |src_pixels, dest_pixels| {
*dest_pixels = tint_argb32(*src_pixels, tint_color); *dest_pixels = (*src_pixels).tint(tint_color);
}, },
); );
} }
@ -146,7 +146,7 @@ impl RgbaBitmap {
dest_x, dest_x,
dest_y, dest_y,
|src_pixels, dest_pixels| { |src_pixels, dest_pixels| {
*dest_pixels = blend.blend_1u32(*src_pixels, *dest_pixels); *dest_pixels = blend.blend(*src_pixels, *dest_pixels);
}, },
); );
} }
@ -170,7 +170,7 @@ impl RgbaBitmap {
horizontal_flip, horizontal_flip,
vertical_flip, vertical_flip,
|src_pixels, dest_pixels| { |src_pixels, dest_pixels| {
*dest_pixels = blend.blend_1u32(*src_pixels, *dest_pixels); *dest_pixels = blend.blend(*src_pixels, *dest_pixels);
}, },
); );
} }
@ -183,7 +183,7 @@ impl RgbaBitmap {
dest_y: i32, dest_y: i32,
horizontal_flip: bool, horizontal_flip: bool,
vertical_flip: bool, vertical_flip: bool,
tint_color: u32, tint_color: ARGBu8x4,
) { ) {
per_pixel_flipped_blit( per_pixel_flipped_blit(
self, // self, //
@ -194,7 +194,7 @@ impl RgbaBitmap {
horizontal_flip, horizontal_flip,
vertical_flip, vertical_flip,
|src_pixels, dest_pixels| { |src_pixels, dest_pixels| {
*dest_pixels = tint_argb32(*src_pixels, tint_color); *dest_pixels = (*src_pixels).tint(tint_color);
}, },
); );
} }
@ -205,8 +205,8 @@ impl RgbaBitmap {
src_region: &Rect, src_region: &Rect,
dest_x: i32, dest_x: i32,
dest_y: i32, dest_y: i32,
transparent_color: u32, transparent_color: ARGBu8x4,
tint_color: u32, tint_color: ARGBu8x4,
) { ) {
per_pixel_blit( per_pixel_blit(
self, // self, //
@ -216,7 +216,7 @@ impl RgbaBitmap {
dest_y, dest_y,
|src_pixels, dest_pixels| { |src_pixels, dest_pixels| {
if *src_pixels != transparent_color { if *src_pixels != transparent_color {
*dest_pixels = tint_argb32(*src_pixels, tint_color); *dest_pixels = (*src_pixels).tint(tint_color);
} }
}, },
); );
@ -228,7 +228,7 @@ impl RgbaBitmap {
src_region: &Rect, src_region: &Rect,
dest_x: i32, dest_x: i32,
dest_y: i32, dest_y: i32,
transparent_color: u32, transparent_color: ARGBu8x4,
blend: BlendFunction, blend: BlendFunction,
) { ) {
per_pixel_blit( per_pixel_blit(
@ -239,7 +239,7 @@ impl RgbaBitmap {
dest_y, dest_y,
|src_pixels, dest_pixels| { |src_pixels, dest_pixels| {
if *src_pixels != transparent_color { if *src_pixels != transparent_color {
*dest_pixels = blend.blend_1u32(*src_pixels, *dest_pixels); *dest_pixels = blend.blend(*src_pixels, *dest_pixels);
} }
}, },
); );
@ -251,10 +251,10 @@ impl RgbaBitmap {
src_region: &Rect, src_region: &Rect,
dest_x: i32, dest_x: i32,
dest_y: i32, dest_y: i32,
transparent_color: u32, transparent_color: ARGBu8x4,
horizontal_flip: bool, horizontal_flip: bool,
vertical_flip: bool, vertical_flip: bool,
tint_color: u32, tint_color: ARGBu8x4,
) { ) {
per_pixel_flipped_blit( per_pixel_flipped_blit(
self, // self, //
@ -266,7 +266,7 @@ impl RgbaBitmap {
vertical_flip, vertical_flip,
|src_pixels, dest_pixels| { |src_pixels, dest_pixels| {
if *src_pixels != transparent_color { if *src_pixels != transparent_color {
*dest_pixels = tint_argb32(*src_pixels, tint_color); *dest_pixels = (*src_pixels).tint(tint_color);
} }
}, },
); );
@ -278,7 +278,7 @@ impl RgbaBitmap {
src_region: &Rect, src_region: &Rect,
dest_x: i32, dest_x: i32,
dest_y: i32, dest_y: i32,
transparent_color: u32, transparent_color: ARGBu8x4,
horizontal_flip: bool, horizontal_flip: bool,
vertical_flip: bool, vertical_flip: bool,
blend: BlendFunction, blend: BlendFunction,
@ -293,7 +293,7 @@ impl RgbaBitmap {
vertical_flip, vertical_flip,
|src_pixels, dest_pixels| { |src_pixels, dest_pixels| {
if *src_pixels != transparent_color { if *src_pixels != transparent_color {
*dest_pixels = blend.blend_1u32(*src_pixels, *dest_pixels); *dest_pixels = blend.blend(*src_pixels, *dest_pixels);
} }
}, },
); );
@ -308,7 +308,7 @@ impl RgbaBitmap {
angle: f32, angle: f32,
scale_x: f32, scale_x: f32,
scale_y: f32, scale_y: f32,
tint_color: u32, tint_color: ARGBu8x4,
) { ) {
per_pixel_rotozoom_blit( per_pixel_rotozoom_blit(
self, // self, //
@ -320,7 +320,7 @@ impl RgbaBitmap {
scale_x, scale_x,
scale_y, scale_y,
|src_pixel, dest_bitmap, draw_x, draw_y| { |src_pixel, dest_bitmap, draw_x, draw_y| {
dest_bitmap.set_pixel(draw_x, draw_y, tint_argb32(src_pixel, tint_color)); dest_bitmap.set_pixel(draw_x, draw_y, src_pixel.tint(tint_color));
}, },
); );
} }
@ -347,7 +347,7 @@ impl RgbaBitmap {
scale_y, scale_y,
|src_pixel, dest_bitmap, draw_x, draw_y| { |src_pixel, dest_bitmap, draw_x, draw_y| {
if let Some(dest_pixel) = dest_bitmap.get_pixel(draw_x, draw_y) { if let Some(dest_pixel) = dest_bitmap.get_pixel(draw_x, draw_y) {
dest_bitmap.set_pixel(draw_x, draw_y, blend.blend_1u32(src_pixel, dest_pixel)) dest_bitmap.set_pixel(draw_x, draw_y, blend.blend(src_pixel, dest_pixel))
} }
}, },
); );
@ -362,8 +362,8 @@ impl RgbaBitmap {
angle: f32, angle: f32,
scale_x: f32, scale_x: f32,
scale_y: f32, scale_y: f32,
transparent_color: u32, transparent_color: ARGBu8x4,
tint_color: u32, tint_color: ARGBu8x4,
) { ) {
per_pixel_rotozoom_blit( per_pixel_rotozoom_blit(
self, // self, //
@ -376,7 +376,7 @@ impl RgbaBitmap {
scale_y, scale_y,
|src_pixel, dest_bitmap, draw_x, draw_y| { |src_pixel, dest_bitmap, draw_x, draw_y| {
if transparent_color != src_pixel { if transparent_color != src_pixel {
dest_bitmap.set_pixel(draw_x, draw_y, tint_argb32(src_pixel, tint_color)); dest_bitmap.set_pixel(draw_x, draw_y, src_pixel.tint(tint_color));
} }
}, },
); );
@ -391,7 +391,7 @@ impl RgbaBitmap {
angle: f32, angle: f32,
scale_x: f32, scale_x: f32,
scale_y: f32, scale_y: f32,
transparent_color: u32, transparent_color: ARGBu8x4,
blend: BlendFunction, blend: BlendFunction,
) { ) {
per_pixel_rotozoom_blit( per_pixel_rotozoom_blit(
@ -406,7 +406,7 @@ impl RgbaBitmap {
|src_pixel, dest_bitmap, draw_x, draw_y| { |src_pixel, dest_bitmap, draw_x, draw_y| {
if transparent_color != src_pixel { if transparent_color != src_pixel {
if let Some(dest_pixel) = dest_bitmap.get_pixel(draw_x, draw_y) { if let Some(dest_pixel) = dest_bitmap.get_pixel(draw_x, draw_y) {
dest_bitmap.set_pixel(draw_x, draw_y, blend.blend_1u32(src_pixel, dest_pixel)) dest_bitmap.set_pixel(draw_x, draw_y, blend.blend(src_pixel, dest_pixel))
} }
} }
}, },

View file

@ -1,7 +1,7 @@
use byteorder::ReadBytesExt; use byteorder::ReadBytesExt;
use std::path::Path; use std::path::Path;
use crate::graphics::{to_argb32, to_rgb32, Bitmap, BitmapError, Palette}; use crate::graphics::{ARGBu8x4, Bitmap, BitmapError, Palette};
mod blit; mod blit;
mod primitives; mod primitives;
@ -11,7 +11,7 @@ pub use blit::*;
pub use primitives::*; pub use primitives::*;
pub use triangles::*; pub use triangles::*;
pub type RgbaBitmap = Bitmap<u32>; pub type RgbaBitmap = Bitmap<ARGBu8x4>;
#[derive(Debug, Copy, Clone, Eq, PartialEq)] #[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum RgbaPixelFormat { pub enum RgbaPixelFormat {
@ -29,7 +29,7 @@ impl RgbaBitmap {
/// ///
/// returns: `Result<Bitmap, BitmapError>` /// returns: `Result<Bitmap, BitmapError>`
pub fn new(width: u32, height: u32) -> Result<Self, BitmapError> { pub fn new(width: u32, height: u32) -> Result<Self, BitmapError> {
Self::internal_new(width, height, to_rgb32([0, 0, 0])) Self::internal_new(width, height, ARGBu8x4::from_rgb([0, 0, 0]))
} }
pub fn from_bytes<T: ReadBytesExt>( pub fn from_bytes<T: ReadBytesExt>(
@ -38,7 +38,7 @@ impl RgbaBitmap {
format: RgbaPixelFormat, format: RgbaPixelFormat,
reader: &mut T, reader: &mut T,
) -> Result<Self, BitmapError> { ) -> Result<Self, BitmapError> {
let mut bitmap = Self::internal_new(width, height, 0)?; let mut bitmap = Self::internal_new(width, height, ARGBu8x4::from_rgb([0, 0, 0]))?;
for pixel in bitmap.pixels_mut().iter_mut() { for pixel in bitmap.pixels_mut().iter_mut() {
*pixel = match format { *pixel = match format {
RgbaPixelFormat::RGBA => { RgbaPixelFormat::RGBA => {
@ -46,14 +46,14 @@ impl RgbaBitmap {
let g = reader.read_u8()?; let g = reader.read_u8()?;
let b = reader.read_u8()?; let b = reader.read_u8()?;
let a = reader.read_u8()?; let a = reader.read_u8()?;
to_argb32([a, r, g, b]) ARGBu8x4::from_argb([a, r, g, b])
} }
RgbaPixelFormat::ARGB => { RgbaPixelFormat::ARGB => {
let a = reader.read_u8()?; let a = reader.read_u8()?;
let r = reader.read_u8()?; let r = reader.read_u8()?;
let g = reader.read_u8()?; let g = reader.read_u8()?;
let b = reader.read_u8()?; let b = reader.read_u8()?;
to_argb32([a, r, g, b]) ARGBu8x4::from_argb([a, r, g, b])
} }
}; };
} }

View file

@ -1,14 +1,14 @@
use crate::graphics::{BlendFunction, RgbaBitmap}; use crate::graphics::{ARGBu8x4, BlendFunction, RgbaBitmap};
impl RgbaBitmap { impl RgbaBitmap {
/// Sets the pixel at the given coordinates using a blended color via the specified blend function /// Sets the pixel at the given coordinates using a blended color via the specified blend function
/// If the coordinates lie outside of the bitmaps clipping region, no pixels will be changed. /// If the 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: u32, blend: BlendFunction) { pub fn set_blended_pixel(&mut self, x: i32, y: i32, color: ARGBu8x4, blend: BlendFunction) {
self.set_custom_pixel( self.set_custom_pixel(
x, // x, //
y, y,
|dest_color| blend.blend_1u32(color, dest_color), |dest_color| blend.blend(color, dest_color),
); );
} }
@ -16,47 +16,47 @@ impl RgbaBitmap {
/// The coordinates are not checked for validity, so it is up to you to ensure they lie within the /// The coordinates are not checked for validity, so it is up to you to ensure they lie within the
/// bounds of the bitmap. /// bounds of the bitmap.
#[inline] #[inline]
pub unsafe fn set_blended_pixel_unchecked(&mut self, x: i32, y: i32, color: u32, blend: BlendFunction) { pub unsafe fn set_blended_pixel_unchecked(&mut self, x: i32, y: i32, color: ARGBu8x4, blend: BlendFunction) {
self.set_custom_pixel_unchecked( self.set_custom_pixel_unchecked(
x, // x, //
y, y,
|dest_color| blend.blend_1u32(color, dest_color), |dest_color| blend.blend(color, dest_color),
); );
} }
/// Draws a line from x1,y1 to x2,y2 by blending the drawn pixels using the given blend function. /// Draws a line from x1,y1 to x2,y2 by blending the drawn pixels using the given blend function.
#[inline] #[inline]
pub fn blended_line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: u32, blend: BlendFunction) { pub fn blended_line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: ARGBu8x4, blend: BlendFunction) {
self.line_custom( self.line_custom(
x1, // x1, //
y1, y1,
x2, x2,
y2, y2,
|dest_color| blend.blend_1u32(color, dest_color), |dest_color| blend.blend(color, dest_color),
); );
} }
/// Draws a horizontal line from x1,y to x2,y by blending the drawn pixels using the given /// Draws a horizontal line from x1,y to x2,y by blending the drawn pixels using the given
/// blend function. /// blend function.
#[inline] #[inline]
pub fn blended_horiz_line(&mut self, x1: i32, x2: i32, y: i32, color: u32, blend: BlendFunction) { pub fn blended_horiz_line(&mut self, x1: i32, x2: i32, y: i32, color: ARGBu8x4, blend: BlendFunction) {
self.horiz_line_custom( self.horiz_line_custom(
x1, // x1, //
x2, x2,
y, y,
|dest_color| blend.blend_1u32(color, dest_color), |dest_color| blend.blend(color, dest_color),
); );
} }
/// Draws a vertical line from x,y1 to x,y2 by blending the drawn pixels using the given blend /// Draws a vertical line from x,y1 to x,y2 by blending the drawn pixels using the given blend
/// function. /// function.
#[inline] #[inline]
pub fn blended_vert_line(&mut self, x: i32, y1: i32, y2: i32, color: u32, blend: BlendFunction) { pub fn blended_vert_line(&mut self, x: i32, y1: i32, y2: i32, color: ARGBu8x4, blend: BlendFunction) {
self.vert_line_custom( self.vert_line_custom(
x, // x, //
y1, y1,
y2, y2,
|dest_color| blend.blend_1u32(color, dest_color), |dest_color| blend.blend(color, dest_color),
); );
} }
@ -64,13 +64,13 @@ impl RgbaBitmap {
/// 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 function. /// The box is drawn by blending the drawn pixels using the given blend function.
#[inline] #[inline]
pub fn blended_rect(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: u32, blend: BlendFunction) { pub fn blended_rect(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: ARGBu8x4, blend: BlendFunction) {
self.rect_custom( self.rect_custom(
x1, // x1, //
y1, y1,
x2, x2,
y2, y2,
|dest_color| blend.blend_1u32(color, dest_color), |dest_color| blend.blend(color, dest_color),
); );
} }
@ -78,13 +78,13 @@ impl RgbaBitmap {
/// drawn, assuming they are specifying the top-left and bottom-right corners respectively. The /// drawn, assuming they are specifying the top-left and bottom-right corners respectively. The
/// filled box is draw by blending the drawn pixels using the given blend function. /// filled box is draw by blending the drawn pixels using the given blend function.
#[inline] #[inline]
pub fn blended_filled_rect(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: u32, blend: BlendFunction) { pub fn blended_filled_rect(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, color: ARGBu8x4, blend: BlendFunction) {
self.filled_rect_custom( self.filled_rect_custom(
x1, // x1, //
y1, y1,
x2, x2,
y2, y2,
|dest_color| blend.blend_1u32(color, dest_color), |dest_color| blend.blend(color, dest_color),
); );
} }
} }

View file

@ -1,29 +1,26 @@
use std::simd; use std::simd;
use crate::graphics::{ use crate::graphics::{edge_function, per_pixel_triangle_2d, ARGBu8x4, BlendFunction, RgbaBitmap};
edge_function, from_argb32_simd, from_rgb32_simd, multiply_argb_simd, per_pixel_triangle_2d, tint_argb_simd,
to_argb32_simd, to_rgb32_simd, BlendFunction, RgbaBitmap,
};
use crate::math::Vector2; use crate::math::Vector2;
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
pub enum RgbaTriangle2d<'a> { pub enum RgbaTriangle2d<'a> {
Solid { Solid {
position: [Vector2; 3], // position: [Vector2; 3], //
color: u32, color: ARGBu8x4,
}, },
SolidBlended { SolidBlended {
position: [Vector2; 3], // position: [Vector2; 3], //
color: u32, color: ARGBu8x4,
blend: BlendFunction, blend: BlendFunction,
}, },
SolidMultiColor { SolidMultiColor {
position: [Vector2; 3], // position: [Vector2; 3], //
color: [u32; 3], color: [ARGBu8x4; 3],
}, },
SolidMultiColorBlended { SolidMultiColorBlended {
position: [Vector2; 3], // position: [Vector2; 3], //
color: [u32; 3], color: [ARGBu8x4; 3],
blend: BlendFunction, blend: BlendFunction,
}, },
SolidTextured { SolidTextured {
@ -34,26 +31,26 @@ pub enum RgbaTriangle2d<'a> {
SolidTexturedColored { SolidTexturedColored {
position: [Vector2; 3], // position: [Vector2; 3], //
texcoord: [Vector2; 3], texcoord: [Vector2; 3],
color: u32, color: ARGBu8x4,
bitmap: &'a RgbaBitmap, bitmap: &'a RgbaBitmap,
}, },
SolidTexturedColoredBlended { SolidTexturedColoredBlended {
position: [Vector2; 3], // position: [Vector2; 3], //
texcoord: [Vector2; 3], texcoord: [Vector2; 3],
color: u32, color: ARGBu8x4,
bitmap: &'a RgbaBitmap, bitmap: &'a RgbaBitmap,
blend: BlendFunction, blend: BlendFunction,
}, },
SolidTexturedMultiColored { SolidTexturedMultiColored {
position: [Vector2; 3], // position: [Vector2; 3], //
texcoord: [Vector2; 3], texcoord: [Vector2; 3],
color: [u32; 3], color: [ARGBu8x4; 3],
bitmap: &'a RgbaBitmap, bitmap: &'a RgbaBitmap,
}, },
SolidTexturedMultiColoredBlended { SolidTexturedMultiColoredBlended {
position: [Vector2; 3], // position: [Vector2; 3], //
texcoord: [Vector2; 3], texcoord: [Vector2; 3],
color: [u32; 3], color: [ARGBu8x4; 3],
bitmap: &'a RgbaBitmap, bitmap: &'a RgbaBitmap,
blend: BlendFunction, blend: BlendFunction,
}, },
@ -61,7 +58,7 @@ pub enum RgbaTriangle2d<'a> {
position: [Vector2; 3], // position: [Vector2; 3], //
texcoord: [Vector2; 3], texcoord: [Vector2; 3],
bitmap: &'a RgbaBitmap, bitmap: &'a RgbaBitmap,
tint: u32, tint: ARGBu8x4,
}, },
SolidTexturedBlended { SolidTexturedBlended {
position: [Vector2; 3], // position: [Vector2; 3], //
@ -72,7 +69,7 @@ pub enum RgbaTriangle2d<'a> {
} }
impl RgbaBitmap { impl RgbaBitmap {
pub fn solid_triangle_2d(&mut self, positions: &[Vector2; 3], color: u32) { pub fn solid_triangle_2d(&mut self, positions: &[Vector2; 3], color: ARGBu8x4) {
per_pixel_triangle_2d( per_pixel_triangle_2d(
self, // self, //
positions[0], positions[0],
@ -82,24 +79,21 @@ impl RgbaBitmap {
) )
} }
pub fn solid_blended_triangle_2d(&mut self, positions: &[Vector2; 3], color: u32, blend: BlendFunction) { pub fn solid_blended_triangle_2d(&mut self, positions: &[Vector2; 3], color: ARGBu8x4, blend: BlendFunction) {
let color = from_argb32_simd(color);
per_pixel_triangle_2d( per_pixel_triangle_2d(
self, // self, //
positions[0], positions[0],
positions[1], positions[1],
positions[2], positions[2],
|dest_pixels, _w0, _w1, _w2| { |dest_pixels, _w0, _w1, _w2| *dest_pixels = blend.blend(color, *dest_pixels),
*dest_pixels = to_argb32_simd(blend.blend_simd(color, from_argb32_simd(*dest_pixels)))
},
) )
} }
pub fn solid_multicolor_triangle_2d(&mut self, positions: &[Vector2; 3], colors: &[u32; 3]) { pub fn solid_multicolor_triangle_2d(&mut self, positions: &[Vector2; 3], colors: &[ARGBu8x4; 3]) {
let area = simd::f32x4::splat(edge_function(positions[0], positions[1], positions[2])); let area = simd::f32x4::splat(edge_function(positions[0], positions[1], positions[2]));
let color1 = from_rgb32_simd(colors[0]).cast(); let color1 = colors[0].0.cast();
let color2 = from_rgb32_simd(colors[1]).cast(); let color2 = colors[1].0.cast();
let color3 = from_rgb32_simd(colors[2]).cast(); let color3 = colors[2].0.cast();
per_pixel_triangle_2d( per_pixel_triangle_2d(
self, // self, //
positions[0], positions[0],
@ -111,7 +105,7 @@ impl RgbaBitmap {
+ simd::f32x4::splat(w2) * color3) + simd::f32x4::splat(w2) * color3)
/ area) / area)
.cast(); .cast();
*dest_pixels = to_rgb32_simd(color) *dest_pixels = ARGBu8x4(color)
}, },
) )
} }
@ -119,13 +113,13 @@ impl RgbaBitmap {
pub fn solid_multicolor_blended_triangle_2d( pub fn solid_multicolor_blended_triangle_2d(
&mut self, &mut self,
positions: &[Vector2; 3], positions: &[Vector2; 3],
colors: &[u32; 3], colors: &[ARGBu8x4; 3],
blend: BlendFunction, blend: BlendFunction,
) { ) {
let area = simd::f32x4::splat(edge_function(positions[0], positions[1], positions[2])); let area = simd::f32x4::splat(edge_function(positions[0], positions[1], positions[2]));
let color1 = from_argb32_simd(colors[0]).cast(); let color1 = colors[0].0.cast();
let color2 = from_argb32_simd(colors[1]).cast(); let color2 = colors[1].0.cast();
let color3 = from_argb32_simd(colors[2]).cast(); let color3 = colors[2].0.cast();
per_pixel_triangle_2d( per_pixel_triangle_2d(
self, // self, //
positions[0], positions[0],
@ -137,7 +131,7 @@ impl RgbaBitmap {
+ simd::f32x4::splat(w2) * color3) + simd::f32x4::splat(w2) * color3)
/ area) / area)
.cast(); .cast();
*dest_pixels = to_argb32_simd(blend.blend_simd(color, from_argb32_simd(*dest_pixels))) *dest_pixels = blend.blend(ARGBu8x4(color), *dest_pixels)
}, },
) )
} }
@ -166,11 +160,10 @@ impl RgbaBitmap {
&mut self, &mut self,
positions: &[Vector2; 3], positions: &[Vector2; 3],
texcoords: &[Vector2; 3], texcoords: &[Vector2; 3],
color: u32, color: ARGBu8x4,
bitmap: &Self, bitmap: &Self,
) { ) {
let area = simd::f32x2::splat(edge_function(positions[0], positions[1], positions[2])); let area = simd::f32x2::splat(edge_function(positions[0], positions[1], positions[2]));
let color = from_argb32_simd(color);
let texcoord1 = simd::f32x2::from_array([texcoords[0].x, texcoords[0].y]); let texcoord1 = simd::f32x2::from_array([texcoords[0].x, texcoords[0].y]);
let texcoord2 = simd::f32x2::from_array([texcoords[1].x, texcoords[1].y]); let texcoord2 = simd::f32x2::from_array([texcoords[1].x, texcoords[1].y]);
let texcoord3 = simd::f32x2::from_array([texcoords[2].x, texcoords[2].y]); let texcoord3 = simd::f32x2::from_array([texcoords[2].x, texcoords[2].y]);
@ -184,8 +177,8 @@ impl RgbaBitmap {
+ simd::f32x2::splat(w1) * texcoord2 + simd::f32x2::splat(w1) * texcoord2
+ simd::f32x2::splat(w2) * texcoord3) + simd::f32x2::splat(w2) * texcoord3)
/ area; / area;
let texel = from_argb32_simd(bitmap.sample_at(texcoord[0], texcoord[1])); let texel = bitmap.sample_at(texcoord[0], texcoord[1]);
*dest_pixels = to_argb32_simd(multiply_argb_simd(texel, color)) *dest_pixels = texel * color
}, },
) )
} }
@ -194,12 +187,11 @@ impl RgbaBitmap {
&mut self, &mut self,
positions: &[Vector2; 3], positions: &[Vector2; 3],
texcoords: &[Vector2; 3], texcoords: &[Vector2; 3],
color: u32, color: ARGBu8x4,
bitmap: &Self, bitmap: &Self,
blend: BlendFunction, blend: BlendFunction,
) { ) {
let area = simd::f32x2::splat(edge_function(positions[0], positions[1], positions[2])); let area = simd::f32x2::splat(edge_function(positions[0], positions[1], positions[2]));
let color = from_argb32_simd(color);
let texcoord1 = simd::f32x2::from_array([texcoords[0].x, texcoords[0].y]); let texcoord1 = simd::f32x2::from_array([texcoords[0].x, texcoords[0].y]);
let texcoord2 = simd::f32x2::from_array([texcoords[1].x, texcoords[1].y]); let texcoord2 = simd::f32x2::from_array([texcoords[1].x, texcoords[1].y]);
let texcoord3 = simd::f32x2::from_array([texcoords[2].x, texcoords[2].y]); let texcoord3 = simd::f32x2::from_array([texcoords[2].x, texcoords[2].y]);
@ -213,9 +205,9 @@ impl RgbaBitmap {
+ simd::f32x2::splat(w1) * texcoord2 + simd::f32x2::splat(w1) * texcoord2
+ simd::f32x2::splat(w2) * texcoord3) + simd::f32x2::splat(w2) * texcoord3)
/ area; / area;
let texel = from_argb32_simd(bitmap.sample_at(texcoord[0], texcoord[1])); let texel = bitmap.sample_at(texcoord[0], texcoord[1]);
let src = multiply_argb_simd(texel, color); let src = texel * color;
*dest_pixels = to_argb32_simd(blend.blend_simd(src, from_argb32_simd(*dest_pixels))) *dest_pixels = blend.blend(src, *dest_pixels)
}, },
) )
} }
@ -224,13 +216,13 @@ impl RgbaBitmap {
&mut self, &mut self,
positions: &[Vector2; 3], positions: &[Vector2; 3],
texcoords: &[Vector2; 3], texcoords: &[Vector2; 3],
colors: &[u32; 3], colors: &[ARGBu8x4; 3],
bitmap: &Self, bitmap: &Self,
) { ) {
let area = simd::f32x4::splat(edge_function(positions[0], positions[1], positions[2])); let area = simd::f32x4::splat(edge_function(positions[0], positions[1], positions[2]));
let color1 = from_rgb32_simd(colors[0]).cast(); let color1 = colors[0].0.cast();
let color2 = from_rgb32_simd(colors[1]).cast(); let color2 = colors[1].0.cast();
let color3 = from_rgb32_simd(colors[2]).cast(); let color3 = colors[2].0.cast();
// we are using a f32x4 here with two zero's at the end as dummy values just so that we can // we are using a f32x4 here with two zero's at the end as dummy values just so that we can
// do the texture coordinate interpolation in the inner loop as f32x4 operations. // do the texture coordinate interpolation in the inner loop as f32x4 operations.
// however, for the texture coordinates, we only care about the first two lanes in the results ... // however, for the texture coordinates, we only care about the first two lanes in the results ...
@ -248,8 +240,8 @@ impl RgbaBitmap {
let w2 = simd::f32x4::splat(w2); let w2 = simd::f32x4::splat(w2);
let color = ((w0 * color1 + w1 * color2 + w2 * color3) / area).cast::<u8>(); let color = ((w0 * color1 + w1 * color2 + w2 * color3) / area).cast::<u8>();
let texcoord = (w0 * texcoord1 + w1 * texcoord2 + w2 * texcoord3) / area; let texcoord = (w0 * texcoord1 + w1 * texcoord2 + w2 * texcoord3) / area;
let texel = from_argb32_simd(bitmap.sample_at(texcoord[0], texcoord[1])); let texel = bitmap.sample_at(texcoord[0], texcoord[1]);
*dest_pixels = to_rgb32_simd(multiply_argb_simd(texel, color)) *dest_pixels = texel * ARGBu8x4(color)
}, },
) )
} }
@ -258,14 +250,14 @@ impl RgbaBitmap {
&mut self, &mut self,
positions: &[Vector2; 3], positions: &[Vector2; 3],
texcoords: &[Vector2; 3], texcoords: &[Vector2; 3],
colors: &[u32; 3], colors: &[ARGBu8x4; 3],
bitmap: &Self, bitmap: &Self,
blend: BlendFunction, blend: BlendFunction,
) { ) {
let area = simd::f32x4::splat(edge_function(positions[0], positions[1], positions[2])); let area = simd::f32x4::splat(edge_function(positions[0], positions[1], positions[2]));
let color1 = from_argb32_simd(colors[0]).cast(); let color1 = colors[0].0.cast();
let color2 = from_argb32_simd(colors[1]).cast(); let color2 = colors[1].0.cast();
let color3 = from_argb32_simd(colors[2]).cast(); let color3 = colors[2].0.cast();
// we are using a f32x4 here with two zero's at the end as dummy values just so that we can // we are using a f32x4 here with two zero's at the end as dummy values just so that we can
// do the texture coordinate interpolation in the inner loop as f32x4 operations. // do the texture coordinate interpolation in the inner loop as f32x4 operations.
// however, for the texture coordinates, we only care about the first two lanes in the results ... // however, for the texture coordinates, we only care about the first two lanes in the results ...
@ -283,10 +275,9 @@ impl RgbaBitmap {
let w2 = simd::f32x4::splat(w2); let w2 = simd::f32x4::splat(w2);
let color = ((w0 * color1 + w1 * color2 + w2 * color3) / area).cast::<u8>(); let color = ((w0 * color1 + w1 * color2 + w2 * color3) / area).cast::<u8>();
let texcoord = (w0 * texcoord1 + w1 * texcoord2 + w2 * texcoord3) / area; let texcoord = (w0 * texcoord1 + w1 * texcoord2 + w2 * texcoord3) / area;
let texel = from_argb32_simd(bitmap.sample_at(texcoord[0], texcoord[1])); let texel = bitmap.sample_at(texcoord[0], texcoord[1]);
let src = multiply_argb_simd(texel, color); let src = texel * ARGBu8x4(color);
let dest = from_argb32_simd(*dest_pixels); *dest_pixels = blend.blend(src, *dest_pixels)
*dest_pixels = to_argb32_simd(blend.blend_simd(src, dest))
}, },
) )
} }
@ -296,10 +287,9 @@ impl RgbaBitmap {
positions: &[Vector2; 3], positions: &[Vector2; 3],
texcoords: &[Vector2; 3], texcoords: &[Vector2; 3],
bitmap: &Self, bitmap: &Self,
tint: u32, tint: ARGBu8x4,
) { ) {
let area = simd::f32x2::splat(edge_function(positions[0], positions[1], positions[2])); let area = simd::f32x2::splat(edge_function(positions[0], positions[1], positions[2]));
let tint = from_argb32_simd(tint);
let texcoord1 = simd::f32x2::from_array([texcoords[0].x, texcoords[0].y]); let texcoord1 = simd::f32x2::from_array([texcoords[0].x, texcoords[0].y]);
let texcoord2 = simd::f32x2::from_array([texcoords[1].x, texcoords[1].y]); let texcoord2 = simd::f32x2::from_array([texcoords[1].x, texcoords[1].y]);
let texcoord3 = simd::f32x2::from_array([texcoords[2].x, texcoords[2].y]); let texcoord3 = simd::f32x2::from_array([texcoords[2].x, texcoords[2].y]);
@ -313,8 +303,8 @@ impl RgbaBitmap {
+ simd::f32x2::splat(w1) * texcoord2 + simd::f32x2::splat(w1) * texcoord2
+ simd::f32x2::splat(w2) * texcoord3) + simd::f32x2::splat(w2) * texcoord3)
/ area; / area;
let texel = from_argb32_simd(bitmap.sample_at(texcoord[0], texcoord[1])); let texel = bitmap.sample_at(texcoord[0], texcoord[1]);
*dest_pixels = to_argb32_simd(tint_argb_simd(texel, tint)); *dest_pixels = texel.tint(tint);
}, },
) )
} }
@ -340,8 +330,8 @@ impl RgbaBitmap {
+ simd::f32x2::splat(w1) * texcoord2 + simd::f32x2::splat(w1) * texcoord2
+ simd::f32x2::splat(w2) * texcoord3) + simd::f32x2::splat(w2) * texcoord3)
/ area; / area;
let texel = from_argb32_simd(bitmap.sample_at(texcoord[0], texcoord[1])); let texel = bitmap.sample_at(texcoord[0], texcoord[1]);
*dest_pixels = to_argb32_simd(blend.blend_simd(texel, from_argb32_simd(*dest_pixels))); *dest_pixels = blend.blend(texel, *dest_pixels);
}, },
) )
} }

View file

@ -5,7 +5,7 @@ use std::path::Path;
use byteorder::{ReadBytesExt, WriteBytesExt}; use byteorder::{ReadBytesExt, WriteBytesExt};
use thiserror::Error; use thiserror::Error;
use crate::graphics::{from_rgb32, luminance, Palette}; use crate::graphics::Palette;
use crate::math::lerp; use crate::math::lerp;
use crate::utils::ReadFixedLengthByteArray; use crate::utils::ReadFixedLengthByteArray;
@ -76,8 +76,7 @@ impl BlendMap {
let mut blend_map = Self::new(source_color, source_color); let mut blend_map = Self::new(source_color, source_color);
for idx in 0..=255 { for idx in 0..=255 {
let rgb = from_rgb32(palette[idx]); let lit = (palette[idx].luminance() * 255.0) as u8;
let lit = (luminance(rgb) * 255.0) as u8;
blend_map blend_map
.set_mapping( .set_mapping(
source_color, source_color,
@ -105,11 +104,9 @@ impl BlendMap {
let mut blend_map = BlendMap::new(0, 255); let mut blend_map = BlendMap::new(0, 255);
for source_color in 0..=255 { for source_color in 0..=255 {
let source_rgb = from_rgb32(palette[source_color]); let source_luminance = palette[source_color].luminance();
let source_luminance = luminance(source_rgb);
for dest_color in 0..=255 { for dest_color in 0..=255 {
let dest_rgb = from_rgb32(palette[dest_color]); let destination_luminance = palette[dest_color].luminance();
let destination_luminance = luminance(dest_rgb);
let weight = (f(source_luminance, destination_luminance) * 255.0) as u8; let weight = (f(source_luminance, destination_luminance) * 255.0) as u8;
blend_map blend_map
.set_mapping( .set_mapping(
@ -135,10 +132,10 @@ impl BlendMap {
pub fn new_translucency_map(blend_r: f32, blend_g: f32, blend_b: f32, palette: &Palette) -> Self { pub fn new_translucency_map(blend_r: f32, blend_g: f32, blend_b: f32, palette: &Palette) -> Self {
let mut blend_map = BlendMap::new(0, 255); let mut blend_map = BlendMap::new(0, 255);
for source in 0..=255 { for source in 0..=255 {
let [source_r, source_g, source_b] = from_rgb32(palette[source]); let [_, source_r, source_g, source_b] = palette[source].to_array();
let mapping = blend_map.get_mapping_mut(source).unwrap(); let mapping = blend_map.get_mapping_mut(source).unwrap();
for dest in 0..=255 { for dest in 0..=255 {
let [dest_r, dest_g, dest_b] = from_rgb32(palette[dest]); let [_, dest_r, dest_g, dest_b] = palette[dest].to_array();
let find_r = lerp(dest_r as f32, source_r as f32, blend_r) as u8; let find_r = lerp(dest_r as f32, source_r as f32, blend_r) as u8;
let find_g = lerp(dest_g as f32, source_g as f32, blend_g) as u8; let find_g = lerp(dest_g as f32, source_g as f32, blend_g) as u8;

View file

@ -1,6 +1,10 @@
use std::ops::{Mul, MulAssign}; use std::ops::{Mul, MulAssign};
use std::simd; use std::simd;
use byteorder::{ReadBytesExt, WriteBytesExt};
use crate::utils::{ReadType, WriteType};
/// Packed 32-bit color, in the format: 0xAARRGGBB /// Packed 32-bit color, in the format: 0xAARRGGBB
pub type Color1u32 = u32; pub type Color1u32 = u32;
@ -24,36 +28,36 @@ pub type SimdColor4f32 = simd::f32x4;
// these colours are taken from the default VGA palette // these colours are taken from the default VGA palette
pub const COLOR_BLACK: Color1u32 = 0xff000000; pub const COLOR_BLACK: ARGBu8x4 = ARGBu8x4::from_rgb([0, 0, 0]);
pub const COLOR_BLUE: Color1u32 = 0xff0000aa; pub const COLOR_BLUE: ARGBu8x4 = ARGBu8x4::from_rgb([0, 0, 170]);
pub const COLOR_GREEN: Color1u32 = 0xff00aa00; pub const COLOR_GREEN: ARGBu8x4 = ARGBu8x4::from_rgb([0, 170, 0]);
pub const COLOR_CYAN: Color1u32 = 0xff00aaaa; pub const COLOR_CYAN: ARGBu8x4 = ARGBu8x4::from_rgb([0, 170, 170]);
pub const COLOR_RED: Color1u32 = 0xffaa0000; pub const COLOR_RED: ARGBu8x4 = ARGBu8x4::from_rgb([170, 0, 0]);
pub const COLOR_MAGENTA: Color1u32 = 0xffaa00aa; pub const COLOR_MAGENTA: ARGBu8x4 = ARGBu8x4::from_rgb([170, 0, 170]);
pub const COLOR_BROWN: Color1u32 = 0xffaa5500; pub const COLOR_BROWN: ARGBu8x4 = ARGBu8x4::from_rgb([170, 85, 0]);
pub const COLOR_LIGHT_GRAY: Color1u32 = 0xffaaaaaa; pub const COLOR_LIGHT_GRAY: ARGBu8x4 = ARGBu8x4::from_rgb([170, 170, 170]);
pub const COLOR_DARK_GRAY: Color1u32 = 0xff555555; pub const COLOR_DARK_GRAY: ARGBu8x4 = ARGBu8x4::from_rgb([85, 85, 85]);
pub const COLOR_BRIGHT_BLUE: Color1u32 = 0xff5555ff; pub const COLOR_BRIGHT_BLUE: ARGBu8x4 = ARGBu8x4::from_rgb([85, 85, 255]);
pub const COLOR_BRIGHT_GREEN: Color1u32 = 0xff55ff55; pub const COLOR_BRIGHT_GREEN: ARGBu8x4 = ARGBu8x4::from_rgb([85, 255, 85]);
pub const COLOR_BRIGHT_CYAN: Color1u32 = 0xff55ffff; pub const COLOR_BRIGHT_CYAN: ARGBu8x4 = ARGBu8x4::from_rgb([85, 255, 255]);
pub const COLOR_BRIGHT_RED: Color1u32 = 0xffff5555; pub const COLOR_BRIGHT_RED: ARGBu8x4 = ARGBu8x4::from_rgb([255, 85, 85]);
pub const COLOR_BRIGHT_MAGENTA: Color1u32 = 0xffff55ff; pub const COLOR_BRIGHT_MAGENTA: ARGBu8x4 = ARGBu8x4::from_rgb([255, 85, 255]);
pub const COLOR_BRIGHT_YELLOW: Color1u32 = 0xffffff55; pub const COLOR_BRIGHT_YELLOW: ARGBu8x4 = ARGBu8x4::from_rgb([255, 255, 85]);
pub const COLOR_BRIGHT_WHITE: Color1u32 = 0xffffffff; pub const COLOR_BRIGHT_WHITE: ARGBu8x4 = ARGBu8x4::from_rgb([255, 255, 255]);
// TODO: probably should name these better, after i do much more reading on the subject :-) // TODO: probably should name these better, after i do much more reading on the subject :-)
#[derive(Debug, Copy, Clone, Eq, PartialEq)] #[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum BlendFunction { pub enum BlendFunction {
Blend, Blend,
BlendSourceWithAlpha(u8), BlendSourceWithAlpha(u8),
TintedBlend(Color1u32), TintedBlend(ARGBu8x4),
MultipliedBlend(Color1u32), MultipliedBlend(ARGBu8x4),
} }
impl BlendFunction { impl BlendFunction {
#[inline] #[inline]
/// Blends the source and destination color together using the function associated with /// Blends the source and destination color together using the function associated with
/// this enum value. Both colors should be 32-bit packed colors in the format 0xAARRGGBB. /// this enum value.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -61,35 +65,13 @@ impl BlendFunction {
/// * `dest`: the destination color to blend the source color over /// * `dest`: the destination color to blend the source color over
/// ///
/// returns: the blended color /// returns: the blended color
pub fn blend_1u32(&self, src: Color1u32, dest: Color1u32) -> Color1u32 { pub fn blend(&self, src: ARGBu8x4, dest: ARGBu8x4) -> ARGBu8x4 {
use BlendFunction::*; use BlendFunction::*;
match self { match self {
Blend => blend_argb32(src, dest), Blend => src.blend(dest),
BlendSourceWithAlpha(opacity) => blend_argb32_source_by(src, dest, *opacity), BlendSourceWithAlpha(opacity) => src.blend_with_alpha(dest, *opacity),
TintedBlend(tint) => tinted_blend_argb32(*tint, src, dest), TintedBlend(tint) => src.tint(*tint).blend(dest),
MultipliedBlend(color) => multiplied_blend_argb32(*color, src, dest), MultipliedBlend(color) => src.mul(*color).blend(dest),
}
}
#[inline]
pub fn blend_4u8(&self, src: Color4u8, dest: Color4u8) -> Color4u8 {
use BlendFunction::*;
match self {
Blend => blend_argb(src, dest),
BlendSourceWithAlpha(opacity) => blend_argb_source_by(src, dest, *opacity),
TintedBlend(tint) => tinted_blend_argb(from_argb32(*tint), src, dest),
MultipliedBlend(color) => multiplied_blend_argb(from_argb32(*color), src, dest),
}
}
#[inline]
pub fn blend_simd(&self, src: SimdColor4u8, dest: SimdColor4u8) -> SimdColor4u8 {
use BlendFunction::*;
match self {
Blend => blend_argb_simd(src, dest),
BlendSourceWithAlpha(opacity) => blend_argb_simd_source_by(src, dest, *opacity),
TintedBlend(tint) => tinted_blend_argb_simd(from_argb32_simd(*tint), src, dest),
MultipliedBlend(color) => multiplied_blend_argb_simd(from_argb32_simd(*color), src, dest),
} }
} }
} }
@ -566,6 +548,8 @@ pub trait ColorsAsBytes {
pub struct ARGBu8x4(pub simd::u8x4); pub struct ARGBu8x4(pub simd::u8x4);
impl ARGBu8x4 { impl ARGBu8x4 {
pub const SIZE: usize = std::mem::size_of::<Self>();
#[inline] #[inline]
pub const fn from_argb(argb: [u8; 4]) -> Self { pub const fn from_argb(argb: [u8; 4]) -> Self {
ARGBu8x4(simd::u8x4::from_array(argb)) ARGBu8x4(simd::u8x4::from_array(argb))
@ -758,13 +742,33 @@ impl ColorsAsBytes for [ARGBu8x4] {
impl std::fmt::Debug for ARGBu8x4 { impl std::fmt::Debug for ARGBu8x4 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ARGBu8x4(0x{:2x}, 0x{:2x}, 0x{:2x}, 0x{:2x})", self.a(), self.r(), self.g(), self.b()) write!(f, "0x{:02x}{:02x}{:02x}{:02x}", self.a(), self.r(), self.g(), self.b())
} }
} }
impl std::fmt::Display for ARGBu8x4 { impl std::fmt::Display for ARGBu8x4 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "0x{:2x}{:2x}{:2x}{:2x}", self.a(), self.r(), self.g(), self.b()) write!(f, "0x{:02x}{:02x}{:02x}{:02x}", self.a(), self.r(), self.g(), self.b())
}
}
impl WriteType for ARGBu8x4 {
type ErrorType = std::io::Error;
#[inline]
fn write<T: WriteBytesExt>(&self, writer: &mut T) -> Result<(), Self::ErrorType> {
writer.write_all(self.0.as_array())?;
Ok(())
}
}
impl ReadType for ARGBu8x4 {
type OutputType = Self;
type ErrorType = std::io::Error;
#[inline]
fn read<T: ReadBytesExt>(reader: &mut T) -> Result<Self::OutputType, Self::ErrorType> {
Ok(ARGBu8x4::from_argb([reader.read_u8()?, reader.read_u8()?, reader.read_u8()?, reader.read_u8()?]))
} }
} }

View file

@ -7,7 +7,7 @@ use std::path::Path;
use byteorder::{ReadBytesExt, WriteBytesExt}; use byteorder::{ReadBytesExt, WriteBytesExt};
use thiserror::Error; use thiserror::Error;
use crate::graphics::{from_rgb32, lerp_rgb32, to_argb32, to_rgb32, IndexedBitmap}; use crate::graphics::{ARGBu8x4, IndexedBitmap};
use crate::utils::abs_diff; use crate::utils::abs_diff;
const NUM_COLORS: usize = 256; const NUM_COLORS: usize = 256;
@ -29,16 +29,19 @@ fn to_6bit(value: u8) -> u8 {
} }
// vga bios (0-63) format // vga bios (0-63) format
fn read_palette_6bit<T: ReadBytesExt>(reader: &mut T, num_colors: usize) -> Result<[u32; NUM_COLORS], PaletteError> { fn read_palette_6bit<T: ReadBytesExt>(
reader: &mut T,
num_colors: usize,
) -> Result<[ARGBu8x4; NUM_COLORS], PaletteError> {
if num_colors > NUM_COLORS { if num_colors > NUM_COLORS {
return Err(PaletteError::OutOfRange(num_colors)); return Err(PaletteError::OutOfRange(num_colors));
} }
let mut colors = [to_argb32([255, 0, 0, 0]); NUM_COLORS]; let mut colors = [ARGBu8x4::from_argb([255, 0, 0, 0]); NUM_COLORS];
for i in 0..num_colors { for i in 0..num_colors {
let r = reader.read_u8()?; let r = reader.read_u8()?;
let g = reader.read_u8()?; let g = reader.read_u8()?;
let b = reader.read_u8()?; let b = reader.read_u8()?;
let color = to_rgb32([from_6bit(r), from_6bit(g), from_6bit(b)]); let color = ARGBu8x4::from_rgb([from_6bit(r), from_6bit(g), from_6bit(b)]);
colors[i] = color; colors[i] = color;
} }
Ok(colors) Ok(colors)
@ -46,32 +49,34 @@ fn read_palette_6bit<T: ReadBytesExt>(reader: &mut T, num_colors: usize) -> Resu
fn write_palette_6bit<T: WriteBytesExt>( fn write_palette_6bit<T: WriteBytesExt>(
writer: &mut T, writer: &mut T,
colors: &[u32; NUM_COLORS], colors: &[ARGBu8x4; NUM_COLORS],
num_colors: usize, num_colors: usize,
) -> Result<(), PaletteError> { ) -> Result<(), PaletteError> {
if num_colors > NUM_COLORS { if num_colors > NUM_COLORS {
return Err(PaletteError::OutOfRange(num_colors)); return Err(PaletteError::OutOfRange(num_colors));
} }
for i in 0..num_colors { for i in 0..num_colors {
let [r, g, b] = from_rgb32(colors[i]); writer.write_u8(to_6bit(colors[i].r()))?;
writer.write_u8(to_6bit(r))?; writer.write_u8(to_6bit(colors[i].g()))?;
writer.write_u8(to_6bit(g))?; writer.write_u8(to_6bit(colors[i].b()))?;
writer.write_u8(to_6bit(b))?;
} }
Ok(()) Ok(())
} }
// normal (0-255) format // normal (0-255) format
fn read_palette_8bit<T: ReadBytesExt>(reader: &mut T, num_colors: usize) -> Result<[u32; NUM_COLORS], PaletteError> { fn read_palette_8bit<T: ReadBytesExt>(
reader: &mut T,
num_colors: usize,
) -> Result<[ARGBu8x4; NUM_COLORS], PaletteError> {
if num_colors > NUM_COLORS { if num_colors > NUM_COLORS {
return Err(PaletteError::OutOfRange(num_colors)); return Err(PaletteError::OutOfRange(num_colors));
} }
let mut colors = [to_argb32([255, 0, 0, 0]); NUM_COLORS]; let mut colors = [ARGBu8x4::from_argb([255, 0, 0, 0]); NUM_COLORS];
for i in 0..num_colors { for i in 0..num_colors {
let r = reader.read_u8()?; let r = reader.read_u8()?;
let g = reader.read_u8()?; let g = reader.read_u8()?;
let b = reader.read_u8()?; let b = reader.read_u8()?;
let color = to_rgb32([r, g, b]); let color = ARGBu8x4::from_rgb([r, g, b]);
colors[i] = color; colors[i] = color;
} }
Ok(colors) Ok(colors)
@ -79,17 +84,16 @@ fn read_palette_8bit<T: ReadBytesExt>(reader: &mut T, num_colors: usize) -> Resu
fn write_palette_8bit<T: WriteBytesExt>( fn write_palette_8bit<T: WriteBytesExt>(
writer: &mut T, writer: &mut T,
colors: &[u32; NUM_COLORS], colors: &[ARGBu8x4; NUM_COLORS],
num_colors: usize, num_colors: usize,
) -> Result<(), PaletteError> { ) -> Result<(), PaletteError> {
if num_colors > NUM_COLORS { if num_colors > NUM_COLORS {
return Err(PaletteError::OutOfRange(num_colors)); return Err(PaletteError::OutOfRange(num_colors));
} }
for i in 0..num_colors { for i in 0..num_colors {
let [r, g, b] = from_rgb32(colors[i]); writer.write_u8(colors[i].r())?;
writer.write_u8(r)?; writer.write_u8(colors[i].g())?;
writer.write_u8(g)?; writer.write_u8(colors[i].b())?;
writer.write_u8(b)?;
} }
Ok(()) Ok(())
} }
@ -114,19 +118,18 @@ pub enum PaletteFormat {
/// colors are all stored individually as 32-bit packed values in the format 0xAARRGGBB. /// colors are all stored individually as 32-bit packed values in the format 0xAARRGGBB.
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
pub struct Palette { pub struct Palette {
colors: [u32; NUM_COLORS], colors: [ARGBu8x4; NUM_COLORS],
} }
impl Palette { impl Palette {
/// Creates a new Palette with all black colors. /// Creates a new Palette with all black colors.
pub fn new() -> Palette { pub fn new() -> Palette {
Palette { colors: [0; NUM_COLORS] } Palette { colors: [ARGBu8x4::from_rgb([0, 0, 0]); NUM_COLORS] }
} }
/// Creates a new Palette with all initial colors having the RGB values specified. /// Creates a new Palette with all initial colors having the RGB values specified.
pub fn new_with_default(r: u8, g: u8, b: u8) -> Palette { pub fn new_with_default(r: u8, g: u8, b: u8) -> Palette {
let rgb = to_rgb32([r, g, b]); Palette { colors: [ARGBu8x4::from_rgb([r, g, b]); NUM_COLORS] }
Palette { colors: [rgb; NUM_COLORS] }
} }
/// Creates a new Palette, pre-loaded with the default VGA BIOS colors. /// Creates a new Palette, pre-loaded with the default VGA BIOS colors.
@ -295,7 +298,9 @@ impl Palette {
pub fn fade_color_toward_rgb(&mut self, color: u8, target_r: u8, target_g: u8, target_b: u8, step: u8) -> bool { pub fn fade_color_toward_rgb(&mut self, color: u8, target_r: u8, target_g: u8, target_b: u8, step: u8) -> bool {
let mut modified = false; let mut modified = false;
let [mut r, mut g, mut b] = from_rgb32(self.colors[color as usize]); let mut r = self.colors[color as usize].r();
let mut g = self.colors[color as usize].g();
let mut b = self.colors[color as usize].b();
if r != target_r { if r != target_r {
modified = true; modified = true;
@ -328,7 +333,7 @@ impl Palette {
} }
if modified { if modified {
self.colors[color as usize] = to_rgb32([r, g, b]); self.colors[color as usize] = ARGBu8x4::from_rgb([r, g, b]);
} }
(target_r == r) && (target_g == g) && (target_b == b) (target_r == r) && (target_g == g) && (target_b == b)
@ -381,8 +386,7 @@ impl Palette {
pub fn fade_colors_toward_palette<T: ColorRange>(&mut self, colors: T, palette: &Palette, step: u8) -> bool { pub fn fade_colors_toward_palette<T: ColorRange>(&mut self, colors: T, palette: &Palette, step: u8) -> bool {
let mut all_faded = true; let mut all_faded = true;
for color in colors { for color in colors {
let [r, g, b] = from_rgb32(palette[color]); if !self.fade_color_toward_rgb(color, palette[color].r(), palette[color].g(), palette[color].b(), step) {
if !self.fade_color_toward_rgb(color, r, g, b, step) {
all_faded = false; all_faded = false;
} }
} }
@ -400,7 +404,7 @@ impl Palette {
/// * `t`: the amount to interpolate between the two palettes, specified as a fraction /// * `t`: the amount to interpolate between the two palettes, specified as a fraction
pub fn lerp<T: ColorRange>(&mut self, colors: T, a: &Palette, b: &Palette, t: f32) { pub fn lerp<T: ColorRange>(&mut self, colors: T, a: &Palette, b: &Palette, t: f32) {
for color in colors { for color in colors {
self[color] = lerp_rgb32(a[color], b[color], t); self[color] = a[color].lerp(b[color], t);
} }
} }
@ -439,15 +443,14 @@ impl Palette {
let mut closest = 0; let mut closest = 0;
for (index, color) in self.colors.iter().enumerate() { for (index, color) in self.colors.iter().enumerate() {
let [this_r, this_g, this_b] = from_rgb32(*color); if r == color.r() && g == color.g() && b == color.b() {
if r == this_r && g == this_g && b == this_b {
return index as u8; return index as u8;
} else { } else {
// this comparison method is using the sRGB Euclidean formula described here: // this comparison method is using the sRGB Euclidean formula described here:
// https://en.wikipedia.org/wiki/Color_difference // https://en.wikipedia.org/wiki/Color_difference
let distance = abs_diff(this_r, r) as u32 + abs_diff(this_g, g) as u32 + abs_diff(this_b, b) as u32; let distance =
abs_diff(color.r(), r) as u32 + abs_diff(color.g(), g) as u32 + abs_diff(color.b(), b) as u32;
if distance < closest_distance { if distance < closest_distance {
closest = index as u8; closest = index as u8;
@ -475,7 +478,7 @@ impl Palette {
} }
impl Index<u8> for Palette { impl Index<u8> for Palette {
type Output = u32; type Output = ARGBu8x4;
#[inline] #[inline]
fn index(&self, index: u8) -> &Self::Output { fn index(&self, index: u8) -> &Self::Output {
@ -509,11 +512,11 @@ mod tests {
#[test] #[test]
fn get_and_set_colors() { fn get_and_set_colors() {
let mut palette = Palette::new(); let mut palette = Palette::new();
assert_eq!(0, palette[0]); assert_eq!(ARGBu8x4::from_rgb([0, 0, 0]), palette[0]);
assert_eq!(0, palette[1]); assert_eq!(ARGBu8x4::from_rgb([0, 0, 0]), palette[1]);
palette[0] = 0x11223344; palette[0] = 0x11223344.into();
assert_eq!(0x11223344, palette[0]); assert_eq!(ARGBu8x4::from(0x11223344), palette[0]);
assert_eq!(0, palette[1]); assert_eq!(ARGBu8x4::from_rgb([0, 0, 0]), palette[1]);
} }
fn assert_ega_colors(palette: &Palette) { fn assert_ega_colors(palette: &Palette) {

View file

@ -21,7 +21,8 @@ mod tests {
use std::io::{BufReader, Read}; use std::io::{BufReader, Read};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use byteorder::{LittleEndian, ReadBytesExt}; use crate::graphics::ARGBu8x4;
use crate::utils::ReadType;
#[allow(dead_code)] #[allow(dead_code)]
const ASSETS_PATH: &str = "./assets/"; const ASSETS_PATH: &str = "./assets/";
@ -45,12 +46,12 @@ mod tests {
Ok(buffer.into_boxed_slice()) Ok(buffer.into_boxed_slice())
} }
pub fn load_raw_argb(bin_file: &Path) -> Result<Box<[u32]>, io::Error> { pub fn load_raw_argb(bin_file: &Path) -> Result<Box<[ARGBu8x4]>, io::Error> {
let f = File::open(bin_file)?; let f = File::open(bin_file)?;
let mut reader = BufReader::new(f); let mut reader = BufReader::new(f);
let mut buffer = Vec::new(); let mut buffer = Vec::new();
loop { loop {
buffer.push(match reader.read_u32::<LittleEndian>() { buffer.push(match ARGBu8x4::read(&mut reader) {
Ok(value) => value, Ok(value) => value,
Err(err) if err.kind() == io::ErrorKind::UnexpectedEof => break, Err(err) if err.kind() == io::ErrorKind::UnexpectedEof => break,
Err(err) => return Err(err), Err(err) => return Err(err),

View file

@ -1,7 +1,6 @@
use byte_slice_cast::AsByteSlice;
use thiserror::Error; use thiserror::Error;
use crate::graphics::{IndexedBitmap, Palette, RgbaBitmap}; use crate::graphics::{ARGBu8x4, ColorsAsBytes, IndexedBitmap, Palette, RgbaBitmap};
pub fn calculate_logical_screen_size(window_width: u32, window_height: u32, scale_factor: u32) -> (u32, u32) { pub fn calculate_logical_screen_size(window_width: u32, window_height: u32, scale_factor: u32) -> (u32, u32) {
let logical_width = (window_width as f32 / scale_factor as f32).ceil() as u32; let logical_width = (window_width as f32 / scale_factor as f32).ceil() as u32;
@ -24,7 +23,7 @@ pub enum SdlFramebufferError {
pub struct SdlFramebuffer { pub struct SdlFramebuffer {
sdl_texture: sdl2::render::Texture, sdl_texture: sdl2::render::Texture,
sdl_texture_pitch: usize, sdl_texture_pitch: usize,
intermediate_texture: Option<Box<[u32]>>, intermediate_texture: Option<Box<[ARGBu8x4]>>,
} }
// TODO: i'm not totally happy with this implementation. i don't like the two display methods and how the caller // TODO: i'm not totally happy with this implementation. i don't like the two display methods and how the caller
@ -46,11 +45,10 @@ impl SdlFramebuffer {
return Err(SdlFramebufferError::SDLError(error.to_string())); return Err(SdlFramebufferError::SDLError(error.to_string()));
} }
let sdl_texture = match canvas.create_texture_streaming( let format = sdl2::pixels::PixelFormatEnum::BGRA8888;
Some(sdl2::pixels::PixelFormatEnum::ARGB8888),
logical_screen_width, let sdl_texture =
logical_screen_height, match canvas.create_texture_streaming(Some(format), logical_screen_width, logical_screen_height) {
) {
Ok(texture) => texture, Ok(texture) => texture,
Err(error) => return Err(SdlFramebufferError::SDLError(error.to_string())), Err(error) => return Err(SdlFramebufferError::SDLError(error.to_string())),
}; };
@ -61,9 +59,8 @@ impl SdlFramebuffer {
// SDL texture uploads each frame. necessary as applications are dealing with 8-bit indexed // SDL texture uploads each frame. necessary as applications are dealing with 8-bit indexed
// bitmaps, not 32-bit RGBA pixels, so this temporary buffer is where we convert the final // bitmaps, not 32-bit RGBA pixels, so this temporary buffer is where we convert the final
// application framebuffer to 32-bit RGBA pixels before it is uploaded to the SDL texture // application framebuffer to 32-bit RGBA pixels before it is uploaded to the SDL texture
let texture_pixels_size = let texture_pixels_size = (logical_screen_width * logical_screen_height) as usize;
(logical_screen_width * logical_screen_height) as usize * SCREEN_TEXTURE_PIXEL_SIZE; Some(vec![ARGBu8x4::default(); texture_pixels_size].into_boxed_slice())
Some(vec![0u32; texture_pixels_size].into_boxed_slice())
} else { } else {
None None
}; };
@ -83,7 +80,7 @@ impl SdlFramebuffer {
src.copy_as_argb_to(intermediate_texture, palette); src.copy_as_argb_to(intermediate_texture, palette);
let texture_pixels = intermediate_texture.as_byte_slice(); let texture_pixels = intermediate_texture.as_bytes();
if let Err(error) = self.sdl_texture.update(None, texture_pixels, self.sdl_texture_pitch) { if let Err(error) = self.sdl_texture.update(None, texture_pixels, self.sdl_texture_pitch) {
return Err(SdlFramebufferError::SDLError(error.to_string())); return Err(SdlFramebufferError::SDLError(error.to_string()));
} }
@ -106,7 +103,7 @@ impl SdlFramebuffer {
"Calls to display should only occur on SdlFramebuffers without an intermediate_texture" "Calls to display should only occur on SdlFramebuffers without an intermediate_texture"
); );
let texture_pixels = src.pixels().as_byte_slice(); let texture_pixels = src.pixels().as_bytes();
if let Err(error) = self.sdl_texture.update(None, texture_pixels, self.sdl_texture_pitch) { if let Err(error) = self.sdl_texture.update(None, texture_pixels, self.sdl_texture_pitch) {
return Err(SdlFramebufferError::SDLError(error.to_string())); return Err(SdlFramebufferError::SDLError(error.to_string()));
} }

View file

@ -1,4 +1,4 @@
use crate::graphics::{GeneralBitmap, GeneralBlitMethod, IndexedBitmap, RgbaBitmap}; use crate::graphics::{ARGBu8x4, ColorsAsBytes, GeneralBitmap, GeneralBlitMethod, IndexedBitmap, RgbaBitmap};
use crate::math::Rect; use crate::math::Rect;
use crate::system::Mouse; use crate::system::Mouse;
@ -240,34 +240,34 @@ impl DefaultMouseCursorBitmaps<IndexedBitmap> for CustomMouseCursor<IndexedBitma
impl DefaultMouseCursorBitmaps<RgbaBitmap> for CustomMouseCursor<RgbaBitmap> { impl DefaultMouseCursorBitmaps<RgbaBitmap> for CustomMouseCursor<RgbaBitmap> {
fn get_default() -> MouseCursorBitmap<RgbaBitmap> { fn get_default() -> MouseCursorBitmap<RgbaBitmap> {
#[rustfmt::skip] #[rustfmt::skip]
const CURSOR_PIXELS: [u32; DEFAULT_MOUSE_CURSOR_WIDTH * DEFAULT_MOUSE_CURSOR_HEIGHT] = [ const CURSOR_PIXELS: [u8; DEFAULT_MOUSE_CURSOR_WIDTH * DEFAULT_MOUSE_CURSOR_HEIGHT * 4] = [
0x00000000, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0x00000000, 0xffffffff, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0x00000000, 0x00000000, 0xffff00ff, 0xffff00ff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff,
0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0x00000000, 0x00000000, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff, 0xffff00ff 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff
]; ];
let mut cursor = let mut cursor =
RgbaBitmap::new(DEFAULT_MOUSE_CURSOR_WIDTH as u32, DEFAULT_MOUSE_CURSOR_HEIGHT as u32).unwrap(); RgbaBitmap::new(DEFAULT_MOUSE_CURSOR_WIDTH as u32, DEFAULT_MOUSE_CURSOR_HEIGHT as u32).unwrap();
cursor.pixels_mut().copy_from_slice(&CURSOR_PIXELS); cursor.pixels_mut().as_bytes_mut().copy_from_slice(&CURSOR_PIXELS);
MouseCursorBitmap { MouseCursorBitmap {
cursor, cursor,
hotspot_x: DEFAULT_MOUSE_CURSOR_HOTSPOT_X, hotspot_x: DEFAULT_MOUSE_CURSOR_HOTSPOT_X,
hotspot_y: DEFAULT_MOUSE_CURSOR_HOTSPOT_Y, hotspot_y: DEFAULT_MOUSE_CURSOR_HOTSPOT_Y,
transparent_color: 0xffff00ff, transparent_color: ARGBu8x4::from(0xffff00ff),
} }
} }
} }

View file

@ -1,3 +1,4 @@
use byteorder::{ReadBytesExt, WriteBytesExt};
use std::io::{Error, SeekFrom}; use std::io::{Error, SeekFrom};
/// Provides a convenience method for determining the total size of a stream. This is provided /// Provides a convenience method for determining the total size of a stream. This is provided
@ -20,3 +21,16 @@ impl<T: std::io::Read + std::io::Seek> StreamSize for T {
Ok(len) Ok(len)
} }
} }
pub trait ReadType {
type OutputType;
type ErrorType;
fn read<T: ReadBytesExt>(reader: &mut T) -> Result<Self::OutputType, Self::ErrorType>;
}
pub trait WriteType {
type ErrorType;
fn write<T: WriteBytesExt>(&self, writer: &mut T) -> Result<(), Self::ErrorType>;
}

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View file

@ -5,24 +5,24 @@ use helpers::test_assets_file;
pub mod helpers; pub mod helpers;
const LIGHTER_BACKGROUND: u32 = 0xff2c3041; const LIGHTER_BACKGROUND: ARGBu8x4 = ARGBu8x4::from_rgb([0x2c, 0x30, 0x41]);
pub const COLOR_BLACK_HALF_ALPHA: u32 = 0x7f000000; pub const COLOR_BLACK_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0x00, 0x00, 0x00]);
pub const COLOR_BLUE_HALF_ALPHA: u32 = 0x7f0000aa; pub const COLOR_BLUE_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0x00, 0x00, 0xaa]);
pub const COLOR_GREEN_HALF_ALPHA: u32 = 0x7f00aa00; pub const COLOR_GREEN_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0x00, 0xaa, 0x00]);
pub const COLOR_CYAN_HALF_ALPHA: u32 = 0x7f00aaaa; pub const COLOR_CYAN_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0x00, 0xaa, 0xaa]);
pub const COLOR_RED_HALF_ALPHA: u32 = 0x7faa0000; pub const COLOR_RED_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0xaa, 0x00, 0x00]);
pub const COLOR_MAGENTA_HALF_ALPHA: u32 = 0x7faa00aa; pub const COLOR_MAGENTA_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0xaa, 0x00, 0xaa]);
pub const COLOR_BROWN_HALF_ALPHA: u32 = 0x7faa5500; pub const COLOR_BROWN_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0xaa, 0x55, 0x00]);
pub const COLOR_LIGHT_GRAY_HALF_ALPHA: u32 = 0x7faaaaaa; pub const COLOR_LIGHT_GRAY_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0xaa, 0xaa, 0xaa]);
pub const COLOR_DARK_GRAY_HALF_ALPHA: u32 = 0x7f555555; pub const COLOR_DARK_GRAY_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0x55, 0x55, 0x55]);
pub const COLOR_BRIGHT_BLUE_HALF_ALPHA: u32 = 0x7f5555ff; pub const COLOR_BRIGHT_BLUE_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0x55, 0x55, 0xff]);
pub const COLOR_BRIGHT_GREEN_HALF_ALPHA: u32 = 0x7f55ff55; pub const COLOR_BRIGHT_GREEN_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0x55, 0xff, 0x55]);
pub const COLOR_BRIGHT_CYAN_HALF_ALPHA: u32 = 0x7f55ffff; pub const COLOR_BRIGHT_CYAN_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0x55, 0xff, 0xff]);
pub const COLOR_BRIGHT_RED_HALF_ALPHA: u32 = 0x7fff5555; pub const COLOR_BRIGHT_RED_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0xff, 0x55, 0x55]);
pub const COLOR_BRIGHT_MAGENTA_HALF_ALPHA: u32 = 0x7fff55ff; pub const COLOR_BRIGHT_MAGENTA_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0xff, 0x55, 0xff]);
pub const COLOR_BRIGHT_YELLOW_HALF_ALPHA: u32 = 0x7fffff55; pub const COLOR_BRIGHT_YELLOW_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0xff, 0xff, 0x55]);
pub const COLOR_BRIGHT_WHITE_HALF_ALPHA: u32 = 0x7fffffff; pub const COLOR_BRIGHT_WHITE_HALF_ALPHA: ARGBu8x4 = ARGBu8x4::from_argb([0x7f, 0xff, 0xff, 0xff]);
const SCREEN_WIDTH: u32 = 320; const SCREEN_WIDTH: u32 = 320;
const SCREEN_HEIGHT: u32 = 240; const SCREEN_HEIGHT: u32 = 240;
@ -60,9 +60,9 @@ fn setup_for_blending_half_solid_half_semi_transparent() -> RgbaBitmap {
for y in (screen.height() / 2)..screen.height() { for y in (screen.height() / 2)..screen.height() {
for x in 0..screen.width() { for x in 0..screen.width() {
unsafe { unsafe {
let pixel = screen.get_pixel_unchecked(x as i32, y as i32); let mut pixel = screen.get_pixel_unchecked(x as i32, y as i32);
let [r, g, b] = from_rgb32(pixel); pixel.set_a(127);
screen.set_pixel_unchecked(x as i32, y as i32, to_argb32([127, r, g, b])); screen.set_pixel_unchecked(x as i32, y as i32, pixel);
} }
} }
} }
@ -83,7 +83,7 @@ fn pixel_addressing() {
let mut i = 0; let mut i = 0;
for _y in 0..16 { for _y in 0..16 {
for _x in 0..16 { for _x in 0..16 {
*pixels = to_rgb32([i, i, i]); *pixels = ARGBu8x4::from_rgb([i, i, i]);
i = i.wrapping_add(1); i = i.wrapping_add(1);
pixels = pixels.offset(1); pixels = pixels.offset(1);
} }
@ -634,12 +634,17 @@ fn generate_bitmap_with_varied_alpha(width: i32, height: i32) -> RgbaBitmap {
let y_third = height / 3; let y_third = height / 3;
let mut bitmap = RgbaBitmap::new(width as u32, height as u32).unwrap(); let mut bitmap = RgbaBitmap::new(width as u32, height as u32).unwrap();
bitmap.clear(0); // alpha=0 bitmap.clear(0.into()); // alpha=0
bitmap.filled_rect(0, 0, x_third, y_third, 0x330000aa); let color1 = ARGBu8x4::from_argb([0x33, 0x00, 0x00, 0xaa]);
bitmap.filled_rect(x_third * 2 + 1, y_third * 2 + 1, width - 1, height - 1, 0x6600aa00); let color2 = ARGBu8x4::from_argb([0x66, 0x00, 0xaa, 0x00]);
bitmap.filled_rect(0, y_third * 2 + 1, x_third, height - 1, 0x9900aaaa); let color3 = ARGBu8x4::from_argb([0x99, 0x00, 0xaa, 0xaa]);
bitmap.filled_rect(x_third * 2 + 1, 0, width - 1, y_third, 0xccaa0000); let color4 = ARGBu8x4::from_argb([0xcc, 0xaa, 0x00, 0x00]);
bitmap.filled_rect(0, 0, x_third, y_third, color1);
bitmap.filled_rect(x_third * 2 + 1, y_third * 2 + 1, width - 1, height - 1, color2);
bitmap.filled_rect(0, y_third * 2 + 1, x_third, height - 1, color3);
bitmap.filled_rect(x_third * 2 + 1, 0, width - 1, y_third, color4);
bitmap.filled_rect(x_third, y_third, x_third * 2 + 1, y_third * 2 + 1, COLOR_MAGENTA); bitmap.filled_rect(x_third, y_third, x_third * 2 + 1, y_third * 2 + 1, COLOR_MAGENTA);
bitmap.rect(0, 0, width - 1, height - 1, COLOR_BROWN); bitmap.rect(0, 0, width - 1, height - 1, COLOR_BROWN);
@ -651,12 +656,17 @@ fn generate_solid_bitmap_with_varied_alpha(width: i32, height: i32) -> RgbaBitma
let y_third = height / 3; let y_third = height / 3;
let mut bitmap = RgbaBitmap::new(width as u32, height as u32).unwrap(); let mut bitmap = RgbaBitmap::new(width as u32, height as u32).unwrap();
bitmap.clear(to_argb32([255, 0, 0, 0])); bitmap.clear(ARGBu8x4::from_argb([255, 0, 0, 0]));
bitmap.filled_rect(0, 0, x_third, y_third, 0x330000aa); let color1 = ARGBu8x4::from_argb([0x33, 0x00, 0x00, 0xaa]);
bitmap.filled_rect(x_third * 2 + 1, y_third * 2 + 1, width - 1, height - 1, 0x6600aa00); let color2 = ARGBu8x4::from_argb([0x66, 0x00, 0xaa, 0x00]);
bitmap.filled_rect(0, y_third * 2 + 1, x_third, height - 1, 0x9900aaaa); let color3 = ARGBu8x4::from_argb([0x99, 0x00, 0xaa, 0xaa]);
bitmap.filled_rect(x_third * 2 + 1, 0, width - 1, y_third, 0xccaa0000); let color4 = ARGBu8x4::from_argb([0xcc, 0xaa, 0x00, 0x00]);
bitmap.filled_rect(0, 0, x_third, y_third, color1);
bitmap.filled_rect(x_third * 2 + 1, y_third * 2 + 1, width - 1, height - 1, color2);
bitmap.filled_rect(0, y_third * 2 + 1, x_third, height - 1, color3);
bitmap.filled_rect(x_third * 2 + 1, 0, width - 1, y_third, color4);
bitmap.filled_rect(x_third, y_third, x_third * 2 + 1, y_third * 2 + 1, COLOR_MAGENTA); bitmap.filled_rect(x_third, y_third, x_third * 2 + 1, y_third * 2 + 1, COLOR_MAGENTA);
bitmap.rect(0, 0, width - 1, height - 1, COLOR_BROWN); bitmap.rect(0, 0, width - 1, height - 1, COLOR_BROWN);
@ -746,7 +756,7 @@ fn solid_tinted_blits() {
let bmp21 = generate_bitmap(21, 21); let bmp21 = generate_bitmap(21, 21);
let bmp3 = generate_bitmap(3, 3); let bmp3 = generate_bitmap(3, 3);
let method = SolidTinted(to_argb32([127, 155, 242, 21])); let method = SolidTinted(ARGBu8x4::from_argb([127, 155, 242, 21]));
let x = 40; let x = 40;
let y = 20; let y = 20;
@ -951,7 +961,7 @@ fn solid_flipped_tinted_blits() {
let bmp = generate_bitmap(16, 16); let bmp = generate_bitmap(16, 16);
let tint_color = to_argb32([127, 155, 242, 21]); let tint_color = ARGBu8x4::from_argb([127, 155, 242, 21]);
let x = 40; let x = 40;
let y = 20; let y = 20;
@ -1090,7 +1100,7 @@ fn transparent_blits() {
let bmp21 = generate_bitmap(21, 21); let bmp21 = generate_bitmap(21, 21);
let bmp3 = generate_bitmap(3, 3); let bmp3 = generate_bitmap(3, 3);
let method = Transparent(to_rgb32([0, 0, 0])); let method = Transparent(ARGBu8x4::from_rgb([0, 0, 0]));
let x = 40; let x = 40;
let y = 20; let y = 20;
@ -1161,8 +1171,10 @@ fn transparent_tinted_blits() {
let bmp21 = generate_bitmap(21, 21); let bmp21 = generate_bitmap(21, 21);
let bmp3 = generate_bitmap(3, 3); let bmp3 = generate_bitmap(3, 3);
let method = let method = TransparentTinted {
TransparentTinted { transparent_color: to_rgb32([0, 0, 0]), tint_color: to_argb32([127, 155, 242, 21]) }; transparent_color: ARGBu8x4::from_rgb([0, 0, 0]),
tint_color: ARGBu8x4::from_argb([127, 155, 242, 21]),
};
let x = 40; let x = 40;
let y = 20; let y = 20;
@ -1232,7 +1244,8 @@ fn blended_transparent_blits() {
let bmp21 = generate_solid_bitmap_with_varied_alpha(21, 21); let bmp21 = generate_solid_bitmap_with_varied_alpha(21, 21);
let bmp3 = generate_solid_bitmap_with_varied_alpha(3, 3); let bmp3 = generate_solid_bitmap_with_varied_alpha(3, 3);
let method = TransparentBlended { transparent_color: to_argb32([255, 0, 0, 0]), blend: BlendFunction::Blend }; let method =
TransparentBlended { transparent_color: ARGBu8x4::from_argb([255, 0, 0, 0]), blend: BlendFunction::Blend };
let x = 40; let x = 40;
let y = 20; let y = 20;
@ -1299,7 +1312,7 @@ fn transparent_flipped_blits() {
let mut screen = setup(); let mut screen = setup();
screen.clear(LIGHTER_BACKGROUND); screen.clear(LIGHTER_BACKGROUND);
let transparent_color = to_rgb32([0, 0, 0]); let transparent_color = ARGBu8x4::from_rgb([0, 0, 0]);
let bmp = generate_bitmap(16, 16); let bmp = generate_bitmap(16, 16);
@ -1368,8 +1381,8 @@ fn transparent_flipped_tinted_blits() {
let mut screen = setup(); let mut screen = setup();
screen.clear(LIGHTER_BACKGROUND); screen.clear(LIGHTER_BACKGROUND);
let transparent_color = to_rgb32([0, 0, 0]); let transparent_color = ARGBu8x4::from_rgb([0, 0, 0]);
let tint_color = to_argb32([127, 155, 242, 21]); let tint_color = ARGBu8x4::from_argb([127, 155, 242, 21]);
let bmp = generate_bitmap(16, 16); let bmp = generate_bitmap(16, 16);
@ -1439,7 +1452,7 @@ fn blended_transparent_flipped_blits() {
let bmp = generate_solid_bitmap_with_varied_alpha(16, 16); let bmp = generate_solid_bitmap_with_varied_alpha(16, 16);
let transparent_color = to_argb32([255, 0, 0, 0]); let transparent_color = ARGBu8x4::from_argb([255, 0, 0, 0]);
let blend = BlendFunction::Blend; let blend = BlendFunction::Blend;
let x = 40; let x = 40;
@ -1507,7 +1520,7 @@ fn transparent_single_blits() {
let mut screen = setup(); let mut screen = setup();
screen.clear(LIGHTER_BACKGROUND); screen.clear(LIGHTER_BACKGROUND);
let transparent_color = to_rgb32([0, 0, 0]); let transparent_color = ARGBu8x4::from_rgb([0, 0, 0]);
let bmp = generate_bitmap(16, 16); let bmp = generate_bitmap(16, 16);
@ -1580,7 +1593,7 @@ fn transparent_flipped_single_blits() {
let mut screen = setup(); let mut screen = setup();
screen.clear(LIGHTER_BACKGROUND); screen.clear(LIGHTER_BACKGROUND);
let transparent_color = to_rgb32([0, 0, 0]); let transparent_color = ARGBu8x4::from_rgb([0, 0, 0]);
let bmp = generate_bitmap(16, 16); let bmp = generate_bitmap(16, 16);
@ -1719,7 +1732,7 @@ fn rotozoom_tinted_blits() {
let bmp = generate_bitmap(16, 16); let bmp = generate_bitmap(16, 16);
let tint_color = to_argb32([127, 155, 242, 21]); let tint_color = ARGBu8x4::from_argb([127, 155, 242, 21]);
let x = 40; let x = 40;
let y = 20; let y = 20;
@ -1857,7 +1870,7 @@ fn rotozoom_transparent_blits() {
let mut screen = setup(); let mut screen = setup();
screen.clear(LIGHTER_BACKGROUND); screen.clear(LIGHTER_BACKGROUND);
let transparent_color = to_rgb32([0, 0, 0]); let transparent_color = ARGBu8x4::from_rgb([0, 0, 0]);
let bmp = generate_bitmap(16, 16); let bmp = generate_bitmap(16, 16);
@ -1928,8 +1941,8 @@ fn rotozoom_transparent_tinted_blits() {
let mut screen = setup(); let mut screen = setup();
screen.clear(LIGHTER_BACKGROUND); screen.clear(LIGHTER_BACKGROUND);
let transparent_color = to_rgb32([0, 0, 0]); let transparent_color = ARGBu8x4::from_rgb([0, 0, 0]);
let tint_color = to_argb32([127, 155, 242, 21]); let tint_color = ARGBu8x4::from_argb([127, 155, 242, 21]);
let bmp = generate_bitmap(16, 16); let bmp = generate_bitmap(16, 16);
@ -2001,7 +2014,7 @@ fn blended_rotozoom_transparent_blits() {
let bmp = generate_solid_bitmap_with_varied_alpha(16, 16); let bmp = generate_solid_bitmap_with_varied_alpha(16, 16);
let transparent_color = to_argb32([255, 0, 0, 0]); let transparent_color = ARGBu8x4::from_argb([255, 0, 0, 0]);
let blend = BlendFunction::Blend; let blend = BlendFunction::Blend;
let x = 40; let x = 40;
@ -2098,34 +2111,34 @@ fn blend_function_tinted_blend() {
let bmp_solid_with_varied_alpha = generate_solid_bitmap_with_varied_alpha(32, 32); let bmp_solid_with_varied_alpha = generate_solid_bitmap_with_varied_alpha(32, 32);
let bmp_with_varied_alpha = generate_bitmap_with_varied_alpha(32, 32); let bmp_with_varied_alpha = generate_bitmap_with_varied_alpha(32, 32);
let method = RgbaBlitMethod::SolidBlended(BlendFunction::TintedBlend(to_argb32([255, 155, 242, 21]))); let method = RgbaBlitMethod::SolidBlended(BlendFunction::TintedBlend(ARGBu8x4::from_argb([255, 155, 242, 21])));
screen.blit(method.clone(), &bmp_solid, 10, 5); screen.blit(method.clone(), &bmp_solid, 10, 5);
screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 5); screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 5);
screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 5); screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 5);
let method = RgbaBlitMethod::SolidBlended(BlendFunction::TintedBlend(to_argb32([127, 155, 242, 21]))); let method = RgbaBlitMethod::SolidBlended(BlendFunction::TintedBlend(ARGBu8x4::from_argb([127, 155, 242, 21])));
screen.blit(method.clone(), &bmp_solid, 10, 40); screen.blit(method.clone(), &bmp_solid, 10, 40);
screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 40); screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 40);
screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 40); screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 40);
let method = RgbaBlitMethod::SolidBlended(BlendFunction::TintedBlend(to_argb32([0, 155, 242, 21]))); let method = RgbaBlitMethod::SolidBlended(BlendFunction::TintedBlend(ARGBu8x4::from_argb([0, 155, 242, 21])));
screen.blit(method.clone(), &bmp_solid, 10, 75); screen.blit(method.clone(), &bmp_solid, 10, 75);
screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 75); screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 75);
screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 75); screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 75);
////// //////
let method = RgbaBlitMethod::SolidBlended(BlendFunction::TintedBlend(to_argb32([255, 155, 242, 21]))); let method = RgbaBlitMethod::SolidBlended(BlendFunction::TintedBlend(ARGBu8x4::from_argb([255, 155, 242, 21])));
screen.blit(method.clone(), &bmp_solid, 10, 125); screen.blit(method.clone(), &bmp_solid, 10, 125);
screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 125); screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 125);
screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 125); screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 125);
let method = RgbaBlitMethod::SolidBlended(BlendFunction::TintedBlend(to_argb32([127, 155, 242, 21]))); let method = RgbaBlitMethod::SolidBlended(BlendFunction::TintedBlend(ARGBu8x4::from_argb([127, 155, 242, 21])));
screen.blit(method.clone(), &bmp_solid, 10, 160); screen.blit(method.clone(), &bmp_solid, 10, 160);
screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 160); screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 160);
screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 160); screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 160);
let method = RgbaBlitMethod::SolidBlended(BlendFunction::TintedBlend(to_argb32([0, 155, 242, 21]))); let method = RgbaBlitMethod::SolidBlended(BlendFunction::TintedBlend(ARGBu8x4::from_argb([0, 155, 242, 21])));
screen.blit(method.clone(), &bmp_solid, 10, 195); screen.blit(method.clone(), &bmp_solid, 10, 195);
screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 195); screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 195);
screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 195); screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 195);
@ -2192,34 +2205,34 @@ fn blend_function_multiplied_blend() {
let bmp_solid_with_varied_alpha = generate_solid_bitmap_with_varied_alpha(32, 32); let bmp_solid_with_varied_alpha = generate_solid_bitmap_with_varied_alpha(32, 32);
let bmp_with_varied_alpha = generate_bitmap_with_varied_alpha(32, 32); let bmp_with_varied_alpha = generate_bitmap_with_varied_alpha(32, 32);
let method = RgbaBlitMethod::SolidBlended(BlendFunction::MultipliedBlend(to_argb32([255, 242, 29, 81]))); let method = RgbaBlitMethod::SolidBlended(BlendFunction::MultipliedBlend(ARGBu8x4::from_argb([255, 242, 29, 81])));
screen.blit(method.clone(), &bmp_solid, 10, 5); screen.blit(method.clone(), &bmp_solid, 10, 5);
screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 5); screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 5);
screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 5); screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 5);
let method = RgbaBlitMethod::SolidBlended(BlendFunction::MultipliedBlend(to_argb32([127, 242, 29, 81]))); let method = RgbaBlitMethod::SolidBlended(BlendFunction::MultipliedBlend(ARGBu8x4::from_argb([127, 242, 29, 81])));
screen.blit(method.clone(), &bmp_solid, 10, 40); screen.blit(method.clone(), &bmp_solid, 10, 40);
screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 40); screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 40);
screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 40); screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 40);
let method = RgbaBlitMethod::SolidBlended(BlendFunction::MultipliedBlend(to_argb32([0, 242, 29, 81]))); let method = RgbaBlitMethod::SolidBlended(BlendFunction::MultipliedBlend(ARGBu8x4::from_argb([0, 242, 29, 81])));
screen.blit(method.clone(), &bmp_solid, 10, 75); screen.blit(method.clone(), &bmp_solid, 10, 75);
screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 75); screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 75);
screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 75); screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 75);
////// //////
let method = RgbaBlitMethod::SolidBlended(BlendFunction::MultipliedBlend(to_argb32([255, 242, 29, 81]))); let method = RgbaBlitMethod::SolidBlended(BlendFunction::MultipliedBlend(ARGBu8x4::from_argb([255, 242, 29, 81])));
screen.blit(method.clone(), &bmp_solid, 10, 125); screen.blit(method.clone(), &bmp_solid, 10, 125);
screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 125); screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 125);
screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 125); screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 125);
let method = RgbaBlitMethod::SolidBlended(BlendFunction::MultipliedBlend(to_argb32([127, 242, 29, 81]))); let method = RgbaBlitMethod::SolidBlended(BlendFunction::MultipliedBlend(ARGBu8x4::from_argb([127, 242, 29, 81])));
screen.blit(method.clone(), &bmp_solid, 10, 160); screen.blit(method.clone(), &bmp_solid, 10, 160);
screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 160); screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 160);
screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 160); screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 160);
let method = RgbaBlitMethod::SolidBlended(BlendFunction::MultipliedBlend(to_argb32([0, 242, 29, 81]))); let method = RgbaBlitMethod::SolidBlended(BlendFunction::MultipliedBlend(ARGBu8x4::from_argb([0, 242, 29, 81])));
screen.blit(method.clone(), &bmp_solid, 10, 195); screen.blit(method.clone(), &bmp_solid, 10, 195);
screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 195); screen.blit(method.clone(), &bmp_solid_with_varied_alpha, 100, 195);
screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 195); screen.blit(method.clone(), &bmp_with_varied_alpha, 200, 195);
@ -2478,15 +2491,16 @@ fn get_quad(
let positions_2 = [top_left, bottom_right, top_right]; let positions_2 = [top_left, bottom_right, top_right];
let texcoords_1 = [Vector2::new(0.0, 0.0), Vector2::new(0.0, 1.0), Vector2::new(1.0, 1.0)]; let texcoords_1 = [Vector2::new(0.0, 0.0), Vector2::new(0.0, 1.0), Vector2::new(1.0, 1.0)];
let texcoords_2 = [Vector2::new(0.0, 0.0), Vector2::new(1.0, 1.0), Vector2::new(1.0, 0.0)]; let texcoords_2 = [Vector2::new(0.0, 0.0), Vector2::new(1.0, 1.0), Vector2::new(1.0, 0.0)];
let single_color = to_argb32([128, 255, 0, 255]); let single_color = ARGBu8x4::from_argb([128, 255, 0, 255]);
let colors_1 = [to_rgb32([255, 0, 0]), to_rgb32([0, 255, 0]), to_rgb32([0, 0, 255])]; let colors_1 = [ARGBu8x4::from_rgb([255, 0, 0]), ARGBu8x4::from_rgb([0, 255, 0]), ARGBu8x4::from_rgb([0, 0, 255])];
let colors_2 = [to_rgb32([255, 0, 0]), to_rgb32([0, 0, 255]), to_rgb32([255, 255, 255])]; let colors_2 =
let tint_color = to_argb32([128, 192, 47, 160]); [ARGBu8x4::from_rgb([255, 0, 0]), ARGBu8x4::from_rgb([0, 0, 255]), ARGBu8x4::from_rgb([255, 255, 255])];
let tint_color = ARGBu8x4::from_argb([128, 192, 47, 160]);
match mode { match mode {
TriangleType::Solid => [ TriangleType::Solid => [
RgbaTriangle2d::Solid { position: positions_1, color: to_rgb32([255, 0, 255]) }, RgbaTriangle2d::Solid { position: positions_1, color: ARGBu8x4::from_rgb([255, 0, 255]) },
RgbaTriangle2d::Solid { position: positions_2, color: to_rgb32([255, 0, 255]) }, RgbaTriangle2d::Solid { position: positions_2, color: ARGBu8x4::from_rgb([255, 0, 255]) },
], ],
TriangleType::SolidBlended => [ TriangleType::SolidBlended => [
RgbaTriangle2d::SolidBlended { position: positions_1, color: single_color, blend: BlendFunction::Blend }, RgbaTriangle2d::SolidBlended { position: positions_1, color: single_color, blend: BlendFunction::Blend },

View file

@ -2,7 +2,7 @@ use crate::BACKGROUND_COLOR;
use ggdt::prelude::*; use ggdt::prelude::*;
fn display_raw_keyboard_state(system: &mut System<Standard>, x: i32, y: i32) { fn display_raw_keyboard_state(system: &mut System<Standard>, x: i32, y: i32) {
let font_opts = FontRenderOpts::Color(0xffffffff); let font_opts = FontRenderOpts::Color(COLOR_BRIGHT_WHITE);
let font = &system.res.font; let font = &system.res.font;
system.res.video.print_string("Raw Keyboard State", x, x, font_opts, font); system.res.video.print_string("Raw Keyboard State", x, x, font_opts, font);
@ -40,7 +40,7 @@ fn display_key_state(key: Scancode, system: &mut System<Standard>, x: i32, y: i3
), ),
x, x,
y, y,
FontRenderOpts::Color(0xffffffff), FontRenderOpts::Color(COLOR_BRIGHT_WHITE),
&system.res.font, &system.res.font,
); );
} }
@ -87,7 +87,7 @@ fn keyboard_state() {
display_key_state(*key, &mut system, 2, 160 + (idx as i32 * 10)); display_key_state(*key, &mut system, 2, 160 + (idx as i32 * 10));
} }
system.res.video.set_pixel(system.res.mouse.x(), system.res.mouse.y(), to_rgb32([255, 0, 255])); system.res.video.set_pixel(system.res.mouse.x(), system.res.mouse.y(), COLOR_BRIGHT_MAGENTA);
system.display().unwrap(); system.display().unwrap();
} }

View file

@ -22,7 +22,7 @@ mod system_resources_standard;
use ggdt::prelude::*; use ggdt::prelude::*;
const BACKGROUND_COLOR: u32 = 0xff2c3041; const BACKGROUND_COLOR: ARGBu8x4 = ARGBu8x4::from_rgb([0x2c, 0x30, 0x41]);
fn draw_base_screen<BitmapType>( fn draw_base_screen<BitmapType>(
dest: &mut BitmapType, dest: &mut BitmapType,

View file

@ -3,7 +3,7 @@ use ggdt::prelude::*;
fn display_mouse_state(system: &mut System<Standard>) { fn display_mouse_state(system: &mut System<Standard>) {
let font = &system.res.font; let font = &system.res.font;
let font_opts = FontRenderOpts::Color(0xffffffff); let font_opts = FontRenderOpts::Color(COLOR_BRIGHT_WHITE);
system.res.video.print_string( system.res.video.print_string(
&format!( &format!(
@ -62,7 +62,7 @@ fn mouse_with_custom_cursor() {
system.update().unwrap(); system.update().unwrap();
display_mouse_state(&mut system); display_mouse_state(&mut system);
system.res.video.set_pixel(system.res.mouse.x(), system.res.mouse.y(), to_rgb32([255, 0, 255])); system.res.video.set_pixel(system.res.mouse.x(), system.res.mouse.y(), COLOR_BRIGHT_MAGENTA);
system.display().unwrap(); system.display().unwrap();
} }
@ -91,7 +91,7 @@ fn mouse_with_os_cursor() {
system.update().unwrap(); system.update().unwrap();
display_mouse_state(&mut system); display_mouse_state(&mut system);
system.res.video.set_pixel(system.res.mouse.x(), system.res.mouse.y(), to_rgb32([255, 0, 255])); system.res.video.set_pixel(system.res.mouse.x(), system.res.mouse.y(), COLOR_BRIGHT_MAGENTA);
system.display().unwrap(); system.display().unwrap();
} }

View file

@ -40,7 +40,7 @@ fn system_events_display() {
&format!("{:?}", event), &format!("{:?}", event),
2, 2,
system.res.video.height() as i32 - 10 - (idx as i32 * 10), system.res.video.height() as i32 - 10 - (idx as i32 * 10),
FontRenderOpts::Color(to_rgb32([255, 255, 255])), FontRenderOpts::Color(COLOR_BRIGHT_WHITE),
&system.res.font, &system.res.font,
); );
} }

View file

@ -27,8 +27,8 @@ fn simple_main_loop(mut system: System<Standard>) {
draw_base_screen( draw_base_screen(
&mut system.res.video, &mut system.res.video,
to_rgb32([32, 32, 32]), ARGBu8x4::from_rgb([32, 32, 32]),
to_rgb32([44, 44, 44]), ARGBu8x4::from_rgb([44, 44, 44]),
COLOR_BRIGHT_WHITE, COLOR_BRIGHT_WHITE,
COLOR_BRIGHT_RED, COLOR_BRIGHT_RED,
); );

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View file

@ -1,4 +1,4 @@
use ggdt::graphics::{to_argb32, BlendFunction, RgbaBitmap, RgbaPixelFormat}; use ggdt::graphics::{ARGBu8x4, BlendFunction, RgbaBitmap, RgbaPixelFormat};
use ggdt::math::{Rect, Vector2}; use ggdt::math::{Rect, Vector2};
use imgui::internal::RawWrapper; use imgui::internal::RawWrapper;
@ -67,9 +67,9 @@ impl Renderer {
Vector2::new(v3.uv[0], v3.uv[1]), Vector2::new(v3.uv[0], v3.uv[1]),
], ],
&[ &[
to_argb32([v2.col[3], v2.col[0], v2.col[1], v2.col[2]]), ARGBu8x4::from_argb([v2.col[3], v2.col[0], v2.col[1], v2.col[2]]),
to_argb32([v1.col[3], v1.col[0], v1.col[1], v1.col[2]]), ARGBu8x4::from_argb([v1.col[3], v1.col[0], v1.col[1], v1.col[2]]),
to_argb32([v3.col[3], v3.col[0], v3.col[1], v3.col[2]]), ARGBu8x4::from_argb([v3.col[3], v3.col[0], v3.col[1], v3.col[2]]),
], ],
bitmap, bitmap,
BlendFunction::Blend, BlendFunction::Blend,