Skip to main content

ndless_sdl/
image.rs

1use cty::c_int;
2use ndless::prelude::*;
3
4use crate::get_error;
5use crate::video::ll::SDL_RWFromConstMem;
6use crate::video::Surface;
7
8pub mod ll {
9	#![allow(non_camel_case_types)]
10
11	use cty::{c_char, c_int, c_uint};
12
13	use crate::video::ll::{SDL_RWops, SDL_Surface};
14
15	pub type IMG_InitFlags = c_uint;
16
17	pub const IMG_INIT_JPG: IMG_InitFlags = 1;
18	pub const IMG_INIT_PNG: IMG_InitFlags = 2;
19	pub const IMG_INIT_TIF: IMG_InitFlags = 4;
20	pub const IMG_INIT_WEBP: IMG_InitFlags = 8;
21
22	extern "C" {
23		pub fn IMG_Init(flags: c_int) -> c_int;
24		pub fn IMG_Quit();
25		pub fn IMG_Load(file: *const c_char) -> *mut SDL_Surface;
26		pub fn IMG_LoadGIF_RW(src: *mut SDL_RWops) -> *mut SDL_Surface;
27		pub fn IMG_LoadLBM_RW(src: *mut SDL_RWops) -> *mut SDL_Surface;
28		pub fn IMG_LoadPCX_RW(src: *mut SDL_RWops) -> *mut SDL_Surface;
29		pub fn IMG_LoadPNM_RW(src: *mut SDL_RWops) -> *mut SDL_Surface;
30		pub fn IMG_LoadTGA_RW(src: *mut SDL_RWops) -> *mut SDL_Surface;
31		pub fn IMG_LoadXCF_RW(src: *mut SDL_RWops) -> *mut SDL_Surface;
32	}
33}
34
35#[derive(Debug, PartialEq, Eq, Copy, Clone)]
36pub enum InitFlag {
37	JPG = ll::IMG_INIT_JPG as isize,
38	PNG = ll::IMG_INIT_PNG as isize,
39	TIF = ll::IMG_INIT_TIF as isize,
40}
41
42pub fn init(flags: &[InitFlag]) -> Vec<InitFlag> {
43	let bitflags = unsafe {
44		ll::IMG_Init(
45			flags
46				.iter()
47				.fold(0i32, |flags, &flag| flags | flag as c_int),
48		)
49	};
50
51	let flags = [InitFlag::JPG, InitFlag::PNG, InitFlag::TIF];
52
53	flags
54		.iter()
55		.filter_map(|&flag| {
56			if bitflags & (flag as c_int) != 0 {
57				Some(flag)
58			} else {
59				None
60			}
61		})
62		.collect()
63}
64
65pub fn load_file(file: impl Into<String>) -> Result<Surface, String> {
66	let cfile = ndless::cstr!(file.into());
67	unsafe {
68		let raw = ll::IMG_Load(cfile.as_ptr());
69
70		if raw.is_null() {
71			Err(get_error())
72		} else {
73			Ok(Surface { raw, owned: true })
74		}
75	}
76}
77
78macro_rules! load_typed {
79	($name: ident, $function: ident) => {
80		pub fn $name(buffer: &[u8]) -> Result<Surface, String> {
81			unsafe {
82				let mem =
83					SDL_RWFromConstMem(buffer.as_ptr() as *const cty::c_void, buffer.len() as i32);
84				if mem.is_null() {
85					return Err(get_error());
86				}
87
88				let raw = ll::$function(mem);
89
90				if raw.is_null() {
91					Err(get_error())
92				} else {
93					Ok(Surface { raw, owned: true })
94				}
95			}
96		}
97	};
98}
99
100load_typed!(load_mem_gif, IMG_LoadGIF_RW);
101load_typed!(load_mem_lbm, IMG_LoadLBM_RW);
102load_typed!(load_mem_pcx, IMG_LoadPCX_RW);
103// PNM disabled for now due to possible link-time errors
104//load_typed!(load_mem_pnm, IMG_LoadPNM_RW);
105load_typed!(load_mem_tga, IMG_LoadTGA_RW);
106load_typed!(load_mem_xcf, IMG_LoadXCF_RW);
107
108pub fn quit() {
109	unsafe {
110		ll::IMG_Quit();
111	}
112}