Text not rendering with sdl2

Pasting large code block below. Sorry.

I'm at a loss as to why the following does not render text in the created window when run with cargo run PATH_TO_MY_FONT. I know the path is valid b/c when I run the sdl2 ttf-demo example with the same path argument it displays text just fine.

extern crate sdl2;

use std::env;
use std::path::Path;

use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
use sdl2::rect::Rect;
use sdl2::render::TextureQuery;
static SCREEN_WIDTH: u32 = 900;
static SCREEN_HEIGHT: u32 = 700;

// handle the annoying Rect i32
macro_rules! rect(
    ($x:expr, $y:expr, $w:expr, $h:expr) => (
        Rect::new($x as i32, $y as i32, $w as u32, $h as u32)
    )
);

// Scale fonts to a reasonable size when they're too big (though they might look less smooth)
fn get_centered_rect(rect_width: u32, rect_height: u32, cons_width: u32, cons_height: u32) -> Rect {
    let wr = rect_width as f32 / cons_width as f32;
    let hr = rect_height as f32 / cons_height as f32;

    let (w, h) = if wr > 1f32 || hr > 1f32 {
        if wr > hr {
            println!("Scaling down! The text will look worse!");
            let h = (rect_height as f32 / wr) as i32;
            (cons_width as i32, h)
        } else {
            println!("Scaling down! The text will look worse!");
            let w = (rect_width as f32 / hr) as i32;
            (w, cons_height as i32)
        }
    } else {
        (rect_width as i32, rect_height as i32)
    };

    let cx = (SCREEN_WIDTH as i32 - w) / 2;
    let cy = (SCREEN_HEIGHT as i32 - h) / 2;
    rect!(cx, cy, w, h)
}
fn run(font_path: &Path) -> Result<(), String> {
    let sdl = sdl2::init()?;
    let video_subsystem = sdl.video()?;
    let ttf_context = sdl2::ttf::init().map_err(|e| e.to_string())?;
    let mut window = video_subsystem
        .window("TOY", 900, 700)
        .resizable()
        .opengl()
        .build()
        .map_err(|e| e.to_string())?;
    window.set_opacity(0.5)?;
    let mut canvas = window.into_canvas().build().map_err(|e| e.to_string())?;
    let texture_creator = canvas.texture_creator();

    let mut font = ttf_context.load_font(font_path, 64)?;
    font.set_style(sdl2::ttf::FontStyle::BOLD);

    let surface = font
        .render("TESTING")
        .blended_wrapped(Color::RGBA(255, 0, 0, 255), 500)
        .map_err(|e| e.to_string())?;

    let texture = texture_creator
        .create_texture_from_surface(&surface)
        .map_err(|e| e.to_string())?;

    canvas.set_draw_color(Color::RGBA(255, 0, 0, 0));
    canvas.clear();
    let TextureQuery { width, height, .. } = texture.query();

    // If the example text is too big for the screen, downscale it (and center irregardless)
    let padding = 64;
    let target = get_centered_rect(
        width,
        height,
        SCREEN_WIDTH - padding,
        SCREEN_HEIGHT - padding,
    );

    canvas.copy(&texture, None, Some(target))?;
    canvas.present();

    'main: loop {
        for event in sdl.event_pump()?.poll_iter() {
            match event {
                sdl2::event::Event::Quit { .. } => break 'main,
                _ => {}
            }
        }
    }
    Ok(())
}

fn main() -> Result<(), String> {
    let args: Vec<_> = env::args().collect();
    println!("linked sdl2_ttf: {}", sdl2::ttf::get_linked_version());
    let path: &Path = Path::new(&args[1]);
    run(path)?;
    Ok(())
}

Here's the diff between a working and nonworking version. I don't see anything that makes sense to cause this problem.

diff --git a/src/main.rs b/src/main.rs
index 69cc7c3..883f4b2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -8,9 +8,8 @@ use sdl2::keyboard::Keycode;
 use sdl2::pixels::Color;
 use sdl2::rect::Rect;
 use sdl2::render::TextureQuery;
-
-static SCREEN_WIDTH: u32 = 800;
-static SCREEN_HEIGHT: u32 = 600;
+static SCREEN_WIDTH: u32 = 900;
+static SCREEN_HEIGHT: u32 = 700;
 
 // handle the annoying Rect i32
 macro_rules! rect(
@@ -42,40 +41,34 @@ fn get_centered_rect(rect_width: u32, rect_height: u32, cons_width: u32, cons_he
     let cy = (SCREEN_HEIGHT as i32 - h) / 2;
     rect!(cx, cy, w, h)
 }
-
 fn run(font_path: &Path) -> Result<(), String> {
-    let sdl_context = sdl2::init()?;
-    let video_subsys = sdl_context.video()?;
+    let sdl = sdl2::init()?;
+    let video_subsystem = sdl.video()?;
     let ttf_context = sdl2::ttf::init().map_err(|e| e.to_string())?;
-
-    let mut window = video_subsys
-        .window("SDL2_TTF Example", SCREEN_WIDTH, SCREEN_HEIGHT)
+    let mut window = video_subsystem
+        .window("TOY", SCREEN_WIDTH, SCREEN_HEIGHT)
         .resizable()
         .opengl()
         .build()
         .map_err(|e| e.to_string())?;
-
     window.set_opacity(0.5)?;
-
     let mut canvas = window.into_canvas().build().map_err(|e| e.to_string())?;
     let texture_creator = canvas.texture_creator();
 
-    // Load a font
     let mut font = ttf_context.load_font(font_path, 64)?;
     font.set_style(sdl2::ttf::FontStyle::BOLD);
 
-    // render a surface, and convert it to a texture bound to the canvas
     let surface = font
-        .render("Hello Rust!")
+        .render("TESTING")
         .blended_wrapped(Color::RGBA(255, 0, 0, 255), 500)
         .map_err(|e| e.to_string())?;
+
     let texture = texture_creator
         .create_texture_from_surface(&surface)
         .map_err(|e| e.to_string())?;
 
-    canvas.set_draw_color(Color::RGBA(195, 217, 255, 255));
+    canvas.set_draw_color(Color::RGBA(255, 0, 0, 255));
     canvas.clear();
-
     let TextureQuery { width, height, .. } = texture.query();
 
     // If the example text is too big for the screen, downscale it (and center irregardless)
@@ -90,33 +83,29 @@ fn run(font_path: &Path) -> Result<(), String> {
     canvas.copy(&texture, None, Some(target))?;
     canvas.present();
 
-    'mainloop: loop {
-        for event in sdl_context.event_pump()?.poll_iter() {
+    'main: loop {
+        for event in sdl.event_pump()?.poll_iter() {
             match event {
                 Event::KeyDown {
                     keycode: Some(Keycode::Escape),
                     ..
                 }
-                | Event::Quit { .. } => break 'mainloop,
+                | Event::Quit { .. } => break 'main,
                 _ => {}
             }
         }
     }
-
     Ok(())
 }
 
 fn main() -> Result<(), String> {
     let args: Vec<_> = env::args().collect();
-
     println!("linked sdl2_ttf: {}", sdl2::ttf::get_linked_version());
-
     if args.len() < 2 {
         println!("Usage: ./demo font.[ttf|ttc|fon]")
     } else {
         let path: &Path = Path::new(&args[1]);
         run(path)?;
     }
-
     Ok(())
 }

It looks like both the surface's color and the canvas's draw color are set to Color::RGBA(255, 0, 0, 255) in your modified snippet.

Are you sure it isn't just drawing the text the same color as the background, rendering it invisible?

1 Like

3 Likes