Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0639ce6
Added new FontSize type
ickshonpe Jan 18, 2026
0113bd7
Added `Rem` unit support, for the moment resolved using the value of …
ickshonpe Jan 20, 2026
d6d5408
Updated text example
ickshonpe Jan 20, 2026
1ef6b32
Added doc comment on how `Viewport` values are resolved for `Text2d`
ickshonpe Jan 20, 2026
ec4f8f3
improved font size doc comments
ickshonpe Jan 20, 2026
a9581df
Fixed `fps_overlay` so it compiles, layout still incorrect.
ickshonpe Jan 20, 2026
a2318e4
Added FontSize to bevy_text's prelude
ickshonpe Jan 20, 2026
f67bfcc
Updatged examples to use FontSize
ickshonpe Jan 20, 2026
5ca48a6
Updated feathers
ickshonpe Jan 20, 2026
d83ec07
Updated release content
ickshonpe Jan 20, 2026
dafc52a
Migrate bevy_feathers
ickshonpe Jan 20, 2026
a3ae75a
updated migration guide.
ickshonpe Jan 20, 2026
d900aaf
Updated release content
ickshonpe Jan 21, 2026
526fd5d
Send `create_text_measure` the logical viewport size, not physical.
ickshonpe Jan 21, 2026
a2da2cc
removed redundant as_vec2
ickshonpe Jan 21, 2026
e8981c6
Merge branch 'main' into font-size
ickshonpe Jan 21, 2026
631dd3c
Fixed release content formatting
ickshonpe Jan 21, 2026
f61ca72
Fixed error in doc comment
ickshonpe Jan 21, 2026
7ab2a5f
Fixed error in fps_overlay example
ickshonpe Jan 21, 2026
6a562db
Fixed desktop_request_redraw module
ickshonpe Jan 21, 2026
1c7c956
Added missing `FontSize` import to doc test.
ickshonpe Jan 21, 2026
967322f
init `RemSize` in text2d test setup
ickshonpe Jan 21, 2026
de63313
Fixed doc test
ickshonpe Jan 21, 2026
717563d
Merge branch 'main' into font-size
ickshonpe Jan 21, 2026
5ac19f6
Merge branch 'main' into font-size
ickshonpe Jan 22, 2026
a16cd81
Merge branch 'main' into font-size
ickshonpe Jan 23, 2026
b3ac4bb
Merge branch 'main' into font-size
ickshonpe Jan 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions crates/bevy_dev_tools/src/fps_overlay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ use bevy_ecs::{
use bevy_picking::Pickable;
use bevy_reflect::Reflect;
use bevy_render::storage::ShaderBuffer;
use bevy_text::{TextColor, TextFont, TextSpan};
use bevy_text::{RemSize, TextColor, TextFont, TextSpan};
use bevy_time::common_conditions::on_timer;
use bevy_ui::{
widget::{Text, TextUiWriter},
FlexDirection, GlobalZIndex, Node, PositionType, Val,
ComputedUiRenderTargetInfo, FlexDirection, GlobalZIndex, Node, PositionType, Val,
};
#[cfg(not(all(target_arch = "wasm32", not(feature = "webgpu"))))]
use bevy_ui_render::prelude::MaterialNode;
Expand Down Expand Up @@ -220,7 +220,8 @@ fn setup(
}
#[cfg(not(all(target_arch = "wasm32", not(feature = "webgpu"))))]
{
let font_size = overlay_config.text_config.font_size;
// Todo: Needs a better design that works with responsive sizing.
let font_size = 20.;
p.spawn((
Node {
width: Val::Px(font_size * FRAME_TIME_GRAPH_WIDTH_SCALE),
Expand Down Expand Up @@ -281,18 +282,25 @@ fn customize_overlay(

fn toggle_display(
overlay_config: Res<FpsOverlayConfig>,
mut text_node: Single<&mut Node, (With<FpsText>, Without<FrameTimeGraph>)>,
mut text_node: Single<
(&mut Node, &ComputedUiRenderTargetInfo),
(With<FpsText>, Without<FrameTimeGraph>),
>,
mut graph_node: Single<&mut Node, (With<FrameTimeGraph>, Without<FpsText>)>,
rem_size: Res<RemSize>,
) {
if overlay_config.enabled {
text_node.display = bevy_ui::Display::DEFAULT;
text_node.0.display = bevy_ui::Display::DEFAULT;
} else {
text_node.display = bevy_ui::Display::None;
text_node.0.display = bevy_ui::Display::None;
}

if overlay_config.frame_time_graph_config.enabled {
// Scale the frame time graph based on the font size of the overlay
let font_size = overlay_config.text_config.font_size;
let font_size = overlay_config
.text_config
.font_size
.eval(text_node.1.logical_size(), rem_size.0);
graph_node.width = Val::Px(font_size * FRAME_TIME_GRAPH_WIDTH_SCALE);
graph_node.height = Val::Px(font_size * FRAME_TIME_GRAPH_HEIGHT_SCALE);

Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_feathers/src/controls/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use bevy_ecs::{
use bevy_input_focus::tab_navigation::TabIndex;
use bevy_picking::{hover::Hovered, PickingSystems};
use bevy_reflect::{prelude::ReflectDefault, Reflect};
use bevy_text::FontSize;
use bevy_ui::{AlignItems, InteractionDisabled, JustifyContent, Node, Pressed, UiRect, Val};
use bevy_ui_widgets::Button;

Expand Down Expand Up @@ -86,7 +87,7 @@ pub fn button<C: SpawnableList<ChildOf> + Send + Sync + 'static, B: Bundle>(
ThemeFontColor(tokens::BUTTON_TEXT),
InheritableFont {
font: HandleOrPath::Path(fonts::REGULAR.to_owned()),
font_size: 14.0,
font_size: FontSize::Px(14.0),
},
overrides,
Children::spawn(children),
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_feathers/src/controls/checkbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use bevy_input_focus::tab_navigation::TabIndex;
use bevy_math::Rot2;
use bevy_picking::{hover::Hovered, PickingSystems};
use bevy_reflect::{prelude::ReflectDefault, Reflect};
use bevy_text::FontSize;
use bevy_ui::{
AlignItems, BorderRadius, Checked, Display, FlexDirection, InteractionDisabled, JustifyContent,
Node, PositionType, UiRect, UiTransform, Val,
Expand Down Expand Up @@ -79,7 +80,7 @@ pub fn checkbox<C: SpawnableList<ChildOf> + Send + Sync + 'static, B: Bundle>(
ThemeFontColor(tokens::CHECKBOX_TEXT),
InheritableFont {
font: HandleOrPath::Path(fonts::REGULAR.to_owned()),
font_size: 14.0,
font_size: FontSize::Px(14.0),
},
overrides,
Children::spawn((
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_feathers/src/controls/radio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use bevy_ecs::{
use bevy_input_focus::tab_navigation::TabIndex;
use bevy_picking::{hover::Hovered, PickingSystems};
use bevy_reflect::{prelude::ReflectDefault, Reflect};
use bevy_text::FontSize;
use bevy_ui::{
AlignItems, BorderRadius, Checked, Display, FlexDirection, InteractionDisabled, JustifyContent,
Node, UiRect, Val,
Expand Down Expand Up @@ -73,7 +74,7 @@ pub fn radio<C: SpawnableList<ChildOf> + Send + Sync + 'static, B: Bundle>(
ThemeFontColor(tokens::RADIO_TEXT),
InheritableFont {
font: HandleOrPath::Path(fonts::REGULAR.to_owned()),
font_size: 14.0,
font_size: FontSize::Px(14.0),
},
overrides,
Children::spawn((
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_feathers/src/controls/slider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use bevy_ecs::{
use bevy_input_focus::tab_navigation::TabIndex;
use bevy_picking::PickingSystems;
use bevy_reflect::{prelude::ReflectDefault, Reflect};
use bevy_text::FontSize;
use bevy_ui::{
widget::Text, AlignItems, BackgroundGradient, ColorStop, Display, FlexDirection, Gradient,
InteractionDisabled, InterpolationColorSpace, JustifyContent, LinearGradient, Node,
Expand Down Expand Up @@ -121,7 +122,7 @@ pub fn slider<B: Bundle>(props: SliderProps, overrides: B) -> impl Bundle {
ThemeFontColor(tokens::SLIDER_TEXT),
InheritableFont {
font: HandleOrPath::Path(fonts::MONO.to_owned()),
font_size: 12.0,
font_size: FontSize::Px(12.0),
},
children![(Text::new("10.0"), ThemedText, SliderValueText,)],
)],
Expand Down
8 changes: 4 additions & 4 deletions crates/bevy_feathers/src/font_styles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use bevy_ecs::{
system::{Commands, Query, Res},
};
use bevy_reflect::{prelude::ReflectDefault, Reflect};
use bevy_text::{Font, TextFont};
use bevy_text::{Font, FontSize, TextFont};

use crate::{handle_or_path::HandleOrPath, theme::ThemedText};

Expand All @@ -22,23 +22,23 @@ pub struct InheritableFont {
/// The font handle or path.
pub font: HandleOrPath<Font>,
/// The desired font size.
pub font_size: f32,
pub font_size: FontSize,
}

impl InheritableFont {
/// Create a new `InheritableFont` from a handle.
pub fn from_handle(handle: Handle<Font>) -> Self {
Self {
font: HandleOrPath::Handle(handle),
font_size: 16.0,
font_size: FontSize::Px(16.0),
}
}

/// Create a new `InheritableFont` from a path.
pub fn from_path(path: &str) -> Self {
Self {
font: HandleOrPath::Path(path.to_string()),
font_size: 16.0,
font_size: FontSize::Px(16.0),
}
}
}
Expand Down
20 changes: 17 additions & 3 deletions crates/bevy_sprite/src/text2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use bevy_camera::Camera;
use bevy_color::Color;
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::entity::EntityHashSet;
use bevy_ecs::query::With;
use bevy_ecs::system::Single;
use bevy_ecs::{
change_detection::{DetectChanges, Ref},
component::Component,
Expand All @@ -21,10 +23,11 @@ use bevy_math::{FloatOrd, Vec2, Vec3};
use bevy_reflect::{prelude::ReflectDefault, Reflect};
use bevy_text::{
ComputedTextBlock, CosmicFontSystem, Font, FontAtlasSet, FontHinting, LineBreak, LineHeight,
SwashCache, TextBounds, TextColor, TextError, TextFont, TextLayout, TextLayoutInfo,
RemSize, SwashCache, TextBounds, TextColor, TextError, TextFont, TextLayout, TextLayoutInfo,
TextPipeline, TextReader, TextRoot, TextSpanAccess, TextWriter,
};
use bevy_transform::components::Transform;
use bevy_window::{PrimaryWindow, Window};
use core::any::TypeId;

/// The top-level 2D text component.
Expand All @@ -45,7 +48,7 @@ use core::any::TypeId;
/// # use bevy_color::Color;
/// # use bevy_color::palettes::basic::BLUE;
/// # use bevy_ecs::world::World;
/// # use bevy_text::{Font, Justify, TextLayout, TextFont, TextColor, TextSpan};
/// # use bevy_text::{Font, FontSize, Justify, TextLayout, TextFont, TextColor, TextSpan};
/// # use bevy_sprite::Text2d;
/// #
/// # let font_handle: Handle<Font> = Default::default();
Expand All @@ -59,7 +62,7 @@ use core::any::TypeId;
/// Text2d::new("hello world!"),
/// TextFont {
/// font: font_handle.clone().into(),
/// font_size: 60.0,
/// font_size: FontSize::Px(60.0),
/// ..Default::default()
/// },
/// TextColor(BLUE.into()),
Expand All @@ -77,6 +80,8 @@ use core::any::TypeId;
/// parent.spawn((TextSpan::new("!"), TextColor(BLUE.into())));
/// });
/// ```
///
/// Viewport-based `FontSize` variants for `Text2d` are resolved based on the primary window’s logical size.
#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect)]
#[reflect(Component, Default, Debug, Clone)]
#[require(
Expand Down Expand Up @@ -182,7 +187,13 @@ pub fn update_text2d_layout(
mut text_reader: Text2dReader,
mut font_system: ResMut<CosmicFontSystem>,
mut swash_cache: ResMut<SwashCache>,
rem_size: Res<RemSize>,
primary_window: Option<Single<&Window, With<PrimaryWindow>>>,
) {
let logical_viewport_size = primary_window
.map(|window| window.resolution.size())
.unwrap_or(Vec2::splat(1000.));

target_scale_factors.clear();
target_scale_factors.extend(
camera_query
Expand Down Expand Up @@ -252,6 +263,8 @@ pub fn update_text2d_layout(
&mut computed,
&mut font_system,
*hinting,
logical_viewport_size,
rem_size.0,
) {
Err(TextError::NoSuchFont | TextError::DegenerateScaleFactor) => {
// There was an error processing the text layout.
Expand Down Expand Up @@ -375,6 +388,7 @@ mod tests {
.init_resource::<CosmicFontSystem>()
.init_resource::<SwashCache>()
.init_resource::<TextIterScratch>()
.init_resource::<RemSize>()
.add_systems(
Update,
(
Expand Down
7 changes: 4 additions & 3 deletions crates/bevy_text/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ pub use text_access::*;
pub mod prelude {
#[doc(hidden)]
pub use crate::{
Font, FontHinting, FontSmoothing, FontSource, FontStyle, FontWeight, FontWidth, Justify,
LineBreak, Strikethrough, StrikethroughColor, TextColor, TextError, TextFont, TextLayout,
TextSpan, Underline, UnderlineColor,
Font, FontHinting, FontSize, FontSmoothing, FontSource, FontStyle, FontWeight, FontWidth,
Justify, LineBreak, Strikethrough, StrikethroughColor, TextColor, TextError, TextFont,
TextLayout, TextSpan, Underline, UnderlineColor,
};
}

Expand Down Expand Up @@ -94,6 +94,7 @@ impl Plugin for TextPlugin {
.init_resource::<CosmicFontSystem>()
.init_resource::<SwashCache>()
.init_resource::<TextIterScratch>()
.init_resource::<RemSize>()
.add_systems(
PostUpdate,
load_font_assets_into_fontdb_system.after(AssetEventSystems),
Expand Down
26 changes: 22 additions & 4 deletions crates/bevy_text/src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ impl TextPipeline {
computed: &mut ComputedTextBlock,
font_system: &mut CosmicFontSystem,
hinting: FontHinting,
logical_viewport_size: Vec2,
base_rem_size: f32,
) -> Result<(), TextError> {
computed.entities.clear();
computed.needs_rerender = false;
Expand Down Expand Up @@ -210,16 +212,27 @@ impl TextPipeline {
FontSource::Monospace => Family::Monospace,
};

let font_size = text_font
.font_size
.eval(logical_viewport_size, base_rem_size);

// Save spans that aren't zero-sized.
if text_font.font_size <= 0.0 {
if font_size <= 0.0 {
once!(warn!(
"Text span {entity} has a font size <= 0.0. Nothing will be displayed.",
));

continue;
}

let attrs = get_attrs(span_index, text_font, line_height, family, scale_factor);
let attrs = get_attrs(
span_index,
text_font,
font_size,
line_height,
family,
scale_factor,
);

sections.push((span, attrs));
}
Expand Down Expand Up @@ -281,6 +294,8 @@ impl TextPipeline {
computed: &mut ComputedTextBlock,
font_system: &mut CosmicFontSystem,
hinting: FontHinting,
logical_viewport_size: Vec2,
base_rem_size: f32,
) -> Result<TextMeasureInfo, TextError> {
const MIN_WIDTH_CONTENT_BOUNDS: TextBounds = TextBounds::new_horizontal(0.0);

Expand All @@ -298,6 +313,8 @@ impl TextPipeline {
computed,
font_system,
hinting,
logical_viewport_size,
base_rem_size,
)?;

let buffer = &mut computed.buffer;
Expand Down Expand Up @@ -579,6 +596,7 @@ impl TextMeasureInfo {
fn get_attrs<'a>(
span_index: usize,
text_font: &TextFont,
font_size: f32,
line_height: LineHeight,
family: Family<'a>,
scale_factor: f64,
Expand All @@ -591,8 +609,8 @@ fn get_attrs<'a>(
.weight(text_font.weight.into())
.metrics(
Metrics {
font_size: text_font.font_size,
line_height: line_height.eval(text_font.font_size),
font_size,
line_height: line_height.eval(font_size),
}
.scale(scale_factor as f32),
)
Expand Down
Loading