1use core::mem;
2use core::ptr;
3use core::slice;
4
5use cstr_core::CString;
6use cty::c_int;
7use ndless::prelude::*;
8
9use crate::get_error;
10use crate::Rect;
11
12pub use self::Color::{RGB, RGBA};
13
14#[allow(non_camel_case_types)]
15type c_float = f32;
16
17pub mod ll {
18 #![allow(non_camel_case_types)]
19
20 use cty::{
21 c_char as c_schar, c_int, c_uchar, c_uint, c_void, int32_t, uint16_t, uint32_t, uint8_t,
22 };
23
24 use crate::Rect;
25
26 type c_float = f32;
27 pub type SDL_Rect = Rect;
28
29 #[repr(C)]
30 #[derive(Copy, Clone)]
31 pub struct SDL_RWops {
32 pub seek: *mut uint8_t,
33 pub read: *mut uint8_t,
34 pub write: *mut uint8_t,
35 pub close: *mut uint8_t,
36 pub _type: uint32_t,
37 _hidden: [c_uchar; 24],
38 }
39
40 #[repr(C)]
41 #[derive(Copy, Clone)]
42 pub struct SDL_Surface {
43 pub flags: uint32_t,
44 pub format: *mut SDL_PixelFormat,
45 pub w: c_int,
46 pub h: c_int,
47 pub pitch: uint16_t,
48 pub pixels: *mut c_void,
49 pub offset: c_int,
50 pub hwdata: *mut c_void,
51 pub clip_rect: SDL_Rect,
52 pub unused1: uint32_t,
53 pub locked: uint32_t,
54 pub map: *mut c_void,
55 pub format_version: c_uint,
56 pub refcount: c_int,
57 }
58
59 #[repr(C)]
60 #[derive(Copy, Clone)]
61 pub struct SDL_Color {
62 pub r: uint8_t,
63 pub g: uint8_t,
64 pub b: uint8_t,
65 pub unused: uint8_t,
66 }
67
68 #[repr(C)]
69 #[derive(Copy, Clone)]
70 pub struct SDL_Palette {
71 pub ncolors: c_int,
72 pub colors: *mut SDL_Color,
73 }
74
75 #[allow(non_snake_case)]
76 #[repr(C)]
77 #[derive(Copy, Clone)]
78 pub struct SDL_PixelFormat {
79 pub palette: *mut SDL_Palette,
80 pub BitsPerPixel: uint8_t,
81 pub BytesPerPixel: uint8_t,
82 pub Rloss: uint8_t,
83 pub Gloss: uint8_t,
84 pub Bloss: uint8_t,
85 pub Aloss: uint8_t,
86 pub Rshift: uint8_t,
87 pub Gshift: uint8_t,
88 pub Bshift: uint8_t,
89 pub Ashift: uint8_t,
90 pub Rmask: uint32_t,
91 pub Gmask: uint32_t,
92 pub Bmask: uint32_t,
93 pub Amask: uint32_t,
94 pub colorkey: uint32_t,
95 pub alpha: uint8_t,
96 }
97
98 #[repr(C)]
99 #[derive(Copy, Clone)]
100 pub struct SDL_VideoInfo {
101 pub flags: uint32_t,
102 pub video_mem: uint32_t,
104 pub vfmt: *mut SDL_PixelFormat,
105 pub current_w: c_int,
106 pub current_h: c_int,
107 }
108
109 extern "C" {
110 pub fn SDL_CreateRGBSurface(
111 flags: uint32_t,
112 width: c_int,
113 height: c_int,
114 depth: c_int,
115 Rmask: uint32_t,
116 Gmask: uint32_t,
117 Bmask: uint32_t,
118 Amask: uint32_t,
119 ) -> *mut SDL_Surface;
120 pub fn SDL_CreateRGBSurfaceFrom(
121 pixels: *mut c_void,
122 width: c_int,
123 height: c_int,
124 depth: c_int,
125 pitch: c_int,
126 Rmask: uint32_t,
127 Gmask: uint32_t,
128 Bmask: uint32_t,
129 Amask: uint32_t,
130 ) -> *mut SDL_Surface;
131 pub fn SDL_FreeSurface(surface: *mut SDL_Surface);
132 pub fn SDL_MapRGB(
133 format: *const SDL_PixelFormat,
134 r: uint8_t,
135 g: uint8_t,
136 b: uint8_t,
137 ) -> uint32_t;
138 pub fn SDL_MapRGBA(
139 format: *const SDL_PixelFormat,
140 r: uint8_t,
141 g: uint8_t,
142 b: uint8_t,
143 a: uint8_t,
144 ) -> uint32_t;
145 pub fn SDL_GetRGB(
146 pixel: uint32_t,
147 fmt: *const SDL_PixelFormat,
148 r: *mut uint8_t,
149 g: *mut uint8_t,
150 b: *mut uint8_t,
151 );
152 pub fn SDL_GetRGBA(
153 pixel: uint32_t,
154 fmt: *const SDL_PixelFormat,
155 r: *mut uint8_t,
156 g: *mut uint8_t,
157 b: *mut uint8_t,
158 a: *mut uint8_t,
159 );
160 pub fn SDL_SetVideoMode(
161 width: c_int,
162 height: c_int,
163 bpp: c_int,
164 flags: uint32_t,
165 ) -> *mut SDL_Surface;
166 pub fn SDL_VideoModeOK(width: c_int, height: c_int, bpp: c_int, flags: uint32_t) -> c_int;
167 pub fn SDL_GetVideoInfo() -> *const SDL_VideoInfo;
168 pub fn SDL_GetVideoSurface() -> *mut SDL_Surface;
169 pub fn SDL_UpdateRect(
170 screen: *mut SDL_Surface,
171 x: int32_t,
172 y: int32_t,
173 w: uint32_t,
174 h: uint32_t,
175 );
176 pub fn SDL_UpdateRects(screen: *mut SDL_Surface, numrects: c_int, rects: *mut SDL_Rect);
177 pub fn SDL_SetColors(
178 surface: *mut SDL_Surface,
179 colors: *mut SDL_Color,
180 firstcolor: c_int,
181 ncolors: c_int,
182 ) -> c_int;
183 pub fn SDL_SetPalette(
184 surface: *mut SDL_Surface,
185 flags: c_int,
186 colors: *mut SDL_Color,
187 firstcolor: c_int,
188 ncolors: c_int,
189 ) -> c_int;
190 pub fn SDL_LockSurface(surface: *mut SDL_Surface) -> c_int;
191 pub fn SDL_UnlockSurface(surface: *mut SDL_Surface);
192 pub fn SDL_Flip(screen: *mut SDL_Surface) -> c_int;
193 pub fn SDL_ConvertSurface(
194 src: *mut SDL_Surface,
195 fmt: *mut SDL_PixelFormat,
196 flags: uint32_t,
197 ) -> *mut SDL_Surface;
198 pub fn SDL_DisplayFormat(surface: *mut SDL_Surface) -> *mut SDL_Surface;
199 pub fn SDL_DisplayFormatAlpha(surface: *mut SDL_Surface) -> *mut SDL_Surface;
200 pub fn SDL_SetColorKey(surface: *mut SDL_Surface, flag: uint32_t, key: uint32_t) -> c_int;
201 pub fn SDL_SetAlpha(surface: *mut SDL_Surface, flag: uint32_t, alpha: uint8_t) -> c_int;
202 pub fn SDL_SetClipRect(surface: *mut SDL_Surface, rect: *const SDL_Rect);
203 pub fn SDL_UpperBlit(
204 src: *mut SDL_Surface,
205 srcrect: *mut SDL_Rect,
206 dst: *mut SDL_Surface,
207 dstrect: *mut SDL_Rect,
208 ) -> c_int;
209 pub fn SDL_FillRect(
210 dst: *mut SDL_Surface,
211 dstrect: *mut SDL_Rect,
212 color: uint32_t,
213 ) -> c_int;
214 pub fn SDL_SetGamma(r: c_float, g: c_float, b: c_float) -> c_int;
215 pub fn SDL_SetGammaRamp(
216 r: *const uint16_t,
217 g: *const uint16_t,
218 b: *const uint16_t,
219 ) -> c_int;
220 pub fn SDL_GetGammaRamp(r: *mut uint16_t, g: *mut uint16_t, b: *mut uint16_t) -> c_int;
221 pub fn SDL_RWFromFile(file: *const c_schar, mode: *const c_schar) -> *mut SDL_RWops;
222 pub fn SDL_RWFromConstMem(mem: *const c_void, size: c_int) -> *mut SDL_RWops;
223 pub fn SDL_LoadBMP_RW(src: *mut SDL_RWops, freesrc: c_int) -> *mut SDL_Surface;
224 pub fn SDL_SaveBMP_RW(
225 surface: *mut SDL_Surface,
226 dst: *mut SDL_RWops,
227 freedst: c_int,
228 ) -> c_int;
229 pub fn SDL_GL_SwapBuffers();
230 }
231}
232
233#[derive(Debug, PartialEq)]
234pub struct Surface {
235 pub raw: *mut ll::SDL_Surface,
236 pub owned: bool,
237}
238
239fn wrap_surface(raw: *mut ll::SDL_Surface, owned: bool) -> Surface {
240 Surface { raw, owned }
241}
242
243impl Drop for Surface {
244 fn drop(&mut self) {
245 unsafe {
246 if self.owned {
247 ll::SDL_FreeSurface(self.raw);
248 }
249 }
250 }
251}
252
253#[derive(PartialEq, Copy, Clone, Debug)]
254pub struct Palette {
255 pub raw: *mut ll::SDL_Palette,
256}
257
258fn wrap_palette(palette: *mut ll::SDL_Palette) -> Option<Palette> {
259 if palette.is_null() {
260 None
261 } else {
262 Some(Palette { raw: palette })
263 }
264}
265
266pub type PaletteColors<'a> = slice::Iter<'a, ll::SDL_Color>;
267
268impl Palette {
269 pub fn colors<'a>(&'a self) -> PaletteColors<'a> {
270 use self::ll::SDL_Color;
271 let colors = unsafe { (*self.raw).colors } as *const SDL_Color;
272 let ncolors = unsafe { (*self.raw).ncolors } as usize;
273 let colors: &'a [SDL_Color] = unsafe {
274 &*(slice::from_raw_parts(&colors, ncolors) as *const [*const SDL_Color]
275 as *const [SDL_Color])
276 };
277 colors.iter()
278 }
279}
280
281#[derive(PartialEq, Debug)]
282pub struct PixelFormat {
283 pub palette: Option<Palette>,
284 pub bpp: u8,
285 pub r_loss: u8,
286 pub g_loss: u8,
287 pub b_loss: u8,
288 pub a_loss: u8,
289 pub r_shift: u8,
290 pub g_shift: u8,
291 pub b_shift: u8,
292 pub a_shift: u8,
293 pub r_mask: u32,
294 pub g_mask: u32,
295 pub b_mask: u32,
296 pub a_mask: u32,
297 pub color_key: u32,
298 pub alpha: u8,
299}
300
301fn wrap_pixel_format(raw: *mut ll::SDL_PixelFormat) -> PixelFormat {
302 let fmt = &unsafe { *raw };
303 PixelFormat {
304 palette: wrap_palette(fmt.palette),
305 bpp: fmt.BitsPerPixel,
306 r_loss: fmt.Rloss,
307 g_loss: fmt.Gloss,
308 b_loss: fmt.Bloss,
309 a_loss: fmt.Aloss,
310 r_shift: fmt.Rshift,
311 g_shift: fmt.Gshift,
312 b_shift: fmt.Bshift,
313 a_shift: fmt.Ashift,
314 r_mask: fmt.Rmask,
315 g_mask: fmt.Gmask,
316 b_mask: fmt.Bmask,
317 a_mask: fmt.Amask,
318 color_key: fmt.colorkey,
319 alpha: fmt.alpha,
320 }
321}
322
323fn unwrap_pixel_format(fmt: &PixelFormat) -> ll::SDL_PixelFormat {
324 ll::SDL_PixelFormat {
325 palette: match fmt.palette {
326 None => ptr::null_mut(),
327 Some(palette) => palette.raw,
328 },
329 BitsPerPixel: fmt.bpp,
330 BytesPerPixel: fmt.bpp / 8,
331 Rloss: fmt.r_loss,
332 Gloss: fmt.g_loss,
333 Bloss: fmt.b_loss,
334 Aloss: fmt.a_loss,
335 Rshift: fmt.r_shift,
336 Gshift: fmt.g_shift,
337 Bshift: fmt.b_shift,
338 Ashift: fmt.a_shift,
339 Rmask: fmt.r_mask,
340 Gmask: fmt.g_mask,
341 Bmask: fmt.b_mask,
342 Amask: fmt.a_mask,
343 colorkey: fmt.color_key,
344 alpha: fmt.alpha,
345 }
346}
347
348#[derive(Debug, PartialEq, Eq, Copy, Clone)]
349pub enum Color {
350 RGB(u8, u8, u8),
351 RGBA(u8, u8, u8, u8),
352}
353
354impl Color {
355 pub fn from_mapped(bit: u32, fmt: *const ll::SDL_PixelFormat) -> Color {
356 let mut r = 0;
357 let mut g = 0;
358 let mut b = 0;
359 let mut a = 0;
360
361 unsafe { ll::SDL_GetRGBA(bit, fmt, &mut r, &mut g, &mut b, &mut a) }
362
363 RGBA(r, g, b, a)
364 }
365
366 pub fn to_mapped(self, fmt: *const ll::SDL_PixelFormat) -> u32 {
367 match self {
368 RGB(r, g, b) => unsafe { ll::SDL_MapRGB(fmt, r, g, b) },
369 RGBA(r, g, b, a) => unsafe { ll::SDL_MapRGBA(fmt, r, g, b, a) },
370 }
371 }
372
373 pub fn from_struct(c: ll::SDL_Color) -> Color {
374 RGB(c.r, c.g, c.b)
375 }
376
377 pub fn to_struct(self) -> ll::SDL_Color {
378 match self {
379 RGB(r, g, b) => ll::SDL_Color { r, g, b, unused: 0 },
380 RGBA(r, g, b, _) => ll::SDL_Color { r, g, b, unused: 0 },
381 }
382 }
383}
384
385#[derive(PartialEq, Eq, Copy, Clone)]
386pub enum SurfaceFlag {
387 SWSurface = 0x0000_0000,
388 HWSurface = 0x0000_0001,
389 AsyncBlit = 0x0000_0004,
390 SrcColorKey = 0x0000_1000,
391 SrcAlpha = 0x0001_0000,
392 RLEAccel = 0x0000_4000,
393}
394
395#[derive(PartialEq, Eq, Copy, Clone)]
396pub enum VideoFlag {
397 AnyFormat = 0x1000_0000,
398 HWPalette = 0x2000_0000,
399 DoubleBuf = 0x4000_0000,
400 Fullscreen = 0x8000_0000usize as isize,
401 OpenGL = 0x0000_0002,
403 OpenGLBlit = 0x0000_000A,
404 Resizable = 0x0000_0010,
405 NoFrame = 0x0000_0020,
406}
407
408pub fn set_video_mode(
409 w: isize,
410 h: isize,
411 bpp: isize,
412 surface_flags: &[SurfaceFlag],
413 video_flags: &[VideoFlag],
414) -> Result<Surface, String> {
415 let flags = surface_flags
416 .iter()
417 .fold(0u32, |flags, &flag| flags | flag as u32);
418 let flags = video_flags
419 .iter()
420 .fold(flags, |flags, &flag| flags | flag as u32);
421
422 unsafe {
423 let raw = ll::SDL_SetVideoMode(w as c_int, h as c_int, bpp as c_int, flags);
424
425 if raw.is_null() {
426 Err(get_error())
427 } else {
428 Ok(wrap_surface(raw, false))
429 }
430 }
431}
432
433pub fn is_video_mode_ok(
434 w: isize,
435 h: isize,
436 bpp: isize,
437 surface_flags: &[SurfaceFlag],
438 video_flags: &[VideoFlag],
439) -> Option<isize> {
440 let flags = surface_flags
441 .iter()
442 .fold(0u32, |flags, &flag| flags | flag as u32);
443 let flags = video_flags
444 .iter()
445 .fold(flags, |flags, &flag| flags | flag as u32);
446
447 unsafe {
448 let bpp = ll::SDL_VideoModeOK(w as c_int, h as c_int, bpp as c_int, flags);
449
450 if bpp == 0 {
451 None
452 } else {
453 Some(bpp as isize)
454 }
455 }
456}
457
458#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
459pub enum VideoInfoFlag {
460 HWAvailable = 0x0000_0001,
461 WMAvailable = 0x0000_0002,
462 BlitHW = 0x0000_0200,
463 BlitHWColorkey = 0x0000_0400,
464 BlitHWAlpha = 0x0000_0800,
465 BlitSW = 0x0000_1000,
466 BlitSWColorkey = 0x0000_2000,
467 BlitSWAlpha = 0x0000_4000,
468 BlitFill = 0x0000_8000,
469}
470
471#[derive(Debug, PartialEq)]
472pub struct VideoInfo {
473 pub flags: Vec<VideoInfoFlag>,
474 pub width: isize,
475 pub height: isize,
476 pub format: PixelFormat,
477}
478
479fn wrap_video_info_flags(bitflags: u32) -> Vec<VideoInfoFlag> {
480 let flags = [
481 VideoInfoFlag::HWAvailable,
482 VideoInfoFlag::WMAvailable,
483 VideoInfoFlag::BlitHW,
484 VideoInfoFlag::BlitHWColorkey,
485 VideoInfoFlag::BlitHWAlpha,
486 VideoInfoFlag::BlitSW,
487 VideoInfoFlag::BlitSWColorkey,
488 VideoInfoFlag::BlitSWAlpha,
489 VideoInfoFlag::BlitFill,
490 ];
491
492 flags
493 .iter()
494 .filter_map(|&flag| {
495 if bitflags & (flag as u32) != 0 {
496 Some(flag)
497 } else {
498 None
499 }
500 })
501 .collect()
502}
503
504pub fn get_video_info() -> VideoInfo {
505 let raw = unsafe { ll::SDL_GetVideoInfo() };
506 VideoInfo {
507 flags: wrap_video_info_flags(unsafe { (*raw).flags } as u32),
508 width: unsafe { (*raw).current_w } as isize,
509 height: unsafe { (*raw).current_h } as isize,
510 format: wrap_pixel_format(unsafe { (*raw).vfmt }),
511 }
512}
513
514#[derive(Copy, Clone)]
515pub enum PaletteType {
516 Logical = 1,
517 Physical,
518}
519
520pub fn get_video_surface() -> Result<Surface, String> {
521 let raw = unsafe { ll::SDL_GetVideoSurface() };
522
523 if raw.is_null() {
524 Err(get_error())
525 } else {
526 Ok(wrap_surface(raw, false))
527 }
528}
529
530#[allow(clippy::too_many_arguments)]
532impl Surface {
533 pub fn new(
534 surface_flags: &[SurfaceFlag],
535 width: isize,
536 height: isize,
537 bpp: isize,
538 rmask: u32,
539 gmask: u32,
540 bmask: u32,
541 amask: u32,
542 ) -> Result<Surface, String> {
543 let flags = surface_flags
544 .iter()
545 .fold(0u32, |flags, flag| flags | *flag as u32);
546
547 unsafe {
548 let raw = ll::SDL_CreateRGBSurface(
549 flags,
550 width as c_int,
551 height as c_int,
552 bpp as c_int,
553 rmask,
554 gmask,
555 bmask,
556 amask,
557 );
558
559 if raw.is_null() {
560 Err(get_error())
561 } else {
562 Ok(Surface { raw, owned: true })
563 }
564 }
565 }
566
567 pub fn from_bmp(path: impl Into<String>) -> Result<Surface, String> {
568 let path = path.into();
569 let cpath = CString::new(path).unwrap();
570 let mode = CString::new("rb").unwrap();
571 let raw =
572 unsafe { ll::SDL_LoadBMP_RW(ll::SDL_RWFromFile(cpath.as_ptr(), mode.as_ptr()), 1) };
573
574 if raw.is_null() {
575 Err(get_error())
576 } else {
577 Ok(wrap_surface(raw, true))
578 }
579 }
580
581 pub fn get_width(&self) -> u16 {
584 unsafe { (*self.raw).w as u16 }
585 }
586
587 pub fn get_height(&self) -> u16 {
588 unsafe { (*self.raw).h as u16 }
589 }
590
591 pub fn get_size(&self) -> (u16, u16) {
592 (self.get_width(), self.get_height())
593 }
594
595 pub fn get_rect(&self) -> Rect {
596 Rect {
597 x: 0,
598 y: 0,
599 w: self.get_width(),
600 h: self.get_height(),
601 }
602 }
603
604 pub fn update_rect(&self, rect: Rect) {
605 unsafe {
606 ll::SDL_UpdateRect(
607 self.raw,
608 i32::from(rect.x),
609 i32::from(rect.y),
610 u32::from(rect.w),
611 u32::from(rect.h),
612 );
613 }
614 }
615
616 pub fn update_rects(&self, rects: &[Rect]) {
617 unsafe {
618 ll::SDL_UpdateRects(self.raw, rects.len() as c_int, rects.as_ptr() as *mut Rect);
619 }
620 }
621
622 pub fn set_colors(&self, colors: &[Color]) -> bool {
623 let mut colors: Vec<_> = colors.iter().map(|color| color.to_struct()).collect();
624
625 unsafe { ll::SDL_SetColors(self.raw, colors.as_mut_ptr(), 0, colors.len() as c_int) == 1 }
626 }
627
628 pub fn set_palette(&self, palettes: &[PaletteType], colors: &[Color]) -> bool {
629 let mut colors: Vec<_> = colors.iter().map(|color| color.to_struct()).collect();
630 let flags = palettes
631 .iter()
632 .fold(0 as c_int, |flags, &flag| flags | flag as c_int);
633
634 unsafe {
635 ll::SDL_SetPalette(
636 self.raw,
637 flags,
638 colors.as_mut_ptr(),
639 0,
640 colors.len() as c_int,
641 ) == 1
642 }
643 }
644
645 pub fn lock(&self) -> bool {
646 unsafe { ll::SDL_LockSurface(self.raw) == 0 }
647 }
648
649 pub fn with_lock<F: Fn(&mut [u8]) -> bool>(&self, f: F) -> bool {
651 unsafe {
652 if ll::SDL_LockSurface(self.raw) != 0 {
653 panic!("could not lock surface");
654 }
655 let len = (*self.raw).pitch as usize * ((*self.raw).h as usize);
656 let pixels: &mut [u8] = mem::transmute(((*self.raw).pixels, len));
657 let rv = f(pixels);
658 ll::SDL_UnlockSurface(self.raw);
659 rv
660 }
661 }
662
663 pub fn unlock(&self) {
664 unsafe {
665 ll::SDL_UnlockSurface(self.raw);
666 }
667 }
668
669 pub fn flip(&self) -> bool {
670 unsafe { ll::SDL_Flip(self.raw) == 0 }
671 }
672
673 pub fn convert(&self, fmt: &PixelFormat, flags: &[SurfaceFlag]) -> Result<Surface, String> {
674 let flags = flags.iter().fold(0u32, |flags, &flag| flags | flag as u32);
675
676 let mut rawfmt = unwrap_pixel_format(fmt);
677
678 let new = unsafe { ll::SDL_ConvertSurface(self.raw, &mut rawfmt, flags) };
679 if new.is_null() {
680 Err(get_error())
681 } else {
682 Ok(wrap_surface(new, true))
683 }
684 }
685
686 pub fn try_clone(&self) -> Result<Surface, String> {
687 let new =
688 unsafe { ll::SDL_ConvertSurface(self.raw, (*self.raw).format, (*self.raw).flags) };
689 if new.is_null() {
690 Err(get_error())
691 } else {
692 Ok(wrap_surface(new, true))
693 }
694 }
695
696 pub fn display_format(&self) -> Result<Surface, String> {
697 let raw = unsafe { ll::SDL_DisplayFormat(self.raw) };
698
699 if raw.is_null() {
700 Err(get_error())
701 } else {
702 Ok(wrap_surface(raw, true))
703 }
704 }
705
706 pub fn display_format_alpha(&self) -> Result<Surface, String> {
707 let raw = unsafe { ll::SDL_DisplayFormatAlpha(self.raw) };
708
709 if raw.is_null() {
710 Err(get_error())
711 } else {
712 Ok(wrap_surface(raw, true))
713 }
714 }
715
716 pub fn save_bmp(&self, path: impl Into<String>) -> bool {
717 let path = path.into();
718 let cpath = CString::new(path).unwrap();
719 let mode = CString::new("wb").unwrap();
720 unsafe {
721 ll::SDL_SaveBMP_RW(
722 self.raw,
723 ll::SDL_RWFromFile(cpath.as_ptr(), mode.as_ptr()),
724 1,
725 ) == 0
726 }
727 }
728
729 pub fn set_alpha(&self, flags: &[SurfaceFlag], alpha: u8) -> bool {
730 let flags = flags.iter().fold(0u32, |flags, &flag| flags | flag as u32);
731
732 unsafe { ll::SDL_SetAlpha(self.raw, flags, alpha) == 0 }
733 }
734
735 pub fn set_color_key(&self, flags: &[SurfaceFlag], color: Color) -> bool {
736 let flags = flags.iter().fold(0u32, |flags, &flag| flags | flag as u32);
737
738 unsafe {
739 ll::SDL_SetColorKey(
740 self.raw,
741 flags,
742 color.to_mapped((*self.raw).format as *const _),
743 ) == 0
744 }
745 }
746
747 pub fn set_clip_rect(&self, rect: Rect) {
748 unsafe {
749 ll::SDL_SetClipRect(self.raw, &rect);
750 }
751 }
752
753 pub fn get_clip_rect(&self) -> Rect {
754 let rect = Rect {
755 x: 0,
756 y: 0,
757 w: 0,
758 h: 0,
759 };
760
761 unsafe {
762 ll::SDL_SetClipRect(self.raw, &rect as *const Rect);
763 }
764
765 rect
766 }
767
768 pub fn blit_rect(
769 &self,
770 src: &Surface,
771 src_rect: Option<Rect>,
772 dest_rect: Option<Rect>,
773 ) -> bool {
774 unsafe {
775 ll::SDL_UpperBlit(
776 src.raw,
777 match src_rect {
778 Some(ref rect) => rect as *const Rect as *mut Rect,
779 None => ptr::null_mut(),
780 },
781 self.raw,
782 match dest_rect {
783 Some(ref rect) => rect as *const Rect as *mut Rect,
784 None => ptr::null_mut(),
785 },
786 ) == 0
787 }
788 }
789
790 pub fn blit(&self, src: &Surface) -> bool {
791 self.blit_rect(src, None, None)
792 }
793
794 pub fn blit_at(&self, src: &Surface, x: i16, y: i16) -> bool {
795 let (w, h) = src.get_size();
796
797 self.blit_rect(src, None, Some(Rect { x, y, w, h }))
798 }
799
800 pub fn fill_rect(&self, rect: Option<Rect>, color: Color) -> bool {
801 unsafe {
802 ll::SDL_FillRect(
803 self.raw,
804 match rect {
805 Some(ref rect) => rect as *const Rect as *mut Rect,
806 None => ptr::null_mut(),
807 },
808 color.to_mapped((*self.raw).format as *const _),
809 ) == 0
810 }
811 }
812
813 pub fn fill(&self, color: Color) -> bool {
814 self.fill_rect(None, color)
815 }
816
817 pub fn clear(&self) -> bool {
818 self.fill(RGB(0, 0, 0))
819 }
820
821 pub fn draw_str(&self, font: &crate::nsdl::Font, msg: &str, x: i32, y: i32) {
822 font.draw(self.raw, msg, x, y)
823 }
824}
825
826impl Clone for Surface {
827 fn clone(&self) -> Self {
828 self.try_clone().unwrap()
829 }
830}
831
832pub fn set_gamma(r: f32, g: f32, b: f32) -> bool {
833 unsafe { ll::SDL_SetGamma(r as c_float, g as c_float, b as c_float) != -1 }
834}
835
836pub fn set_gamma_ramp(r: Option<[u16; 256]>, g: Option<[u16; 256]>, b: Option<[u16; 256]>) -> bool {
837 unsafe {
838 ll::SDL_SetGammaRamp(
839 match r {
840 Some(r) => r.as_ptr(),
841 None => ptr::null(),
842 },
843 match g {
844 Some(g) => g.as_ptr(),
845 None => ptr::null(),
846 },
847 match b {
848 Some(b) => b.as_ptr(),
849 None => ptr::null(),
850 },
851 ) != -1
852 }
853}
854
855pub fn get_gamma_ramp() -> ([u16; 256], [u16; 256], [u16; 256]) {
856 let mut r = [0u16; 256];
857 let mut g = [0u16; 256];
858 let mut b = [0u16; 256];
859
860 unsafe {
861 ll::SDL_GetGammaRamp(r.as_mut_ptr(), g.as_mut_ptr(), b.as_mut_ptr());
862 }
863
864 (r, g, b)
865}
866
867pub fn swap_buffers() {
868 unsafe {
869 ll::SDL_GL_SwapBuffers();
870 }
871}
872
873