mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
Make CosmicFontSystem
and SwashCache
pub resources. (#15479)
# Objective In nannou, we'd like to be able to access the [outline commands](https://docs.rs/cosmic-text/latest/cosmic_text/struct.SwashCache.html#method.get_outline_commands) from swash, while still benefit from Bevy's management of font assets. ## Solution Make `CosmicFontSystem` and `SwashCache` pub resources. ## Testing Ran some examples.
This commit is contained in:
parent
9b4d2de215
commit
df23b937cc
5 changed files with 73 additions and 36 deletions
|
@ -109,7 +109,9 @@ impl Plugin for TextPlugin {
|
|||
.register_type::<TextBounds>()
|
||||
.init_asset_loader::<FontLoader>()
|
||||
.init_resource::<FontAtlasSets>()
|
||||
.insert_resource(TextPipeline::default())
|
||||
.init_resource::<TextPipeline>()
|
||||
.init_resource::<CosmicFontSystem>()
|
||||
.init_resource::<SwashCache>()
|
||||
.add_systems(
|
||||
PostUpdate,
|
||||
(
|
||||
|
|
|
@ -20,8 +20,13 @@ use crate::{
|
|||
PositionedGlyph, TextBounds, TextSection, YAxisOrientation,
|
||||
};
|
||||
|
||||
/// A wrapper around a [`cosmic_text::FontSystem`]
|
||||
struct CosmicFontSystem(cosmic_text::FontSystem);
|
||||
/// A wrapper resource around a [`cosmic_text::FontSystem`]
|
||||
///
|
||||
/// The font system is used to retrieve fonts and their information, including glyph outlines.
|
||||
///
|
||||
/// This resource is updated by the [`TextPipeline`] resource.
|
||||
#[derive(Resource)]
|
||||
pub struct CosmicFontSystem(pub cosmic_text::FontSystem);
|
||||
|
||||
impl Default for CosmicFontSystem {
|
||||
fn default() -> Self {
|
||||
|
@ -32,8 +37,13 @@ impl Default for CosmicFontSystem {
|
|||
}
|
||||
}
|
||||
|
||||
/// A wrapper around a [`cosmic_text::SwashCache`]
|
||||
struct SwashCache(cosmic_text::SwashCache);
|
||||
/// A wrapper resource around a [`cosmic_text::SwashCache`]
|
||||
///
|
||||
/// The swash cache rasterizer is used to rasterize glyphs
|
||||
///
|
||||
/// This resource is updated by the [`TextPipeline`] resource.
|
||||
#[derive(Resource)]
|
||||
pub struct SwashCache(pub cosmic_text::SwashCache);
|
||||
|
||||
impl Default for SwashCache {
|
||||
fn default() -> Self {
|
||||
|
@ -48,14 +58,6 @@ impl Default for SwashCache {
|
|||
pub struct TextPipeline {
|
||||
/// Identifies a font [`ID`](cosmic_text::fontdb::ID) by its [`Font`] [`Asset`](bevy_asset::Asset).
|
||||
map_handle_to_font_id: HashMap<AssetId<Font>, (cosmic_text::fontdb::ID, String)>,
|
||||
/// The font system is used to retrieve fonts and their information, including glyph outlines.
|
||||
///
|
||||
/// See [`cosmic_text::FontSystem`] for more information.
|
||||
font_system: CosmicFontSystem,
|
||||
/// The swash cache rasterizer is used to rasterize glyphs
|
||||
///
|
||||
/// See [`cosmic_text::SwashCache`] for more information.
|
||||
swash_cache: SwashCache,
|
||||
/// Buffered vec for collecting spans.
|
||||
///
|
||||
/// See [this dark magic](https://users.rust-lang.org/t/how-to-cache-a-vectors-capacity/94478/10).
|
||||
|
@ -76,8 +78,9 @@ impl TextPipeline {
|
|||
scale_factor: f64,
|
||||
buffer: &mut CosmicBuffer,
|
||||
alignment: JustifyText,
|
||||
font_system: &mut CosmicFontSystem,
|
||||
) -> Result<(), TextError> {
|
||||
let font_system = &mut self.font_system.0;
|
||||
let font_system = &mut font_system.0;
|
||||
|
||||
// return early if the fonts are not loaded yet
|
||||
let mut font_size = 0.;
|
||||
|
@ -188,6 +191,8 @@ impl TextPipeline {
|
|||
textures: &mut Assets<Image>,
|
||||
y_axis_orientation: YAxisOrientation,
|
||||
buffer: &mut CosmicBuffer,
|
||||
font_system: &mut CosmicFontSystem,
|
||||
swash_cache: &mut SwashCache,
|
||||
) -> Result<(), TextError> {
|
||||
layout_info.glyphs.clear();
|
||||
layout_info.size = Default::default();
|
||||
|
@ -204,11 +209,10 @@ impl TextPipeline {
|
|||
scale_factor,
|
||||
buffer,
|
||||
text_alignment,
|
||||
font_system,
|
||||
)?;
|
||||
|
||||
let box_size = buffer_dimensions(buffer);
|
||||
let font_system = &mut self.font_system.0;
|
||||
let swash_cache = &mut self.swash_cache.0;
|
||||
|
||||
buffer
|
||||
.layout_runs()
|
||||
|
@ -250,8 +254,8 @@ impl TextPipeline {
|
|||
font_atlas_set.add_glyph_to_atlas(
|
||||
texture_atlases,
|
||||
textures,
|
||||
font_system,
|
||||
swash_cache,
|
||||
&mut font_system.0,
|
||||
&mut swash_cache.0,
|
||||
layout_glyph,
|
||||
font_smoothing,
|
||||
)
|
||||
|
@ -300,6 +304,7 @@ impl TextPipeline {
|
|||
linebreak_behavior: BreakLineOn,
|
||||
buffer: &mut CosmicBuffer,
|
||||
text_alignment: JustifyText,
|
||||
font_system: &mut CosmicFontSystem,
|
||||
) -> Result<TextMeasureInfo, TextError> {
|
||||
const MIN_WIDTH_CONTENT_BOUNDS: TextBounds = TextBounds::new_horizontal(0.0);
|
||||
|
||||
|
@ -311,12 +316,13 @@ impl TextPipeline {
|
|||
scale_factor,
|
||||
buffer,
|
||||
text_alignment,
|
||||
font_system,
|
||||
)?;
|
||||
|
||||
let min_width_content_size = buffer_dimensions(buffer);
|
||||
|
||||
let max_width_content_size = {
|
||||
let font_system = &mut self.font_system.0;
|
||||
let font_system = &mut font_system.0;
|
||||
buffer.set_size(font_system, None, None);
|
||||
buffer_dimensions(buffer)
|
||||
};
|
||||
|
@ -328,11 +334,12 @@ impl TextPipeline {
|
|||
})
|
||||
}
|
||||
|
||||
/// Get a mutable reference to the [`cosmic_text::FontSystem`].
|
||||
///
|
||||
/// Used internally.
|
||||
pub fn font_system_mut(&mut self) -> &mut cosmic_text::FontSystem {
|
||||
&mut self.font_system.0
|
||||
/// Returns the [`cosmic_text::fontdb::ID`] for a given [`Font`] asset.
|
||||
pub fn get_font_id(&self, asset_id: AssetId<Font>) -> Option<cosmic_text::fontdb::ID> {
|
||||
self.map_handle_to_font_id
|
||||
.get(&asset_id)
|
||||
.cloned()
|
||||
.map(|(id, _)| id)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -442,11 +449,11 @@ fn buffer_dimensions(buffer: &Buffer) -> Vec2 {
|
|||
}
|
||||
|
||||
/// Discards stale data cached in `FontSystem`.
|
||||
pub(crate) fn trim_cosmic_cache(mut pipeline: ResMut<TextPipeline>) {
|
||||
pub(crate) fn trim_cosmic_cache(mut font_system: ResMut<CosmicFontSystem>) {
|
||||
// A trim age of 2 was found to reduce frame time variance vs age of 1 when tested with dynamic text.
|
||||
// See https://github.com/bevyengine/bevy/pull/15037
|
||||
//
|
||||
// We assume only text updated frequently benefits from the shape cache (e.g. animated text, or
|
||||
// text that is dynamically measured for UI).
|
||||
pipeline.font_system_mut().shape_run_cache.trim(2);
|
||||
font_system.0.shape_run_cache.trim(2);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::pipeline::CosmicFontSystem;
|
||||
use crate::{
|
||||
BreakLineOn, CosmicBuffer, Font, FontAtlasSets, PositionedGlyph, Text, TextBounds, TextError,
|
||||
TextLayoutInfo, TextPipeline, YAxisOrientation,
|
||||
BreakLineOn, CosmicBuffer, Font, FontAtlasSets, PositionedGlyph, SwashCache, Text, TextBounds,
|
||||
TextError, TextLayoutInfo, TextPipeline, YAxisOrientation,
|
||||
};
|
||||
use bevy_asset::Assets;
|
||||
use bevy_color::LinearRgba;
|
||||
|
@ -158,6 +159,8 @@ pub fn update_text2d_layout(
|
|||
&mut TextLayoutInfo,
|
||||
&mut CosmicBuffer,
|
||||
)>,
|
||||
mut font_system: ResMut<CosmicFontSystem>,
|
||||
mut swash_cache: ResMut<SwashCache>,
|
||||
) {
|
||||
// We need to consume the entire iterator, hence `last`
|
||||
let factor_changed = scale_factor_changed.read().last().is_some();
|
||||
|
@ -198,6 +201,8 @@ pub fn update_text2d_layout(
|
|||
&mut textures,
|
||||
YAxisOrientation::BottomToTop,
|
||||
buffer.as_mut(),
|
||||
&mut font_system,
|
||||
&mut swash_cache,
|
||||
) {
|
||||
Err(TextError::NoSuchFont) => {
|
||||
// There was an error processing the text layout, let's add this entity to the
|
||||
|
@ -274,7 +279,9 @@ mod tests {
|
|||
.init_resource::<Assets<TextureAtlasLayout>>()
|
||||
.init_resource::<FontAtlasSets>()
|
||||
.init_resource::<Events<WindowScaleFactorChanged>>()
|
||||
.insert_resource(TextPipeline::default())
|
||||
.init_resource::<TextPipeline>()
|
||||
.init_resource::<CosmicFontSystem>()
|
||||
.init_resource::<SwashCache>()
|
||||
.add_systems(
|
||||
Update,
|
||||
(
|
||||
|
|
|
@ -22,7 +22,9 @@ use thiserror::Error;
|
|||
use ui_surface::UiSurface;
|
||||
|
||||
#[cfg(feature = "bevy_text")]
|
||||
use bevy_text::{CosmicBuffer, TextPipeline};
|
||||
use bevy_text::CosmicBuffer;
|
||||
#[cfg(feature = "bevy_text")]
|
||||
use bevy_text::CosmicFontSystem;
|
||||
|
||||
mod convert;
|
||||
pub mod debug;
|
||||
|
@ -124,7 +126,7 @@ pub fn ui_layout_system(
|
|||
Option<&ScrollPosition>,
|
||||
)>,
|
||||
#[cfg(feature = "bevy_text")] mut buffer_query: Query<&mut CosmicBuffer>,
|
||||
#[cfg(feature = "bevy_text")] mut text_pipeline: ResMut<TextPipeline>,
|
||||
#[cfg(feature = "bevy_text")] mut font_system: ResMut<CosmicFontSystem>,
|
||||
) {
|
||||
let UiLayoutSystemBuffers {
|
||||
interned_root_nodes,
|
||||
|
@ -250,8 +252,6 @@ pub fn ui_layout_system(
|
|||
|
||||
#[cfg(feature = "bevy_text")]
|
||||
let text_buffers = &mut buffer_query;
|
||||
#[cfg(feature = "bevy_text")]
|
||||
let font_system = text_pipeline.font_system_mut();
|
||||
// clean up removed nodes after syncing children to avoid potential panic (invalid SlotMap key used)
|
||||
ui_surface.remove_entities(removed_components.removed_nodes.read());
|
||||
|
||||
|
@ -271,7 +271,7 @@ pub fn ui_layout_system(
|
|||
#[cfg(feature = "bevy_text")]
|
||||
text_buffers,
|
||||
#[cfg(feature = "bevy_text")]
|
||||
font_system,
|
||||
&mut font_system.0,
|
||||
);
|
||||
|
||||
for root in &camera.root_nodes {
|
||||
|
@ -523,6 +523,10 @@ mod tests {
|
|||
world.init_resource::<ManualTextureViews>();
|
||||
#[cfg(feature = "bevy_text")]
|
||||
world.init_resource::<bevy_text::TextPipeline>();
|
||||
#[cfg(feature = "bevy_text")]
|
||||
world.init_resource::<bevy_text::CosmicFontSystem>();
|
||||
#[cfg(feature = "bevy_text")]
|
||||
world.init_resource::<bevy_text::SwashCache>();
|
||||
|
||||
// spawn a dummy primary window and camera
|
||||
world.spawn((
|
||||
|
@ -1160,6 +1164,10 @@ mod tests {
|
|||
world.init_resource::<ManualTextureViews>();
|
||||
#[cfg(feature = "bevy_text")]
|
||||
world.init_resource::<bevy_text::TextPipeline>();
|
||||
#[cfg(feature = "bevy_text")]
|
||||
world.init_resource::<bevy_text::CosmicFontSystem>();
|
||||
#[cfg(feature = "bevy_text")]
|
||||
world.init_resource::<bevy_text::SwashCache>();
|
||||
|
||||
// spawn a dummy primary window and camera
|
||||
world.spawn((
|
||||
|
|
|
@ -16,8 +16,9 @@ use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
|||
use bevy_render::{camera::Camera, texture::Image};
|
||||
use bevy_sprite::TextureAtlasLayout;
|
||||
use bevy_text::{
|
||||
scale_value, BreakLineOn, CosmicBuffer, Font, FontAtlasSets, JustifyText, Text, TextBounds,
|
||||
TextError, TextLayoutInfo, TextMeasureInfo, TextPipeline, YAxisOrientation,
|
||||
scale_value, BreakLineOn, CosmicBuffer, CosmicFontSystem, Font, FontAtlasSets, JustifyText,
|
||||
SwashCache, Text, TextBounds, TextError, TextLayoutInfo, TextMeasureInfo, TextPipeline,
|
||||
YAxisOrientation,
|
||||
};
|
||||
use bevy_utils::{tracing::error, Entry};
|
||||
use taffy::style::AvailableSpace;
|
||||
|
@ -112,6 +113,7 @@ fn create_text_measure(
|
|||
mut text_flags: Mut<TextFlags>,
|
||||
buffer: &mut CosmicBuffer,
|
||||
text_alignment: JustifyText,
|
||||
font_system: &mut CosmicFontSystem,
|
||||
) {
|
||||
match text_pipeline.create_text_measure(
|
||||
entity,
|
||||
|
@ -121,6 +123,7 @@ fn create_text_measure(
|
|||
text.linebreak_behavior,
|
||||
buffer,
|
||||
text_alignment,
|
||||
font_system,
|
||||
) {
|
||||
Ok(measure) => {
|
||||
if text.linebreak_behavior == BreakLineOn::NoWrap {
|
||||
|
@ -173,6 +176,7 @@ pub fn measure_text_system(
|
|||
With<Node>,
|
||||
>,
|
||||
mut text_pipeline: ResMut<TextPipeline>,
|
||||
mut font_system: ResMut<CosmicFontSystem>,
|
||||
) {
|
||||
scale_factors_buffer.clear();
|
||||
|
||||
|
@ -208,6 +212,7 @@ pub fn measure_text_system(
|
|||
text_flags,
|
||||
buffer.as_mut(),
|
||||
text_alignment,
|
||||
&mut font_system,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -229,6 +234,8 @@ fn queue_text(
|
|||
mut text_flags: Mut<TextFlags>,
|
||||
text_layout_info: Mut<TextLayoutInfo>,
|
||||
buffer: &mut CosmicBuffer,
|
||||
font_system: &mut CosmicFontSystem,
|
||||
swash_cache: &mut SwashCache,
|
||||
) {
|
||||
// Skip the text node if it is waiting for a new measure func
|
||||
if !text_flags.needs_new_measure_func {
|
||||
|
@ -258,6 +265,8 @@ fn queue_text(
|
|||
textures,
|
||||
YAxisOrientation::TopToBottom,
|
||||
buffer,
|
||||
font_system,
|
||||
swash_cache,
|
||||
) {
|
||||
Err(TextError::NoSuchFont) => {
|
||||
// There was an error processing the text layout, try again next frame
|
||||
|
@ -305,6 +314,8 @@ pub fn text_system(
|
|||
Option<&TargetCamera>,
|
||||
&mut CosmicBuffer,
|
||||
)>,
|
||||
mut font_system: ResMut<CosmicFontSystem>,
|
||||
mut swash_cache: ResMut<SwashCache>,
|
||||
) {
|
||||
scale_factors_buffer.clear();
|
||||
|
||||
|
@ -343,6 +354,8 @@ pub fn text_system(
|
|||
text_flags,
|
||||
text_layout_info,
|
||||
buffer.as_mut(),
|
||||
&mut font_system,
|
||||
&mut swash_cache,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue