Skip to content

Commit

Permalink
prevent users from creating Sdl2TtfContext out of nothing
Browse files Browse the repository at this point in the history
and various other changes, including:
- allow multiple `ttf::init` calls, the same way it works with TTF_Init
- return last sdl error instead of I/O error (like stale pr #1348, fixes #1347 and closes #1348)
- implement `Clone` for `Sdl2TtfContext`, SDL C code will do the reference counting
- make `ttf::font::internal_*` `pub(super)`
- make `ttf::font::Font::raw` safe (obtaining a raw pointer is safe, using it is unsafe)
  • Loading branch information
antonilol committed Oct 8, 2024
1 parent 400e033 commit c4e74c7
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 21 deletions.
40 changes: 23 additions & 17 deletions src/sdl2/ttf/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use get_error;
use rwops::RWops;
use std::error;
use std::fmt;
use std::io;
use std::os::raw::{c_int, c_long};
use std::path::Path;
use sys::ttf;
Expand All @@ -14,7 +13,14 @@ use super::font::{

/// A context manager for `SDL2_TTF` to manage C code initialization and clean-up.
#[must_use]
pub struct Sdl2TtfContext;
pub struct Sdl2TtfContext(());

impl Clone for Sdl2TtfContext {
fn clone(&self) -> Self {
// This should not return an error because SDL_ttf is already initialized
init().unwrap()
}
}

// Clean up the context once it goes out of scope
impl Drop for Sdl2TtfContext {
Expand Down Expand Up @@ -54,7 +60,7 @@ impl Sdl2TtfContext {
point_size: u16,
) -> Result<Font<'ttf, 'r>, String> {
let raw = unsafe { ttf::TTF_OpenFontRW(rwops.raw(), 0, point_size as c_int) };
if (raw as *mut ()).is_null() {
if raw.is_null() {
Err(get_error())
} else {
Ok(internal_load_font_from_ll(raw, Some(rwops)))
Expand All @@ -72,7 +78,7 @@ impl Sdl2TtfContext {
let raw = unsafe {
ttf::TTF_OpenFontIndexRW(rwops.raw(), 0, point_size as c_int, index as c_long)
};
if (raw as *mut ()).is_null() {
if raw.is_null() {
Err(get_error())
} else {
Ok(internal_load_font_from_ll(raw, Some(rwops)))
Expand All @@ -82,22 +88,21 @@ impl Sdl2TtfContext {

/// Returns the version of the dynamically linked `SDL_TTF` library
pub fn get_linked_version() -> Version {
unsafe { Version::from_ll(*ttf::TTF_Linked_Version()) }
Version::from_ll(unsafe { *ttf::TTF_Linked_Version() })
}

/// An error for when `sdl2_ttf` is attempted initialized twice
/// Necessary for context management, unless we find a way to have a singleton
#[derive(Debug)]
pub enum InitError {
InitializationError(io::Error),
InitializationError(String),
AlreadyInitializedError,
}

impl error::Error for InitError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match *self {
InitError::AlreadyInitializedError => None,
InitError::InitializationError(ref error) => Some(error),
InitError::InitializationError(_) | InitError::AlreadyInitializedError => None,
}
}
}
Expand All @@ -115,19 +120,20 @@ impl fmt::Display for InitError {

/// Initializes the truetype font API and returns a context manager which will
/// clean up the library once it goes out of scope.
#[doc(alias = "TTF_Init")]
pub fn init() -> Result<Sdl2TtfContext, InitError> {
unsafe {
if ttf::TTF_WasInit() == 1 {
Err(InitError::AlreadyInitializedError)
} else if ttf::TTF_Init() == 0 {
Ok(Sdl2TtfContext)
} else {
Err(InitError::InitializationError(io::Error::last_os_error()))
}
if unsafe { ttf::TTF_Init() } == 0 {
Ok(Sdl2TtfContext(()))
} else {
Err(InitError::InitializationError(get_error()))
}
}

/// Returns whether library has been initialized already.
pub fn has_been_initialized() -> bool {
unsafe { ttf::TTF_WasInit() == 1 }
amount_of_times_initialized() != 0
}

fn amount_of_times_initialized() -> c_int {
unsafe { ttf::TTF_WasInit() }
}
11 changes: 7 additions & 4 deletions src/sdl2/ttf/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ impl<'ttf, 'r> Drop for Font<'ttf, 'r> {
}

/// Internally used to load a font (for internal visibility).
pub fn internal_load_font<'ttf, P: AsRef<Path>>(
pub(super) fn internal_load_font<'ttf, P: AsRef<Path>>(
path: P,
ptsize: u16,
) -> Result<Font<'ttf, 'static>, String> {
Expand All @@ -271,7 +271,10 @@ pub fn internal_load_font<'ttf, P: AsRef<Path>>(
}

/// Internally used to load a font (for internal visibility).
pub fn internal_load_font_from_ll<'ttf, 'r, R>(raw: *mut ttf::TTF_Font, rwops: R) -> Font<'ttf, 'r>
pub(super) fn internal_load_font_from_ll<'ttf, 'r, R>(
raw: *mut ttf::TTF_Font,
rwops: R,
) -> Font<'ttf, 'r>
where
R: Into<Option<RWops<'r>>>,
{
Expand All @@ -283,7 +286,7 @@ where
}

/// Internally used to load a font (for internal visibility).
pub fn internal_load_font_at_index<'ttf, P: AsRef<Path>>(
pub(super) fn internal_load_font_at_index<'ttf, P: AsRef<Path>>(
path: P,
index: u32,
ptsize: u16,
Expand All @@ -308,7 +311,7 @@ impl<'ttf, 'r> Font<'ttf, 'r> {
// this can prevent introducing UB until
// https://github.com/rust-lang/rust-clippy/issues/5953 is fixed
#[allow(clippy::trivially_copy_pass_by_ref)]
unsafe fn raw(&self) -> *mut ttf::TTF_Font {
fn raw(&self) -> *mut ttf::TTF_Font {
self.raw
}

Expand Down

0 comments on commit c4e74c7

Please sign in to comment.