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);
103load_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}