From a21d71889ade9558fb34720ed5872846a5a177c6 Mon Sep 17 00:00:00 2001 From: Andelf Date: Sat, 26 Apr 2014 22:12:33 +0800 Subject: [PATCH] use new flag implementation same as rust-sdl2 --- src/demo/video.rs | 8 +-- src/sdl2_image/flag.rs | 109 +++++++++++++++++++++++++++++++++++++++++ src/sdl2_image/lib.rs | 37 +++++--------- 3 files changed, 125 insertions(+), 29 deletions(-) create mode 100644 src/sdl2_image/flag.rs diff --git a/src/demo/video.rs b/src/demo/video.rs index 413ab3bd..53cf192e 100644 --- a/src/demo/video.rs +++ b/src/demo/video.rs @@ -4,18 +4,18 @@ use sdl2_image::LoadSurface; // use sdl2_image::LoadTexture; pub fn main(png: &Path) { - sdl2::init([sdl2::InitVideo]); - sdl2_image::init([sdl2_image::InitPng, sdl2_image::InitJpg]); + sdl2::init(sdl2::InitVideo); + sdl2_image::init(sdl2_image::InitPng | sdl2_image::InitJpg); let window = match sdl2::video::Window::new( "rust-sdl2 demo: Video", sdl2::video::PosCentered, - sdl2::video::PosCentered, 800, 600, [sdl2::video::OpenGL]) { + sdl2::video::PosCentered, 800, 600, sdl2::video::OpenGL) { Ok(window) => window, Err(err) => fail!(format!("failed to create window: {}", err)) }; let renderer = match sdl2::render::Renderer::from_window( - window, sdl2::render::DriverAuto, [sdl2::render::Accelerated]) { + window, sdl2::render::DriverAuto, sdl2::render::Accelerated) { Ok(renderer) => renderer, Err(err) => fail!(format!("failed to create renderer: {}", err)) }; diff --git a/src/sdl2_image/flag.rs b/src/sdl2_image/flag.rs new file mode 100644 index 00000000..4b573574 --- /dev/null +++ b/src/sdl2_image/flag.rs @@ -0,0 +1,109 @@ +// Loosely based on zlib-licensed code from RustAllegro +// https://github.com/SiegeLord/RustAllegro +// +// Implements efficient, type-safe flags with support for bitwise operators. +// +// Usage: +// +// flag_type!(FlagTypeName { +// FlagName1 = FlagValue1, +// FlagName2 = FlagValue2, +// ... +// FlagNameN = FlagValueN +// }) +// +// fn foo(flag: FlagTypeName) { +// let raw = (flag | FlagNameN).get(); +// bar(raw); +// } + +#![macro_escape] + +macro_rules! flag_type( + ($typename:ident : $supertype:ident { $($name:ident = $value:expr),* }) => { + pub struct $typename { + bits: $supertype + } + + impl $typename { + #[inline] + pub fn new(bits: $supertype) -> $typename { + $typename { bits: bits } + } + + #[inline] + pub fn get(self) -> $supertype { + self.bits + } + } + + impl ::std::default::Default for $typename { + fn default() -> $typename { + $typename::new(0) + } + } + + impl ::std::cmp::Eq for $typename { + fn eq(&self, other: &$typename) -> bool { + self.bits == other.bits + } + } + + impl ::std::cmp::TotalEq for $typename {} + + impl ::std::cmp::Ord for $typename { + fn lt(&self, other: &$typename) -> bool { + self.bits < other.bits + } + } + + impl ::std::cmp::TotalOrd for $typename { + fn cmp(&self, other: &$typename) -> Ordering { + self.bits.cmp(&other.bits) + } + } + + impl ::std::ops::Not<$typename> for $typename { + fn not(&self) -> $typename { + $typename { bits: !self.bits } + } + } + + impl ::std::ops::BitAnd<$typename, $typename> for $typename { + fn bitand(&self, rhs: &$typename) -> $typename { + $typename { bits: self.bits & rhs.bits } + } + } + + impl ::std::ops::BitOr<$typename, $typename> for $typename { + fn bitor(&self, rhs: &$typename) -> $typename { + $typename { bits: self.bits | rhs.bits } + } + } + + impl ::std::ops::BitXor<$typename, $typename> for $typename { + fn bitxor(&self, rhs: &$typename) -> $typename { + $typename { bits: self.bits ^ rhs.bits } + } + } + + impl ::std::ops::Shl<$supertype, $typename> for $typename { + fn shl(&self, rhs: &$supertype) -> $typename { + $typename { bits: self.bits << *rhs } + } + } + + impl ::std::ops::Shr<$supertype, $typename> for $typename { + fn shr(&self, rhs: &$supertype) -> $typename { + $typename { bits: self.bits >> *rhs } + } + } + + $( + pub static $name: $typename = $typename { bits: $value as $supertype }; + )+ + }; + ($typename:ident { $($name:ident = $value:expr),* }) => { + flag_type!($typename : u32 { $($name = $value),* }) + } +) diff --git a/src/sdl2_image/lib.rs b/src/sdl2_image/lib.rs index 8d3c6ee4..c44ae122 100644 --- a/src/sdl2_image/lib.rs +++ b/src/sdl2_image/lib.rs @@ -1,3 +1,5 @@ +#![feature(macro_rules)] + #![crate_id="sdl2_image#sdl2_image:0.1"] #![crate_type = "lib"] #![desc = "SDL2_image bindings and wrappers"] @@ -39,19 +41,16 @@ mod others { #[allow(non_camel_case_types, dead_code)] mod ffi; +mod flag; /// InitFlags are passed to init() to control which subsystem /// functionality to load. -// repr(C) "makes the size of the enum's discriminant the default -// size of enums that the C ABI for the platform uses." -#[repr(C)] -#[deriving(Clone, Eq, Hash, Show)] -pub enum InitFlag { - InitJpg = ffi::IMG_INIT_JPG as int, - InitPng = ffi::IMG_INIT_PNG as int, - InitTif = ffi::IMG_INIT_TIF as int, - InitWebp = ffi::IMG_INIT_WEBP as int, -} +flag_type!(InitFlag : c_int { + InitJpg = ffi::IMG_INIT_JPG, + InitPng = ffi::IMG_INIT_PNG, + InitTif = ffi::IMG_INIT_TIF, + InitWebp = ffi::IMG_INIT_WEBP +}) /// Static method extensions for creating Surfaces pub trait LoadSurface { @@ -142,23 +141,11 @@ impl LoadTexture for Renderer { } } -pub fn init(flags: &[InitFlag]) -> ~[InitFlag] { +pub fn init(flags: InitFlag) -> InitFlag { //! Initializes SDL2_image with InitFlags and returns which //! InitFlags were actually used. - let mut used = Vec::new(); - unsafe { - let used_flags = ffi::IMG_Init( - flags.iter().fold(0, |flags, &flag| { - flags | flag as ffi::IMG_InitFlags - }) - ); - for flag in flags.iter() { - if used_flags & *flag as c_int != 0 { - used.push(*flag) - } - } - } - used.as_slice().into_owned() + let used = unsafe { ffi::IMG_Init(flags.get()) }; + InitFlag::new(used) } pub fn quit() {