1 use std::io;
2 use std::error;
3 use std::fmt;
4 use std::os::raw::{c_int, c_long};
5 use std::path::Path;
6 use ::get_error;
7 use ::rwops::RWops;
8 use ::version::Version;
9 use sys;
10 
11 use super::font::{
12     internal_load_font,
13     internal_load_font_at_index,
14     internal_load_font_from_ll,
15     Font,
16 };
17 
18 /// A context manager for `SDL2_TTF` to manage C code initialization and clean-up.
19 #[must_use]
20 pub struct Sdl2TtfContext;
21 
22 // Clean up the context once it goes out of scope
23 impl Drop for Sdl2TtfContext {
drop(&mut self)24     fn drop(&mut self) {
25         unsafe { sys::ttf::TTF_Quit(); }
26     }
27 }
28 
29 impl Sdl2TtfContext {
30     /// Loads a font from the given file with the given size in points.
load_font<'ttf, P: AsRef<Path>>(&'ttf self, path: P, point_size: u16) -> Result<Font<'ttf,'static>, String>31     pub fn load_font<'ttf, P: AsRef<Path>>(&'ttf self, path: P, point_size: u16) -> Result<Font<'ttf,'static>, String> {
32         internal_load_font(path, point_size)
33     }
34 
35     /// Loads the font at the given index of the file, with the given
36     /// size in points.
load_font_at_index<'ttf, P: AsRef<Path>>(&'ttf self, path: P, index: u32, point_size: u16) -> Result<Font<'ttf,'static>, String>37     pub fn load_font_at_index<'ttf, P: AsRef<Path>>(&'ttf self, path: P, index: u32, point_size: u16)
38             -> Result<Font<'ttf,'static>, String> {
39         internal_load_font_at_index(path, index, point_size)
40     }
41 
42     /// Loads a font from the given SDL2 rwops object with the given size in
43     /// points.
load_font_from_rwops<'ttf,'r>(&'ttf self, rwops: RWops<'r>, point_size: u16) -> Result<Font<'ttf,'r>, String>44     pub fn load_font_from_rwops<'ttf,'r>(&'ttf self, rwops: RWops<'r>, point_size: u16)
45             -> Result<Font<'ttf,'r>, String> {
46         let raw = unsafe {
47             sys::ttf::TTF_OpenFontRW(rwops.raw(), 0, point_size as c_int)
48         };
49         if (raw as *mut ()).is_null() {
50             Err(get_error())
51         } else {
52             Ok(internal_load_font_from_ll(raw, Some(rwops)))
53         }
54     }
55 
56     /// Loads the font at the given index of the SDL2 rwops object with
57     /// the given size in points.
load_font_at_index_from_rwops<'ttf,'r>(&'ttf self, rwops: RWops<'r>, index: u32, point_size: u16) -> Result<Font<'ttf,'r>, String>58     pub fn load_font_at_index_from_rwops<'ttf,'r>(&'ttf self, rwops: RWops<'r>, index: u32,
59             point_size: u16) -> Result<Font<'ttf,'r>, String> {
60         let raw = unsafe {
61             sys::ttf::TTF_OpenFontIndexRW(rwops.raw(), 0, point_size as c_int,
62                 index as c_long)
63         };
64         if (raw as *mut ()).is_null() {
65             Err(get_error())
66         } else {
67             Ok(internal_load_font_from_ll(raw, Some(rwops)))
68         }
69     }
70 }
71 
72 /// Returns the version of the dynamically linked `SDL_TTF` library
get_linked_version() -> Version73 pub fn get_linked_version() -> Version {
74     unsafe {
75         Version::from_ll(*sys::ttf::TTF_Linked_Version())
76     }
77 }
78 
79 /// An error for when `sdl2_ttf` is attempted initialized twice
80 /// Necessary for context management, unless we find a way to have a singleton
81 #[derive(Debug)]
82 pub enum InitError {
83     InitializationError(io::Error),
84     AlreadyInitializedError,
85 }
86 
87 impl error::Error for InitError {
description(&self) -> &str88     fn description(&self) -> &str {
89         match *self {
90             InitError::AlreadyInitializedError => {
91                 "SDL2_TTF has already been initialized"
92             },
93             InitError::InitializationError(ref error) => {
94                 error.description()
95             },
96         }
97     }
98 
cause(&self) -> Option<&error::Error>99     fn cause(&self) -> Option<&error::Error> {
100         match *self {
101             InitError::AlreadyInitializedError => {
102                 None
103             },
104             InitError::InitializationError(ref error) => {
105                 Some(error)
106             },
107         }
108     }
109 }
110 
111 impl fmt::Display for InitError {
fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error>112     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
113         formatter.write_str("SDL2_TTF has already been initialized")
114     }
115 }
116 
117 /// Initializes the truetype font API and returns a context manager which will
118 /// clean up the library once it goes out of scope.
init() -> Result<Sdl2TtfContext, InitError>119 pub fn init() -> Result<Sdl2TtfContext, InitError> {
120     unsafe {
121         if sys::ttf::TTF_WasInit() == 1 {
122             Err(InitError::AlreadyInitializedError)
123         } else if sys::ttf::TTF_Init() == 0 {
124             Ok(Sdl2TtfContext)
125         } else {
126             Err(InitError::InitializationError(
127                 io::Error::last_os_error()
128                     ))
129         }
130     }
131 }
132 
133 /// Returns whether library has been initialized already.
has_been_initialized() -> bool134 pub fn has_been_initialized() -> bool {
135     unsafe {
136         sys::ttf::TTF_WasInit() == 1
137     }
138 }
139