From e4608dee822995fe1c77dc94625c3f0af41bdd0a Mon Sep 17 00:00:00 2001 From: gered Date: Sun, 26 Mar 2023 18:34:58 -0400 Subject: [PATCH] add visual tests for RgbaBitmap color tinted blit methods --- ggdt/tests/graphics_rgba.rs | 411 ++++++++++++++++++ ggdt/tests/ref/rgba/rotozoom_tinted_blits.png | Bin 0 -> 3064 bytes .../rotozoom_transparent_tinted_blits.png | Bin 0 -> 3219 bytes .../ref/rgba/solid_flipped_tinted_blits.png | Bin 0 -> 1914 bytes ggdt/tests/ref/rgba/solid_tinted_blits.png | Bin 0 -> 1908 bytes .../rgba/transparent_flipped_tinted_blits.png | Bin 0 -> 1963 bytes .../ref/rgba/transparent_tinted_blits.png | Bin 0 -> 2003 bytes 7 files changed, 411 insertions(+) create mode 100644 ggdt/tests/ref/rgba/rotozoom_tinted_blits.png create mode 100644 ggdt/tests/ref/rgba/rotozoom_transparent_tinted_blits.png create mode 100644 ggdt/tests/ref/rgba/solid_flipped_tinted_blits.png create mode 100644 ggdt/tests/ref/rgba/solid_tinted_blits.png create mode 100644 ggdt/tests/ref/rgba/transparent_flipped_tinted_blits.png create mode 100644 ggdt/tests/ref/rgba/transparent_tinted_blits.png diff --git a/ggdt/tests/graphics_rgba.rs b/ggdt/tests/graphics_rgba.rs index 40a9a1f..52f0ce5 100644 --- a/ggdt/tests/graphics_rgba.rs +++ b/ggdt/tests/graphics_rgba.rs @@ -697,6 +697,75 @@ fn solid_blits() { assert!(verify_visual(&screen, &path), "bitmap differs from source image: {:?}", path); } +#[test] +fn solid_tinted_blits() { + use RgbaBlitMethod::*; + + let mut screen = setup(); + screen.clear(LIGHTER_BACKGROUND); + + let bmp16 = generate_bitmap(16, 16); + let bmp12 = generate_bitmap(12, 12); + let bmp21 = generate_bitmap(21, 21); + let bmp3 = generate_bitmap(3, 3); + + let method = SolidTinted(to_argb32(127, 155, 242, 21)); + + let x = 40; + let y = 20; + screen.blit(method.clone(), &bmp16, x + 16, y + 48); + screen.blit(method.clone(), &bmp12, x + 80, y + 48); + screen.blit(method.clone(), &bmp21, x + 144, y + 48); + screen.blit(method.clone(), &bmp3, x + 208, y + 48); + + let x = 40; + let y = 110; + unsafe { + screen.blit_unchecked(method.clone(), &bmp16, x + 16, y + 48); + screen.blit_unchecked(method.clone(), &bmp12, x + 80, y + 48); + screen.blit_unchecked(method.clone(), &bmp21, x + 144, y + 48); + screen.blit_unchecked(method.clone(), &bmp3, x + 208, y + 48); + } + + ////// + + screen.blit(method.clone(), &bmp16, -3, 46); + screen.blit(method.clone(), &bmp16, -4, 76); + screen.blit(method.clone(), &bmp16, -8, 106); + screen.blit(method.clone(), &bmp16, -12, 136); + screen.blit(method.clone(), &bmp16, -13, 166); + screen.blit(method.clone(), &bmp16, -14, 196); + screen.blit(method.clone(), &bmp16, -16, 226); + + screen.blit(method.clone(), &bmp16, 46, -3); + screen.blit(method.clone(), &bmp16, 76, -4); + screen.blit(method.clone(), &bmp16, 106, -8); + screen.blit(method.clone(), &bmp16, 136, -12); + screen.blit(method.clone(), &bmp16, 166, -13); + screen.blit(method.clone(), &bmp16, 196, -14); + screen.blit(method.clone(), &bmp16, 226, -16); + + screen.blit(method.clone(), &bmp16, 307, 46); + screen.blit(method.clone(), &bmp16, 308, 76); + screen.blit(method.clone(), &bmp16, 312, 106); + screen.blit(method.clone(), &bmp16, 316, 136); + screen.blit(method.clone(), &bmp16, 317, 166); + screen.blit(method.clone(), &bmp16, 318, 196); + screen.blit(method.clone(), &bmp16, 320, 226); + + screen.blit(method.clone(), &bmp16, 46, 227); + screen.blit(method.clone(), &bmp16, 76, 228); + screen.blit(method.clone(), &bmp16, 106, 232); + screen.blit(method.clone(), &bmp16, 136, 236); + screen.blit(method.clone(), &bmp16, 166, 237); + screen.blit(method.clone(), &bmp16, 196, 238); + screen.blit(method.clone(), &bmp16, 226, 240); + + let path = reference_file(Path::new("solid_tinted_blits.png")); + //screen.to_png_file(path.as_path(), PngFormat::RGBA).unwrap(); + assert!(verify_visual(&screen, &path), "bitmap differs from source image: {:?}", path); +} + #[test] fn blended_solid_blits() { use RgbaBlitMethod::*; @@ -829,6 +898,72 @@ fn solid_flipped_blits() { assert!(verify_visual(&screen, &path), "bitmap differs from source image: {:?}", path); } +#[test] +fn solid_flipped_tinted_blits() { + use RgbaBlitMethod::*; + + let mut screen = setup(); + screen.clear(LIGHTER_BACKGROUND); + + let bmp = generate_bitmap(16, 16); + + let tint_color = to_argb32(127, 155, 242, 21); + + let x = 40; + let y = 20; + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, x + 16, y + 48); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, x + 80, y + 48); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, x + 144, y + 48); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: true }, &bmp, x + 208, y + 48); + + let x = 40; + let y = 110; + unsafe { + screen.blit_unchecked(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, x + 16, y + 48); + screen.blit_unchecked(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, x + 80, y + 48); + screen.blit_unchecked(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, x + 144, y + 48); + screen.blit_unchecked(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: true }, &bmp, x + 208, y + 48); + } + + ////// + + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, -3, 46); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, -4, 76); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, -8, 106); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: true }, &bmp, -12, 136); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, -13, 166); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, -14, 196); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, -16, 226); + + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, 46, -3); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, 76, -4); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, 106, -8); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: true }, &bmp, 136, -12); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, 166, -13); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, 196, -14); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, 226, -16); + + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, 307, 46); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, 308, 76); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, 312, 106); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: true }, &bmp, 316, 136); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, 317, 166); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, 318, 196); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, 320, 226); + + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, 46, 227); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, 76, 228); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, 106, 232); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: true }, &bmp, 136, 236); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, 166, 237); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, 196, 238); + screen.blit(SolidFlippedTinted { tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, 226, 240); + + let path = reference_file(Path::new("solid_flipped_tinted_blits.png")); + //screen.to_png_file(path.as_path(), PngFormat::RGBA).unwrap(); + assert!(verify_visual(&screen, &path), "bitmap differs from source image: {:?}", path); +} + #[test] fn blended_solid_flipped_blits() { use RgbaBlitMethod::*; @@ -963,6 +1098,78 @@ fn transparent_blits() { assert!(verify_visual(&screen, &path), "bitmap differs from source image: {:?}", path); } +#[test] +fn transparent_tinted_blits() { + use RgbaBlitMethod::*; + + let mut screen = setup(); + screen.clear(LIGHTER_BACKGROUND); + + let bmp16 = generate_bitmap(16, 16); + let bmp12 = generate_bitmap(12, 12); + let bmp21 = generate_bitmap(21, 21); + let bmp3 = generate_bitmap(3, 3); + + let method = TransparentTinted { + transparent_color: to_rgb32(0, 0, 0), + tint_color: to_argb32(127, 155, 242, 21) + }; + + let x = 40; + let y = 20; + screen.blit(method.clone(), &bmp16, x + 16, y + 48); + screen.blit(method.clone(), &bmp12, x + 80, y + 48); + screen.blit(method.clone(), &bmp21, x + 144, y + 48); + screen.blit(method.clone(), &bmp3, x + 208, y + 48); + + let x = 40; + let y = 110; + unsafe { + screen.blit_unchecked(method.clone(), &bmp16, x + 16, y + 48); + screen.blit_unchecked(method.clone(), &bmp12, x + 80, y + 48); + screen.blit_unchecked(method.clone(), &bmp21, x + 144, y + 48); + screen.blit_unchecked(method.clone(), &bmp3, x + 208, y + 48); + } + + ////// + + screen.blit(method.clone(), &bmp16, -3, 46); + screen.blit(method.clone(), &bmp16, -4, 76); + screen.blit(method.clone(), &bmp16, -8, 106); + screen.blit(method.clone(), &bmp16, -12, 136); + screen.blit(method.clone(), &bmp16, -13, 166); + screen.blit(method.clone(), &bmp16, -14, 196); + screen.blit(method.clone(), &bmp16, -16, 226); + + screen.blit(method.clone(), &bmp16, 46, -3); + screen.blit(method.clone(), &bmp16, 76, -4); + screen.blit(method.clone(), &bmp16, 106, -8); + screen.blit(method.clone(), &bmp16, 136, -12); + screen.blit(method.clone(), &bmp16, 166, -13); + screen.blit(method.clone(), &bmp16, 196, -14); + screen.blit(method.clone(), &bmp16, 226, -16); + + screen.blit(method.clone(), &bmp16, 307, 46); + screen.blit(method.clone(), &bmp16, 308, 76); + screen.blit(method.clone(), &bmp16, 312, 106); + screen.blit(method.clone(), &bmp16, 316, 136); + screen.blit(method.clone(), &bmp16, 317, 166); + screen.blit(method.clone(), &bmp16, 318, 196); + screen.blit(method.clone(), &bmp16, 320, 226); + + screen.blit(method.clone(), &bmp16, 46, 227); + screen.blit(method.clone(), &bmp16, 76, 228); + screen.blit(method.clone(), &bmp16, 106, 232); + screen.blit(method.clone(), &bmp16, 136, 236); + screen.blit(method.clone(), &bmp16, 166, 237); + screen.blit(method.clone(), &bmp16, 196, 238); + screen.blit(method.clone(), &bmp16, 226, 240); + + let path = reference_file(Path::new("transparent_tinted_blits.png")); + //screen.to_png_file(path.as_path(), PngFormat::RGBA).unwrap(); + assert!(verify_visual(&screen, &path), "bitmap differs from source image: {:?}", path); +} + #[test] fn blended_transparent_blits() { use RgbaBlitMethod::*; @@ -1097,6 +1304,73 @@ fn transparent_flipped_blits() { assert!(verify_visual(&screen, &path), "bitmap differs from source image: {:?}", path); } +#[test] +fn transparent_flipped_tinted_blits() { + use RgbaBlitMethod::*; + + let mut screen = setup(); + screen.clear(LIGHTER_BACKGROUND); + + let transparent_color = to_rgb32(0, 0, 0); + let tint_color = to_argb32(127, 155, 242, 21); + + let bmp = generate_bitmap(16, 16); + + let x = 40; + let y = 20; + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, x + 16, y + 48); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, x + 80, y + 48); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, x + 144, y + 48); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: true }, &bmp, x + 208, y + 48); + + let x = 40; + let y = 110; + unsafe { + screen.blit_unchecked(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, x + 16, y + 48); + screen.blit_unchecked(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, x + 80, y + 48); + screen.blit_unchecked(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, x + 144, y + 48); + screen.blit_unchecked(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: true }, &bmp, x + 208, y + 48); + } + + ////// + + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, -3, 46); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, -4, 76); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, -8, 106); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: true }, &bmp, -12, 136); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, -13, 166); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, -14, 196); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, -16, 226); + + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, 46, -3); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, 76, -4); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, 106, -8); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: true }, &bmp, 136, -12); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, 166, -13); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, 196, -14); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, 226, -16); + + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, 307, 46); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, 308, 76); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, 312, 106); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: true }, &bmp, 316, 136); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, 317, 166); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, 318, 196); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, 320, 226); + + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, 46, 227); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, 76, 228); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, 106, 232); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: true }, &bmp, 136, 236); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: false }, &bmp, 166, 237); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: true, vertical_flip: false }, &bmp, 196, 238); + screen.blit(TransparentFlippedTinted { transparent_color, tint_color, horizontal_flip: false, vertical_flip: true }, &bmp, 226, 240); + + let path = reference_file(Path::new("transparent_flipped_tinted_blits.png")); + //screen.to_png_file(path.as_path(), PngFormat::RGBA).unwrap(); + assert!(verify_visual(&screen, &path), "bitmap differs from source image: {:?}", path); +} + #[test] fn blended_transparent_flipped_blits() { use RgbaBlitMethod::*; @@ -1365,6 +1639,74 @@ fn rotozoom_blits() { assert!(verify_visual(&screen, &path), "bitmap differs from source image: {:?}", path); } +#[test] +fn rotozoom_tinted_blits() { + use RgbaBlitMethod::*; + + let mut screen = setup(); + screen.clear(LIGHTER_BACKGROUND); + + let bmp = generate_bitmap(16, 16); + + let tint_color = to_argb32(127, 155, 242, 21); + + let x = 40; + let y = 20; + screen.blit(RotoZoomTinted { tint_color, angle: 1.3, scale_x: 1.0, scale_y: 1.0 }, &bmp, x + 16, y + 48); + screen.blit(RotoZoomTinted { tint_color, angle: 0.3, scale_x: 1.5, scale_y: 1.0 }, &bmp, x + 80, y + 48); + screen.blit(RotoZoomTinted { tint_color, angle: 0.6, scale_x: 1.0, scale_y: 1.5 }, &bmp, x + 144, y + 48); + screen.blit(RotoZoomTinted { tint_color, angle: 2.0, scale_x: 0.7, scale_y: 0.7 }, &bmp, x + 208, y + 48); + + let x = 40; + let y = 110; + unsafe { + screen.blit_unchecked(RotoZoomTinted { tint_color, angle: 1.3, scale_x: 1.0, scale_y: 1.0 }, &bmp, x + 16, y + 48); + screen.blit_unchecked(RotoZoomTinted { tint_color, angle: 0.3, scale_x: 1.5, scale_y: 1.0 }, &bmp, x + 80, y + 48); + screen.blit_unchecked(RotoZoomTinted { tint_color, angle: 0.6, scale_x: 1.0, scale_y: 1.5 }, &bmp, x + 144, y + 48); + screen.blit_unchecked(RotoZoomTinted { tint_color, angle: 2.0, scale_x: 0.7, scale_y: 0.7 }, &bmp, x + 208, y + 48); + } + + ////// + + let method = RotoZoomTinted { tint_color, angle: 1.3, scale_x: 1.0, scale_y: 1.0 }; + + screen.blit(method.clone(), &bmp, -3, 46); + screen.blit(method.clone(), &bmp, -4, 76); + screen.blit(method.clone(), &bmp, -8, 106); + screen.blit(method.clone(), &bmp, -12, 136); + screen.blit(method.clone(), &bmp, -13, 166); + screen.blit(method.clone(), &bmp, -14, 196); + screen.blit(method.clone(), &bmp, -16, 226); + + screen.blit(method.clone(), &bmp, 46, -3); + screen.blit(method.clone(), &bmp, 76, -4); + screen.blit(method.clone(), &bmp, 106, -8); + screen.blit(method.clone(), &bmp, 136, -12); + screen.blit(method.clone(), &bmp, 166, -13); + screen.blit(method.clone(), &bmp, 196, -14); + screen.blit(method.clone(), &bmp, 226, -16); + + screen.blit(method.clone(), &bmp, 307, 46); + screen.blit(method.clone(), &bmp, 308, 76); + screen.blit(method.clone(), &bmp, 312, 106); + screen.blit(method.clone(), &bmp, 316, 136); + screen.blit(method.clone(), &bmp, 317, 166); + screen.blit(method.clone(), &bmp, 318, 196); + screen.blit(method.clone(), &bmp, 320, 226); + + screen.blit(method.clone(), &bmp, 46, 227); + screen.blit(method.clone(), &bmp, 76, 228); + screen.blit(method.clone(), &bmp, 106, 232); + screen.blit(method.clone(), &bmp, 136, 236); + screen.blit(method.clone(), &bmp, 166, 237); + screen.blit(method.clone(), &bmp, 196, 238); + screen.blit(method.clone(), &bmp, 226, 240); + + let path = reference_file(Path::new("rotozoom_tinted_blits.png")); + //screen.to_png_file(path.as_path(), PngFormat::RGBA).unwrap(); + assert!(verify_visual(&screen, &path), "bitmap differs from source image: {:?}", path); +} + #[test] fn blended_rotozoom_blits() { use RgbaBlitMethod::*; @@ -1500,6 +1842,75 @@ fn rotozoom_transparent_blits() { assert!(verify_visual(&screen, &path), "bitmap differs from source image: {:?}", path); } +#[test] +fn rotozoom_transparent_tinted_blits() { + use RgbaBlitMethod::*; + + let mut screen = setup(); + screen.clear(LIGHTER_BACKGROUND); + + let transparent_color = to_rgb32(0, 0, 0); + let tint_color = to_argb32(127, 155, 242, 21); + + let bmp = generate_bitmap(16, 16); + + let x = 40; + let y = 20; + screen.blit(RotoZoomTransparentTinted { transparent_color, tint_color, angle: 1.3, scale_x: 1.0, scale_y: 1.0 }, &bmp, x + 16, y + 48); + screen.blit(RotoZoomTransparentTinted { transparent_color, tint_color, angle: 0.3, scale_x: 1.5, scale_y: 1.0 }, &bmp, x + 80, y + 48); + screen.blit(RotoZoomTransparentTinted { transparent_color, tint_color, angle: 0.6, scale_x: 1.0, scale_y: 1.5 }, &bmp, x + 144, y + 48); + screen.blit(RotoZoomTransparentTinted { transparent_color, tint_color, angle: 2.0, scale_x: 0.7, scale_y: 0.7 }, &bmp, x + 208, y + 48); + + let x = 40; + let y = 110; + unsafe { + screen.blit_unchecked(RotoZoomTransparentTinted { transparent_color, tint_color, angle: 1.3, scale_x: 1.0, scale_y: 1.0 }, &bmp, x + 16, y + 48); + screen.blit_unchecked(RotoZoomTransparentTinted { transparent_color, tint_color, angle: 0.3, scale_x: 1.5, scale_y: 1.0 }, &bmp, x + 80, y + 48); + screen.blit_unchecked(RotoZoomTransparentTinted { transparent_color, tint_color, angle: 0.6, scale_x: 1.0, scale_y: 1.5 }, &bmp, x + 144, y + 48); + screen.blit_unchecked(RotoZoomTransparentTinted { transparent_color, tint_color, angle: 2.0, scale_x: 0.7, scale_y: 0.7 }, &bmp, x + 208, y + 48); + } + + ////// + + let method = RotoZoomTransparentTinted { transparent_color, tint_color, angle: 1.3, scale_x: 1.0, scale_y: 1.0 }; + + screen.blit(method.clone(), &bmp, -3, 46); + screen.blit(method.clone(), &bmp, -4, 76); + screen.blit(method.clone(), &bmp, -8, 106); + screen.blit(method.clone(), &bmp, -12, 136); + screen.blit(method.clone(), &bmp, -13, 166); + screen.blit(method.clone(), &bmp, -14, 196); + screen.blit(method.clone(), &bmp, -16, 226); + + screen.blit(method.clone(), &bmp, 46, -3); + screen.blit(method.clone(), &bmp, 76, -4); + screen.blit(method.clone(), &bmp, 106, -8); + screen.blit(method.clone(), &bmp, 136, -12); + screen.blit(method.clone(), &bmp, 166, -13); + screen.blit(method.clone(), &bmp, 196, -14); + screen.blit(method.clone(), &bmp, 226, -16); + + screen.blit(method.clone(), &bmp, 307, 46); + screen.blit(method.clone(), &bmp, 308, 76); + screen.blit(method.clone(), &bmp, 312, 106); + screen.blit(method.clone(), &bmp, 316, 136); + screen.blit(method.clone(), &bmp, 317, 166); + screen.blit(method.clone(), &bmp, 318, 196); + screen.blit(method.clone(), &bmp, 320, 226); + + screen.blit(method.clone(), &bmp, 46, 227); + screen.blit(method.clone(), &bmp, 76, 228); + screen.blit(method.clone(), &bmp, 106, 232); + screen.blit(method.clone(), &bmp, 136, 236); + screen.blit(method.clone(), &bmp, 166, 237); + screen.blit(method.clone(), &bmp, 196, 238); + screen.blit(method.clone(), &bmp, 226, 240); + + let path = reference_file(Path::new("rotozoom_transparent_tinted_blits.png")); + //screen.to_png_file(path.as_path(), PngFormat::RGBA).unwrap(); + assert!(verify_visual(&screen, &path), "bitmap differs from source image: {:?}", path); +} + #[test] fn blended_rotozoom_transparent_blits() { use RgbaBlitMethod::*; diff --git a/ggdt/tests/ref/rgba/rotozoom_tinted_blits.png b/ggdt/tests/ref/rgba/rotozoom_tinted_blits.png new file mode 100644 index 0000000000000000000000000000000000000000..f52fc3c5a264fe1794ca9a50c2ea2e91a45cb7f8 GIT binary patch literal 3064 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 literal 0 HcmV?d00001 diff --git a/ggdt/tests/ref/rgba/rotozoom_transparent_tinted_blits.png b/ggdt/tests/ref/rgba/rotozoom_transparent_tinted_blits.png new file mode 100644 index 0000000000000000000000000000000000000000..578b6ba6bcbbd22df939821b83bee3d53ccf4a65 GIT binary patch literal 3219 zcmcJSX;jl!8piKG1c-u=xByZN8JFS~5Y!fdNGKp8Ld0<^VF@BSH0%h31V}^$rYxz| zf>j%66%jRHl>~u6LTP~l5)nztnh1peF(#2E3G2jmKFpa9J@aM0-1naMyyw05x#vE= zd+tAv1^BF4ZM_-*u*UbW*Kq(Kyne1i80p6ZYy%kp(;#0jj}w$TilM-uyNA~^y4~uF z(k8Gou;9xBZPd53Gq=tgZMb>_^3HNhR;D>i#4&4qPpXRXS9;v}nJWXg#qNZagDV-| zRtzb1i;3Zsw}joA+(_ZFdpdsuk?Ee;H$A|zA99l=^)4*^p19H(Qs3F1$Xpx_cA1?y zxAHA}tHwMqrgrRUc{s&>G=9|lcNRi~rZ3!)t?9m4E7`QIslH?n#JiAtzk`>0rKsf$ zaV`)wZ=K3Q_O0#sz5|$L?)0j$*NF5h^5;L%W)jZ^dTynt%hpJ-ahETw5b7KPa&t@N zplg|4j*J|#{B%=266Gz17AugEgO0vuXm*vIF`Lo-lF=}8S_gFwX>AR+kk zYygW|h54%J{~KbARI|dKaaR!{RdJ%UaO8x)pE$rT za2>wXjwAiX9;RK?luZ`G5N;1^YB(!3(GOGjw_)3}1Y7EMFvh+M%Xyh$_3niIM7Nzm zTbYHRsItK@p6Xe_Ek%C}Z!60u`H3r6mm*-y@rR%hr;6T%oFMj<6;*y0^p3~DFiK9* zQmJP^n2-<#M^f;TwSvzVy^xe+3&Te4SmXF*e|@tKzda$8yfO*lujWxt_d%Z1lAh zJU%TLSS@|<2?19yU8Ku(8-E|1Hs&_7uV~9vb5cigH-A1~BCXz^_P06BAW|@V`b)NB zwBeriZ=1-%>9oi^4LNh(Y+1GnvKHy0A)6N3PX3+^;XTjOhuK6oKc+HaQDPx5t63Jc z(9?+gCfn9v+_n?1w7v5wJNeFoj<29g{pL|zV6QM9TE`dFX1qS|AajW~jir|_0J4x~ z(=(Ha%a`@59cJ0{7S6{(tM5&|R_;C#7_hXWyIr|fz#f9w(A#jchhgSCPCeH?y}-T2 zrEy;uN9+eQkF}esFhpqZ*|z61OEfF`EO!@7+ZHk8Y8Tkb)kMU-fbw~^@tH&(sPtBi zI2Py|<^97ZRc=)tQBZgFqS~5uc_~>q49@FNnSguHDZXnQA9aVu zP1(YmeQ_>^o~oFoyCYsb*?iRUWwY0ALg6lHK~lF9H?gr@zT0hHTiGZ3d?A$S5-?S@ z#9}rm%t*pG;}A%x86gLKqzPK2_Ro{okQ57UQ&v$lMciuAy>EUnC5=z8Uvw|B6Y0=k zzof6Ol4v(ytz^hrJ-#{`ciB)`r<;1Ch?7IMM0!GRW@DTgDSOM=$MVR$G+`53oj3Us z9K!8vpQY*+C00#k3kCEou0wXwL+>OnpgZnoz+{ief*j{l6Gb1ouo5;outP2zX$#+x zHDbAv9H;w@NCcZ4%aVvbHEgjuRQbqYJH@Ly<-`CLt>nb&29>|+tMBKR&f><&gYRo4 z*QM94h0TSIdeoWRZN34cgz@;bLuB4p|{9z8+t61~7sh$Qn@@nZ!VuEmNo1-Ce;sllv2`Bi8J8bwK z<_3ljc5I;}gwL?SmzbB2LZIpm2(ROF`ZoK%P@etNKugV>-^{?brWnRsxTD}MH5&!G z0vO`wAFTy>t|k~{=R&u%_KkcN#4aw`;0dSnlJV#Ap!GORofG3(PdMatnpV8)FBJWU z+JJ0uFPXah9HW=jhxilEH|*#Zc+6GJ^&c8L(~XY7FSR{{b}L_YkiZ-gkKs6FSwibQ zFb{h{Vd_NW9zeU1u?~+Zm^%3;^bf`%qAmVF93lW*s)i#EE0+GD>hS@2e5O1K185nB z$5f1S2MvDfxo+f~1z;8W!+cb3XBxj%&#>jto9hH#Hi{~tFF{xwu}bPSp+R zxa@Do1rCjV6$WQwQQik#Q)2S{96R58I(^499c8hMjvypuCM1P%#tsCo;8F6RA7s-z zUQwPf>|}ebHJD{wbti|_l6X%AMfW}Zb*(_8WxohFk7$TI_`{(m7JT8r*U^ypiWx~^ z4LA$l=F(v{{}*Laq56}w82k1Ec~8(sTUFFb<2_Rj%UGCJu9?dGF|?&_zxmji^P|xS z=_}v8)V!ZX4q5%YtMidsHI*L_nhKddv=BIDjkO;;*qD>R?QEV>{9^9Cbdc}}m3~hh z`@;Kv2pAKE6#%1ChvK8QJy?=nKuG)3kIJ@w2E=AmtdPJb){oxI;irXA*{uta`4Y@x zA1QVXNjd#&e>NL*^%`i~MoYRpbsX6@*x@SOq^s6*(FiL~ZwH4Q=m)qWEUTb{!xctR`RJCUY8CXj;W<%HHhXiGPF;Ki)T9_!8$HR<0}-bZz3Z=2?O(Q% zYq3d=NCA5Te{{pST?`r*Uff7GAFUcr@dmbOk7=^4WYAHP^Y`p#$%l8(!hu0X@hC?l z0PVNU)~!P>Et6;V!q1w96NI`4$s>CiJs(l6+ma2cl21hylAmVqb{ziW~mnoU?LSQcZood-N>y* zZWPS9kf5r(U4b^cZO(|;FjBwW?=ZD)_)eHJT+eD_PtS3mD&j9OByfqk>~G$=x;Ps`*Hdt@ss33C=!ZINg^3ceQg$C}4o3tSC;F>hvxMFm@E2w7iIZs(RUBBY0%|3b4+h{PSCTpGA%D#bd^|EhYI!J5PURCf&89WmqL zC2K~OzE}HTYf|`kn+M+W-qNlt1vD%(ZaCgDsyab?i|XK=rWCXCGMMqVt0A|YSsH|L z=D>gk(K_kEc(zhPKfgpzXxzK}Bd+HYG8cD^&iNy<<3yvL~JY^t7XZF2;GhcB5MtPn1OhH>e h%#~fNiaa!HTb^a`syEd0sQ$A7e7ys_DnBD-{RC*(l1o{nDVxh-W)!)NG5gKhlRdltZ0GDb-+90Hc`wiTJ@4~-eou;Xt#%tmlPXJIUN+@8w5jd{LOhe6JOAP$Z5!cd}bD zcDNv^EOe;q(UDrej_G?|197b78p}nUm8_nNFHMunLZ4MxH(o7NiyMkYESKs)-wkgK zNX(Q?e@R&jO@^sC+^XLyaJDuN*~rJ4p0K$d8wxl&t@I z>s9|KLzGaKrBB`$bA_JsW{xio!Cz1X<&ne(cXAGl`Kh4!#CaHu9YE;}Q8^|w5ated z_4_^^w(DF|1Q3(Km6$j@w(W06rHC^~qf;Wa#-SR$n!brtfRqiY)<3YRsbu6dhpX>4 ziCks}iT)klV4zwbL*?-JVpn5#A0caFf~-n#JmvcT4Bl%R*dAisZ~aMo%tG?}^otZS zueN*Nt}gM+xV?bOhzc0|CC-CBH)))H^Uk0oaL%S6QoGI(@y39BK9J{aL{?+c&pQ)0 zYJFCDF5->%kjir_K(o!7>xV&+`3WP9`iFa>Hswer2H3+rH-2TiI)Mw|ngP~lg6$-> z$WgF#b{M!(rf>)$=lA7B&IYKWil(j`3^YtDk}tVDii`pZr}joEitT+Lc1!%tPamPo_bk|E?cEuV0uB|Lj~u8 z4wm+Z&kc>KeaU-e7$9&OVOO-U`gNM(lEk$Fzt0p5U4}niwH0=7_%c>4;GdT*Abb^n zZg&S%ZditG$N!$}^_HiG1CO=8>u=8E;;EN1kSoKSDz=2gV08r^U1+{j$w3Xxr;B9^ zC$+PTF?9C=H3f@!@5TviIZ8`;2B?dULOR#=d4WW;r$|-zp55ei7^*ja_*Do9O(uD4 ztkLq?eg=A<`3hPy0!4)Hy`<8{9@(>b0?dNc$GNJSBZwq=%-6g2w8RFIMslIJLr#R$uPh zS+2x(F}&|P5`S0Aa@=zhj2-Jr)2MUw>}OARCYuBbA6DFGo{if!V9UxNmIJ7YLe+W( z(GB34CzY?ojfW|<4@zS}(SR}b;UsBv{k2$N;EG*`nzLIiKCfu+(y6tR_zd{d=OVWt zgG47AsL6)8x|l0~QL~W*?|5#83JSE?aO8nOo_VJ6RPQIql(NzU%X@u~)FP*>j9NT& z4?oI{*Ed6gmQhE{$W8gT&e`L(E+I%~q_YQyqC&_X6~@n_JN@GLpM^rB0Xr&@nUd8X zJcsj-Q)^%fiB+pGw8Rw{`UyeyN_^V1yZ|9n7tb@Z8XDF0%ko<3W7g_gU!_}Jo$?A! zW0hK7A7m+nlhZ8PeSkzPXrCXk#g9g58hVCDwrWBCq8IUAO4rw5j*y7_C6IgI9j$Lq z^)qns@ZV7X^MaHAB%s0OSf1#J&Go{2$lHP;AeabWd6$q}M}n&U#STDQog*3GZ&Tcp z0~#2M>t&xVMT_n6)m`9HlC)C1A|8YHMj%!^T1eh(vdJ#GCfhZBb`00nP9cl z-`}qrvRW;4;p}-ZlV{7~xWm~L#$GYS#qmczh0Mz!G9_b8xiRSym|{(H4n1_+2k)uC Md8;e6bPMh1AH7rZ$^ZZW literal 0 HcmV?d00001 diff --git a/ggdt/tests/ref/rgba/solid_tinted_blits.png b/ggdt/tests/ref/rgba/solid_tinted_blits.png new file mode 100644 index 0000000000000000000000000000000000000000..318c582f9f1a516927c5cbda054d1d8d69801dd3 GIT binary patch literal 1908 zcmb`Ido+}39LJycHTNO+OEsp+hBOSd70P9D3A-hdODBrbN-B2^GQA|_P;6~cH0i26 zZbK=p+a$M>Yba67Fk1`5CIoR9m1^{BB<1qpby#^bU2LOQI>R_{N4=YpD^DMmIUM0c#b@hfM2Ol^{_U_BS z9tfRxP>oqeR@%^Z3+r+zW5l$ayN~hHf&#%^v>=(iDW=L*ibn%0m&wgu>+7x){~h^m zNGjzX84quvo-}LRR6D!b(UeheqO)B-`qLHIBv*;odvP{7uO*c2_B*&L@9Y82p1=7z z5=(E(62O7Dfe2!R?q_w91Z#Bx_O@xKAVsViX^gNQwc8)_^WK zBxCZ<7SN+vrnwxP_#7Y!##MVopt-^h9AHoz* zh>`Xzcuk3`F-95S`sg&UxRYJj#*uzd7O+YT5su1iMj#Y_xfn1ilss6rG~`C(6Ht{1 zaLr$CVrxit)|0Xq(|U?8n^k&y&(!cvBjZ}h_&~M=+G}gH*Yfz*_m)mIcg!EI-|}6U zg@-P-KqlzZhY*kUChL3xt+lXS$KhOp%LJPG3$TAI=gsWD1`|43Ndn&kg0AfYY3}hb zA#7NMrw3uQ2w%yLGDCz5J3uT)Q^tguyF7U-bd-ofa01sF;=yz^ zPJ2G+Zv^&zj~Yb!r?Gd_4bE+%7!zmKAWWa^otKvRp^PegmDDD(z_%_8!jQINgZRB_ zE+F>BlF*uDOxSb6%K*NzSYR_6Sp8X?P4E#@eOk>iv>9v`V(^VtU*N|ikHvSQRt%{L zNBxgku3tEs;{5(;kChEDbVufkZZ6MPB?|Hi-S;b=id;x*Ia4!n>v`RPMrBGc$vXp} z47$l@(RsG;S_JkmL2{LOT(E2r-U%CAP>E_>2vjzA??g)JU|b1Ye?1lSs>k*Xs#}4a z#!AqpgTNXqd3_AnqbpzHr3I<*-qXw8LYXlsAR@4c;x^^C8OmgUrzRt}$^9gnD71fa z9TPlSg^Kl%5MiJ43WlW zBAOe(_OqGOvffjPs=Q-xeYdHiBF}Gfqg(d`{}fCaouy>y)0(kbu>C})3BI*@cRDDFa3s*~nMW%(UMP(EVmc1Mt6Ro_k>PhJ?7Lhrz)w$~))Z-) z`z*npnciM&kB2bhOXO|AkD<-P?sItiu6Xui^8eAA%Q+VXgqu+o*TltwE-F)EP)C8lz90U=?GVQ zaf-fYK=gL63vah$b?xS(g)8T*ULp3I#~BU1aAD2(--B5l)7YoUd>ts69OwqhJFg25 YSk+%1>!iVE=xGWZY#nX#t-Ry@0c9ucyZ`_I literal 0 HcmV?d00001 diff --git a/ggdt/tests/ref/rgba/transparent_flipped_tinted_blits.png b/ggdt/tests/ref/rgba/transparent_flipped_tinted_blits.png new file mode 100644 index 0000000000000000000000000000000000000000..6fda852f8bce4be391555c2d8e0d247d757bb128 GIT binary patch literal 1963 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 U20@q?X4W8NUqnF79?q#>0Gr4zV*mgE literal 0 HcmV?d00001