Skip to main content

dear_imgui_rs/stacks/
font.rs

1use crate::fonts::FontId;
2use crate::{Ui, sys};
3
4/// # Parameter stacks (shared)
5impl Ui {
6    /// Switches to the given font at its configured reference size.
7    ///
8    /// Dear ImGui 1.92 can rasterize a font at multiple sizes. This convenience
9    /// method preserves the pre-1.92 behavior by using the reference size
10    /// supplied when the font was added. Use [`Ui::push_font_with_size`] to
11    /// preserve the current size or select another runtime size explicitly.
12    /// A font without a reference size also preserves the current size.
13    ///
14    /// Returns a `FontStackToken` that must be popped by calling `.pop()`
15    ///
16    /// # Panics
17    ///
18    /// Panics before calling Dear ImGui if the `FontId` came from a different atlas,
19    /// was invalidated by font atlas mutation, or is no longer present in the
20    /// current context's atlas.
21    ///
22    /// # Examples
23    ///
24    /// ```no_run
25    /// # use dear_imgui_rs::*;
26    /// # let mut ctx = Context::create();
27    /// # let font_data_sources = [];
28    /// // At initialization time
29    /// let my_custom_font = ctx.font_atlas().add_font(&font_data_sources);
30    /// # let ui = ctx.frame();
31    /// // During UI construction
32    /// let font = ui.push_font(my_custom_font);
33    /// ui.text("I use the custom font!");
34    /// font.pop();
35    /// ```
36    #[doc(alias = "PushFont")]
37    pub fn push_font(&self, id: FontId) -> FontStackToken<'_> {
38        self.run_with_bound_context(|| unsafe {
39            let font_ptr =
40                crate::fonts::validate_font_id_for_current_context(id, "Ui::push_font()");
41            sys::igPushFont(font_ptr, (*font_ptr).LegacySize);
42        });
43        FontStackToken::new(self)
44    }
45}
46
47create_token!(
48    /// Tracks a font pushed to the font stack that can be popped by calling `.end()`
49    /// or by dropping.
50    #[doc(alias = "PopFont")]
51    pub struct FontStackToken<'ui>;
52
53    /// Pops a change from the font stack.
54    drop { unsafe { sys::igPopFont() } }
55);
56
57impl FontStackToken<'_> {
58    /// Pops a change from the font stack.
59    pub fn pop(self) {
60        self.end()
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    const ROBOTO_MEDIUM: &[u8] = include_bytes!(concat!(
67        env!("CARGO_MANIFEST_DIR"),
68        "/../dear-imgui-sys/third-party/cimgui/imgui/misc/fonts/Roboto-Medium.ttf"
69    ));
70
71    #[test]
72    fn push_font_uses_the_size_supplied_when_the_font_was_added() {
73        let mut ctx = crate::Context::create();
74        let small = ctx
75            .font_atlas()
76            .add_font(&[crate::FontSource::default_font_with_size(13.0)]);
77        let large = ctx
78            .font_atlas()
79            .add_font(&[crate::FontSource::default_font_with_size(29.0)]);
80        assert_eq!(small.reference_size(), Some(13.0));
81        assert_eq!(large.reference_size(), Some(29.0));
82        let _ = ctx.font_atlas().build();
83        ctx.io_mut().set_display_size([128.0, 128.0]);
84        ctx.io_mut().set_delta_time(1.0 / 60.0);
85
86        let ui = ctx.frame();
87        assert_eq!(ui.current_font(), small);
88        assert_eq!(ui.current_font_size(), 13.0);
89
90        {
91            let _font = ui.push_font(large);
92            assert_eq!(ui.current_font(), large);
93            assert_eq!(ui.current_font_size(), 29.0);
94        }
95
96        assert_eq!(ui.current_font(), small);
97        assert_eq!(ui.current_font_size(), 13.0);
98    }
99
100    #[test]
101    fn push_font_preserves_current_size_without_a_reference_size() {
102        let mut ctx = crate::Context::create();
103        let _consumer = ctx
104            .create_renderer_consumer()
105            .expect("the managed renderer consumer should attach");
106        let small = ctx
107            .font_atlas()
108            .add_font(&[crate::FontSource::default_font_with_size(13.0)]);
109        // SAFETY: the vendored bytes contain the complete, unmodified Roboto Medium TTF.
110        let dynamic = ctx
111            .font_atlas()
112            .add_font(&[unsafe { crate::FontSource::ttf_data(ROBOTO_MEDIUM) }]);
113        assert_eq!(dynamic.reference_size(), None);
114        ctx.io_mut().set_display_size([128.0, 128.0]);
115        ctx.io_mut().set_delta_time(1.0 / 60.0);
116        ctx.io_mut()
117            .set_backend_flags(crate::BackendFlags::RENDERER_HAS_TEXTURES);
118
119        let ui = ctx.frame();
120        assert_eq!(ui.current_font(), small);
121        assert_eq!(ui.current_font_size(), 13.0);
122
123        let _font = ui.push_font(dynamic);
124        assert_eq!(ui.current_font(), dynamic);
125        assert_eq!(ui.current_font_size(), 13.0);
126    }
127}