Skip to main content

dear_imgui_rs/fonts/atlas/
texture.rs

1use std::fmt;
2use std::marker::PhantomData;
3use std::ops::Deref;
4use std::ptr::NonNull;
5use std::rc::Rc;
6
7use crate::sys;
8use crate::texture::TextureData;
9
10use super::FontAtlas;
11use super::state::{acquire_font_atlas_texture_borrow, release_font_atlas_texture_borrow};
12
13/// Read-only lease for the current font atlas texture.
14///
15/// The lease keeps safe atlas operations and frame advancement from invalidating the texture or
16/// its pixel buffer. Drop it before rebuilding, compacting, clearing, writing custom rectangles,
17/// or starting another frame that uses the atlas.
18#[must_use = "keep the texture lease alive while using texture data or pixel slices"]
19pub struct FontAtlasTexture<'atlas> {
20    atlas: NonNull<sys::ImFontAtlas>,
21    texture: NonNull<sys::ImTextureData>,
22    atlas_stamp: u64,
23    _atlas: PhantomData<&'atlas FontAtlas>,
24    _not_send_sync: PhantomData<Rc<()>>,
25}
26
27impl<'atlas> FontAtlasTexture<'atlas> {
28    pub(crate) unsafe fn from_raw(
29        atlas: *mut sys::ImFontAtlas,
30        texture: *mut sys::ImTextureData,
31    ) -> Option<Self> {
32        let atlas = NonNull::new(atlas)?;
33        let texture = NonNull::new(texture)?;
34        let atlas_stamp = acquire_font_atlas_texture_borrow(atlas.as_ptr());
35        Some(Self {
36            atlas,
37            texture,
38            atlas_stamp,
39            _atlas: PhantomData,
40            _not_send_sync: PhantomData,
41        })
42    }
43
44    /// Returns an owner-backed logical reference for image and plotting APIs.
45    pub fn texture_ref(&self) -> crate::texture::TextureRef<'_> {
46        let texture = unsafe { sys::ImTextureData_GetTexRef(self.texture.as_ptr()) };
47        crate::texture::TextureRef::from_font_atlas_raw(self.atlas.as_ptr(), texture)
48    }
49}
50
51impl crate::Ui {
52    /// Lease the current Context's font-atlas texture for immediate image submission.
53    pub fn font_atlas_texture(&self) -> Option<FontAtlasTexture<'_>> {
54        self.run_with_bound_context(|| unsafe {
55            let io = sys::igGetIO_ContextPtr(self.context_raw());
56            if io.is_null() || (*io).Fonts.is_null() {
57                return None;
58            }
59            let atlas = (*io).Fonts;
60            FontAtlasTexture::from_raw(atlas, (*atlas).TexData)
61        })
62    }
63}
64
65impl Deref for FontAtlasTexture<'_> {
66    type Target = TextureData;
67
68    fn deref(&self) -> &Self::Target {
69        unsafe { TextureData::from_raw_ref(self.texture.as_ptr()) }
70    }
71}
72
73impl fmt::Debug for FontAtlasTexture<'_> {
74    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
75        formatter
76            .debug_struct("FontAtlasTexture")
77            .field("native_unique_id", &self.native_unique_id())
78            .field("status", &self.status())
79            .field("format", &self.format())
80            .field("width", &self.width())
81            .field("height", &self.height())
82            .finish_non_exhaustive()
83    }
84}
85
86impl Drop for FontAtlasTexture<'_> {
87    fn drop(&mut self) {
88        release_font_atlas_texture_borrow(self.atlas.as_ptr(), self.atlas_stamp);
89    }
90}