From c4e74c77950052c1d930720b3aa103ed083d5a5b Mon Sep 17 00:00:00 2001 From: Antoni Spaanderman <56turtle56@gmail.com> Date: Tue, 8 Oct 2024 17:33:08 +0200 Subject: [PATCH 1/3] prevent users from creating `Sdl2TtfContext` out of nothing 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) --- src/sdl2/ttf/context.rs | 40 +++++++++++++++++++++++----------------- src/sdl2/ttf/font.rs | 11 +++++++---- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/sdl2/ttf/context.rs b/src/sdl2/ttf/context.rs index 8d967606ea..2f713c1949 100644 --- a/src/sdl2/ttf/context.rs +++ b/src/sdl2/ttf/context.rs @@ -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; @@ -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 { @@ -54,7 +60,7 @@ impl Sdl2TtfContext { point_size: u16, ) -> Result, 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))) @@ -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))) @@ -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, } } } @@ -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 { - 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() } } diff --git a/src/sdl2/ttf/font.rs b/src/sdl2/ttf/font.rs index 3a2fa2c34a..664f0686ab 100644 --- a/src/sdl2/ttf/font.rs +++ b/src/sdl2/ttf/font.rs @@ -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>( +pub(super) fn internal_load_font<'ttf, P: AsRef>( path: P, ptsize: u16, ) -> Result, String> { @@ -271,7 +271,10 @@ pub fn internal_load_font<'ttf, P: AsRef>( } /// 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>>, { @@ -283,7 +286,7 @@ where } /// Internally used to load a font (for internal visibility). -pub fn internal_load_font_at_index<'ttf, P: AsRef>( +pub(super) fn internal_load_font_at_index<'ttf, P: AsRef>( path: P, index: u32, ptsize: u16, @@ -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 } From d5985e36907ccffee4d2423b234206e10a6c9409 Mon Sep 17 00:00:00 2001 From: Antoni Spaanderman <56turtle56@gmail.com> Date: Tue, 8 Oct 2024 17:45:30 +0200 Subject: [PATCH 2/3] remove `InitError` because only one variant was used --- src/sdl2/ttf/context.rs | 31 ++----------------------------- src/sdl2/ttf/mod.rs | 4 +--- 2 files changed, 3 insertions(+), 32 deletions(-) diff --git a/src/sdl2/ttf/context.rs b/src/sdl2/ttf/context.rs index 2f713c1949..2da29b632c 100644 --- a/src/sdl2/ttf/context.rs +++ b/src/sdl2/ttf/context.rs @@ -91,41 +91,14 @@ pub fn get_linked_version() -> 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(String), - AlreadyInitializedError, -} - -impl error::Error for InitError { - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match *self { - InitError::InitializationError(_) | InitError::AlreadyInitializedError => None, - } - } -} - -impl fmt::Display for InitError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::AlreadyInitializedError => { - write!(f, "SDL2_TTF has already been initialized") - } - Self::InitializationError(error) => write!(f, "SDL2_TTF initialization error: {error}"), - } - } -} - /// 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 { +pub fn init() -> Result { if unsafe { ttf::TTF_Init() } == 0 { Ok(Sdl2TtfContext(())) } else { - Err(InitError::InitializationError(get_error())) + Err(get_error()) } } diff --git a/src/sdl2/ttf/mod.rs b/src/sdl2/ttf/mod.rs index 2f9f02e38a..6477c6d59f 100644 --- a/src/sdl2/ttf/mod.rs +++ b/src/sdl2/ttf/mod.rs @@ -23,9 +23,7 @@ mod context; mod font; -pub use self::context::{ - get_linked_version, has_been_initialized, init, InitError, Sdl2TtfContext, -}; +pub use self::context::{get_linked_version, has_been_initialized, init, Sdl2TtfContext}; pub use self::font::{ Font, FontError, FontResult, FontStyle, GlyphMetrics, Hinting, PartialRendering, }; From ffe598c5a2b655888c59020f376e9ab5b23e2d02 Mon Sep 17 00:00:00 2001 From: Antoni Spaanderman <56turtle56@gmail.com> Date: Tue, 8 Oct 2024 17:48:41 +0200 Subject: [PATCH 3/3] update changelog --- changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog.md b/changelog.md index 12808ac830..fb4a3ab70f 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,8 @@ when upgrading from a version of rust-sdl2 to another. ### Next +[PR #1437](https://github.com/Rust-SDL2/rust-sdl2/pull/1437) **BREAKING CHANGE** Prevent users from creating `Sdl2TtfContext` out of nothing and use SDL's reference counting init/quit + [PR #1416](https://github.com/Rust-SDL2/rust-sdl2/pull/1416) Apply clippy fixes, fix deprecations and other code quality improvements. [PR #1408](https://github.com/Rust-SDL2/rust-sdl2/pull/1408) Allow comparing `Version`s, add constant with the version the bindings were compiled with.