bevy_text/
font_atlas_set.rs

1use crate::{Font, FontAtlas, FontSmoothing, TextFont};
2use bevy_asset::{AssetEvent, AssetId};
3use bevy_derive::{Deref, DerefMut};
4use bevy_ecs::{message::MessageReader, resource::Resource, system::ResMut};
5use bevy_platform::collections::HashMap;
6
7/// Identifies the font atlases for a particular font in [`FontAtlasSet`]
8///
9/// Allows an `f32` font size to be used as a key in a `HashMap`, by its binary representation.
10#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
11pub struct FontAtlasKey(pub AssetId<Font>, pub u32, pub FontSmoothing);
12
13impl From<&TextFont> for FontAtlasKey {
14    fn from(font: &TextFont) -> Self {
15        FontAtlasKey(
16            font.font.id(),
17            font.font_size.to_bits(),
18            font.font_smoothing,
19        )
20    }
21}
22
23/// Set of rasterized fonts stored in [`FontAtlas`]es.
24#[derive(Debug, Default, Resource, Deref, DerefMut)]
25pub struct FontAtlasSet(HashMap<FontAtlasKey, Vec<FontAtlas>>);
26
27impl FontAtlasSet {
28    /// Checks whether the given subpixel-offset glyph is contained in any of the [`FontAtlas`]es for the font identified by the given [`FontAtlasKey`].
29    pub fn has_glyph(&self, cache_key: cosmic_text::CacheKey, font_key: &FontAtlasKey) -> bool {
30        self.get(font_key)
31            .is_some_and(|font_atlas| font_atlas.iter().any(|atlas| atlas.has_glyph(cache_key)))
32    }
33}
34
35/// A system that automatically frees unused texture atlases when a font asset is removed.
36pub fn free_unused_font_atlases_system(
37    mut font_atlas_sets: ResMut<FontAtlasSet>,
38    mut font_events: MessageReader<AssetEvent<Font>>,
39) {
40    for event in font_events.read() {
41        if let AssetEvent::Removed { id } = event {
42            font_atlas_sets.retain(|key, _| key.0 != *id);
43        }
44    }
45}