1 extern crate sdl2;
2 
3 use std::env;
4 use std::path::Path;
5 
6 use sdl2::event::Event;
7 use sdl2::keyboard::Keycode;
8 use sdl2::rect::Rect;
9 use sdl2::render::TextureQuery;
10 use sdl2::pixels::Color;
11 
12 static SCREEN_WIDTH : u32 = 800;
13 static SCREEN_HEIGHT : u32 = 600;
14 
15 // handle the annoying Rect i32
16 macro_rules! rect(
17     ($x:expr, $y:expr, $w:expr, $h:expr) => (
18         Rect::new($x as i32, $y as i32, $w as u32, $h as u32)
19     )
20 );
21 
22 // Scale fonts to a reasonable size when they're too big (though they might look less smooth)
get_centered_rect(rect_width: u32, rect_height: u32, cons_width: u32, cons_height: u32) -> Rect23 fn get_centered_rect(rect_width: u32, rect_height: u32, cons_width: u32, cons_height: u32) -> Rect {
24     let wr = rect_width as f32 / cons_width as f32;
25     let hr = rect_height as f32 / cons_height as f32;
26 
27     let (w, h) = if wr > 1f32 || hr > 1f32 {
28         if wr > hr {
29             println!("Scaling down! The text will look worse!");
30             let h = (rect_height as f32 / wr) as i32;
31             (cons_width as i32, h)
32         } else {
33             println!("Scaling down! The text will look worse!");
34             let w = (rect_width as f32 / hr) as i32;
35             (w, cons_height as i32)
36         }
37     } else {
38         (rect_width as i32, rect_height as i32)
39     };
40 
41     let cx = (SCREEN_WIDTH as i32 - w) / 2;
42     let cy = (SCREEN_HEIGHT as i32 - h) / 2;
43     rect!(cx, cy, w, h)
44 }
45 
run(font_path: &Path) -> Result<(), String>46 fn run(font_path: &Path) -> Result<(), String> {
47     let sdl_context = sdl2::init()?;
48     let video_subsys = sdl_context.video()?;
49     let ttf_context = sdl2::ttf::init().map_err(|e| e.to_string())?;
50 
51     let window = video_subsys.window("SDL2_TTF Example", SCREEN_WIDTH, SCREEN_HEIGHT)
52         .position_centered()
53         .opengl()
54         .build()
55         .map_err(|e| e.to_string())?;
56 
57     let mut canvas = window.into_canvas().build().map_err(|e| e.to_string())?;
58     let texture_creator = canvas.texture_creator();
59 
60     // Load a font
61     let mut font = ttf_context.load_font(font_path, 128)?;
62     font.set_style(sdl2::ttf::FontStyle::BOLD);
63 
64     // render a surface, and convert it to a texture bound to the canvas
65     let surface = font.render("Hello Rust!")
66         .blended(Color::RGBA(255, 0, 0, 255)).map_err(|e| e.to_string())?;
67     let texture = texture_creator.create_texture_from_surface(&surface)
68         .map_err(|e| e.to_string())?;
69 
70     canvas.set_draw_color(Color::RGBA(195, 217, 255, 255));
71     canvas.clear();
72 
73     let TextureQuery { width, height, .. } = texture.query();
74 
75     // If the example text is too big for the screen, downscale it (and center irregardless)
76     let padding = 64;
77     let target = get_centered_rect(width, height, SCREEN_WIDTH - padding, SCREEN_HEIGHT - padding);
78 
79     canvas.copy(&texture, None, Some(target))?;
80     canvas.present();
81 
82     'mainloop: loop {
83         for event in sdl_context.event_pump()?.poll_iter() {
84             match event {
85                 Event::KeyDown {keycode: Some(Keycode::Escape), ..} |
86                 Event::Quit {..} => break 'mainloop,
87                 _ => {}
88             }
89         }
90     }
91 
92     Ok(())
93 }
94 
main() -> Result<(), String>95 fn main() -> Result<(), String> {
96     let args: Vec<_> = env::args().collect();
97 
98     println!("linked sdl2_ttf: {}", sdl2::ttf::get_linked_version());
99 
100     if args.len() < 2 {
101         println!("Usage: ./demo font.[ttf|ttc|fon]")
102     } else {
103         let path: &Path = Path::new(&args[1]);
104         run(path)?;
105     }
106 
107     Ok(())
108 }
109