From 13e8adb7e7b2ab31a30976581e78486e968758ef Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Tue, 6 Jan 2026 11:28:16 +0000 Subject: [PATCH 1/4] New example `system_fonts`. Displays a scrollable list of all available system fonts. Demonstrates loading and querying system fonts via cosmic-text. --- Cargo.toml | 11 ++++ examples/README.md | 1 + examples/ui/system_fonts.rs | 114 ++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 examples/ui/system_fonts.rs diff --git a/Cargo.toml b/Cargo.toml index c5632881e1dcc..71236cbd0a842 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5238,6 +5238,17 @@ description = "Demonstrates use of core scrollbar in Bevy UI" category = "UI (User Interface)" wasm = true +[[example]] +name = "system_fonts" +path = "examples/ui/system_fonts.rs" +doc-scrape-examples = true + +[package.metadata.example.system_fonts] +name = "system_fonts" +description = "Demonstrates how to use system fonts" +category = "UI (User Interface)" +wasm = true + [[example]] name = "feathers" path = "examples/ui/feathers.rs" diff --git a/examples/README.md b/examples/README.md index 594eaf16081fe..487832ecb3543 100644 --- a/examples/README.md +++ b/examples/README.md @@ -614,6 +614,7 @@ Example | Description [Viewport Node](../examples/ui/viewport_node.rs) | Demonstrates how to create a viewport node with picking support [Virtual Keyboard](../examples/ui/virtual_keyboard.rs) | Example demonstrating a virtual keyboard widget [Window Fallthrough](../examples/ui/window_fallthrough.rs) | Illustrates how to access `winit::window::Window`'s `hittest` functionality. +[system_fonts](../examples/ui/system_fonts.rs) | Demonstrates how to use system fonts ### Usage diff --git a/examples/ui/system_fonts.rs b/examples/ui/system_fonts.rs new file mode 100644 index 0000000000000..0c767b893bc59 --- /dev/null +++ b/examples/ui/system_fonts.rs @@ -0,0 +1,114 @@ +//! This example displays a scrollable list of all available system fonts. +//! Demonstrates loading and querying system fonts via cosmic-text. + +use bevy::{ + diagnostic::FrameTimeDiagnosticsPlugin, input::mouse::MouseScrollUnit, prelude::*, + text::CosmicFontSystem, +}; + +fn main() { + let mut app = App::new(); + app.add_plugins((DefaultPlugins, FrameTimeDiagnosticsPlugin::default())) + .add_systems(Startup, setup); + + app.world_mut() + .resource_mut::() + .db_mut() + .load_system_fonts(); + + app.run(); +} + +fn setup(mut commands: Commands, font_system: Res) { + commands.spawn(Camera2d); + + commands + .spawn(( + Node { + flex_direction: FlexDirection::Column, + width: percent(100), + height: percent(100), + align_items: AlignItems::Center, + row_gap: px(10.), + ..default() + }, + BackgroundColor(Color::srgb(0.1, 0.1, 0.1)), + )) + .with_children(|builder| { + builder.spawn(Text::new(format!( + "Total fonts available: {}", + font_system.db().len(), + ))); + + builder + .spawn(Node { + flex_direction: FlexDirection::Column, + row_gap: px(6), + overflow: Overflow::scroll_y(), + align_items: AlignItems::Stretch, + ..default() + }) + .with_children(|builder| { + let mut families: Vec<(String, String)> = Vec::new(); + for face in font_system.db().faces() { + for (name, lang) in &face.families { + families.push((name.to_string(), lang.to_string())); + } + } + families.sort_unstable(); + families.dedup(); + for (family, language) in families { + builder.spawn(( + Node { + display: Display::Grid, + grid_template_columns: vec![ + GridTrack::flex(1.), + GridTrack::flex(1.), + ], + padding: px(6).all(), + column_gap: px(50.), + ..default() + }, + BackgroundColor(Color::srgb(0.2, 0.2, 0.25)), + children![ + ( + Text::new(&family), + TextFont { + font: FontSource::Family(family.into()), + ..default() + }, + TextLayout::new_with_no_wrap() + ), + ( + Text::new(language), + TextLayout::new_with_no_wrap(), + Node { + justify_self: JustifySelf::End, + ..default() + } + ) + ], + )); + } + }) + .observe( + |on_scroll: On>, + mut query: Query<(&mut ScrollPosition, &ComputedNode)>| { + if let Ok((mut scroll_position, node)) = query.get_mut(on_scroll.entity) { + let dy = match on_scroll.unit { + MouseScrollUnit::Line => on_scroll.y * 20., + MouseScrollUnit::Pixel => on_scroll.y, + }; + + let range = (node.content_size.y - node.size.y).max(0.) + * node.inverse_scale_factor; + println!("dy = {dy}"); + println!("range = {range}"); + println!("y (before) = {}", scroll_position.y); + scroll_position.y = (scroll_position.y - dy).clamp(0., range); + println!("y (after) = {}", scroll_position.y); + } + }, + ); + }); +} From 865fb1953e5cbb3403a61047e65b6f06ca1d696c Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Tue, 6 Jan 2026 11:30:13 +0000 Subject: [PATCH 2/4] Removed debug code --- examples/ui/system_fonts.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/examples/ui/system_fonts.rs b/examples/ui/system_fonts.rs index 0c767b893bc59..1bac017f76b35 100644 --- a/examples/ui/system_fonts.rs +++ b/examples/ui/system_fonts.rs @@ -99,14 +99,9 @@ fn setup(mut commands: Commands, font_system: Res) { MouseScrollUnit::Line => on_scroll.y * 20., MouseScrollUnit::Pixel => on_scroll.y, }; - let range = (node.content_size.y - node.size.y).max(0.) * node.inverse_scale_factor; - println!("dy = {dy}"); - println!("range = {range}"); - println!("y (before) = {}", scroll_position.y); scroll_position.y = (scroll_position.y - dy).clamp(0., range); - println!("y (after) = {}", scroll_position.y); } }, ); From 5b91fac224bf8a861b7b5beccac01aa22b8edaab Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Tue, 6 Jan 2026 11:47:44 +0000 Subject: [PATCH 3/4] Changed header text --- examples/ui/system_fonts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ui/system_fonts.rs b/examples/ui/system_fonts.rs index 1bac017f76b35..1f0bf8160564c 100644 --- a/examples/ui/system_fonts.rs +++ b/examples/ui/system_fonts.rs @@ -36,7 +36,7 @@ fn setup(mut commands: Commands, font_system: Res) { )) .with_children(|builder| { builder.spawn(Text::new(format!( - "Total fonts available: {}", + "Total available fonts: {}", font_system.db().len(), ))); From 78a93ce58e4bbd87dc7608a54d45e45b59bd78e6 Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Tue, 6 Jan 2026 11:54:06 +0000 Subject: [PATCH 4/4] Display the name in the default font as well. --- examples/ui/system_fonts.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/ui/system_fonts.rs b/examples/ui/system_fonts.rs index 1f0bf8160564c..f8aea3847e4e3 100644 --- a/examples/ui/system_fonts.rs +++ b/examples/ui/system_fonts.rs @@ -64,6 +64,7 @@ fn setup(mut commands: Commands, font_system: Res) { grid_template_columns: vec![ GridTrack::flex(1.), GridTrack::flex(1.), + GridTrack::flex(1.), ], padding: px(6).all(), column_gap: px(50.), @@ -74,11 +75,12 @@ fn setup(mut commands: Commands, font_system: Res) { ( Text::new(&family), TextFont { - font: FontSource::Family(family.into()), + font: FontSource::Family(family.as_str().into()), ..default() }, TextLayout::new_with_no_wrap() ), + (Text::new(family), TextLayout::new_with_no_wrap()), ( Text::new(language), TextLayout::new_with_no_wrap(),