Skip to content

Commit

Permalink
Put font data into Arc to reduce memory consumption (#5276)
Browse files Browse the repository at this point in the history
egui never accesses the `FontDefinitions`' member fields mutably, except
in `fonts_tweak_ui` where it cloned the `FontDefinitions` object anyway.

This patch reduces system memory consumption for shared font
definitions.
And also removes some overhead from copying (e.g. for the per
`pixel_per_points` font atlas)

Also it allows to keep a copy of the font definitions outside of egui.

In my App that uses international fonts:
Before:

![image](https://github.com/user-attachments/assets/f8dfb4f4-a21c-447c-8cf9-83025ad6e960)

New:

![image](https://github.com/user-attachments/assets/9f297fbd-e620-4b7e-a32a-65073ee805ed)


Note: If `Arc` is not wanted, then it could ofc be abstracted away.

I know this is quite a breaking change API wise, but would like to hear
your opinion.
  • Loading branch information
StarStarJ authored Nov 1, 2024
1 parent 793cb92 commit 3f5cd74
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 14 deletions.
8 changes: 6 additions & 2 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,9 @@ impl ContextImpl {
FontPriority::Lowest => fam.push(font.name.clone()),
}
}
self.font_definitions.font_data.insert(font.name, font.data);
self.font_definitions
.font_data
.insert(font.name, Arc::new(font.data));
}

#[cfg(feature = "log")]
Expand Down Expand Up @@ -2944,7 +2946,9 @@ impl Context {

for (name, data) in &mut font_definitions.font_data {
ui.collapsing(name, |ui| {
if data.tweak.ui(ui).changed() {
let mut tweak = data.tweak;
if tweak.ui(ui).changed() {
Arc::make_mut(data).tweak = tweak;
changed = true;
}
});
Expand Down
27 changes: 17 additions & 10 deletions crates/epaint/src/text/fonts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,11 @@ fn ab_glyph_font_from_font_data(name: &str, data: &FontData) -> ab_glyph::FontAr
///
/// // Install my own font (maybe supporting non-latin characters):
/// fonts.font_data.insert("my_font".to_owned(),
/// FontData::from_static(include_bytes!("../../../epaint_default_fonts/fonts/Ubuntu-Light.ttf"))); // .ttf and .otf supported
/// std::sync::Arc::new(
/// // .ttf and .otf supported
/// FontData::from_static(include_bytes!("../../../epaint_default_fonts/fonts/Ubuntu-Light.ttf"))
/// )
/// );
///
/// // Put my font first (highest priority):
/// fonts.families.get_mut(&FontFamily::Proportional).unwrap()
Expand All @@ -243,7 +247,7 @@ pub struct FontDefinitions {
/// List of font names and their definitions.
///
/// `epaint` has built-in-default for these, but you can override them if you like.
pub font_data: BTreeMap<String, FontData>,
pub font_data: BTreeMap<String, Arc<FontData>>,

/// Which fonts (names) to use for each [`FontFamily`].
///
Expand Down Expand Up @@ -310,33 +314,36 @@ impl Default for FontDefinitions {
/// otherwise this is the same as [`Self::empty`].
#[cfg(feature = "default_fonts")]
fn default() -> Self {
let mut font_data: BTreeMap<String, FontData> = BTreeMap::new();
let mut font_data: BTreeMap<String, Arc<FontData>> = BTreeMap::new();

let mut families = BTreeMap::new();

font_data.insert("Hack".to_owned(), FontData::from_static(HACK_REGULAR));
font_data.insert(
"Hack".to_owned(),
Arc::new(FontData::from_static(HACK_REGULAR)),
);

// Some good looking emojis. Use as first priority:
font_data.insert(
"NotoEmoji-Regular".to_owned(),
FontData::from_static(NOTO_EMOJI_REGULAR).tweak(FontTweak {
Arc::new(FontData::from_static(NOTO_EMOJI_REGULAR).tweak(FontTweak {
scale: 0.81, // Make smaller
..Default::default()
}),
})),
);

font_data.insert(
"Ubuntu-Light".to_owned(),
FontData::from_static(UBUNTU_LIGHT),
Arc::new(FontData::from_static(UBUNTU_LIGHT)),
);

// Bigger emojis, and more. <http://jslegers.github.io/emoji-icon-font/>:
font_data.insert(
"emoji-icon-font".to_owned(),
FontData::from_static(EMOJI_ICON).tweak(FontTweak {
Arc::new(FontData::from_static(EMOJI_ICON).tweak(FontTweak {
scale: 0.90, // Make smaller
..Default::default()
}),
})),
);

families.insert(
Expand Down Expand Up @@ -795,7 +802,7 @@ impl FontImplCache {
pub fn new(
atlas: Arc<Mutex<TextureAtlas>>,
pixels_per_point: f32,
font_data: &BTreeMap<String, FontData>,
font_data: &BTreeMap<String, Arc<FontData>>,
) -> Self {
let ab_glyph_fonts = font_data
.iter()
Expand Down
4 changes: 2 additions & 2 deletions examples/custom_font/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ fn replace_fonts(ctx: &egui::Context) {
// .ttf and .otf files supported.
fonts.font_data.insert(
"my_font".to_owned(),
egui::FontData::from_static(include_bytes!(
std::sync::Arc::new(egui::FontData::from_static(include_bytes!(
"../../../crates/epaint_default_fonts/fonts/Hack-Regular.ttf"
)),
))),
);

// Put my font first (highest priority) for proportional text:
Expand Down

0 comments on commit 3f5cd74

Please sign in to comment.