mirror of
https://github.com/bevyengine/bevy
synced 2025-01-04 09:18:54 +00:00
0981789ec7
# Objective Fixes #6272 ## Solution Revert to old way of positioning text for Text2D rendered text. Co-authored-by: Michel van der Hulst <hulstmichel@gmail.com>
114 lines
3.6 KiB
Rust
114 lines
3.6 KiB
Rust
use ab_glyph::{PxScale, ScaleFont};
|
|
use bevy_asset::{Assets, Handle, HandleId};
|
|
use bevy_ecs::component::Component;
|
|
use bevy_ecs::system::Resource;
|
|
use bevy_math::Vec2;
|
|
use bevy_render::texture::Image;
|
|
use bevy_sprite::TextureAtlas;
|
|
use bevy_utils::HashMap;
|
|
|
|
use glyph_brush_layout::{FontId, SectionText};
|
|
|
|
use crate::{
|
|
error::TextError, glyph_brush::GlyphBrush, scale_value, Font, FontAtlasSet, PositionedGlyph,
|
|
TextAlignment, TextSection, TextSettings, YAxisOrientation,
|
|
};
|
|
|
|
#[derive(Default, Resource)]
|
|
pub struct TextPipeline {
|
|
brush: GlyphBrush,
|
|
map_font_id: HashMap<HandleId, FontId>,
|
|
}
|
|
|
|
/// Render information for a corresponding [`Text`](crate::Text) component.
|
|
///
|
|
/// Contains scaled glyphs and their size. Generated via [`TextPipeline::queue_text`].
|
|
#[derive(Component, Clone, Default, Debug)]
|
|
pub struct TextLayoutInfo {
|
|
pub glyphs: Vec<PositionedGlyph>,
|
|
pub size: Vec2,
|
|
}
|
|
|
|
impl TextPipeline {
|
|
pub fn get_or_insert_font_id(&mut self, handle: &Handle<Font>, font: &Font) -> FontId {
|
|
let brush = &mut self.brush;
|
|
*self
|
|
.map_font_id
|
|
.entry(handle.id())
|
|
.or_insert_with(|| brush.add_font(handle.clone(), font.font.clone()))
|
|
}
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
pub fn queue_text(
|
|
&mut self,
|
|
fonts: &Assets<Font>,
|
|
sections: &[TextSection],
|
|
scale_factor: f64,
|
|
text_alignment: TextAlignment,
|
|
bounds: Vec2,
|
|
font_atlas_set_storage: &mut Assets<FontAtlasSet>,
|
|
texture_atlases: &mut Assets<TextureAtlas>,
|
|
textures: &mut Assets<Image>,
|
|
text_settings: &TextSettings,
|
|
y_axis_orientation: YAxisOrientation,
|
|
) -> Result<TextLayoutInfo, TextError> {
|
|
let mut scaled_fonts = Vec::new();
|
|
let sections = sections
|
|
.iter()
|
|
.map(|section| {
|
|
let font = fonts
|
|
.get(§ion.style.font)
|
|
.ok_or(TextError::NoSuchFont)?;
|
|
let font_id = self.get_or_insert_font_id(§ion.style.font, font);
|
|
let font_size = scale_value(section.style.font_size, scale_factor);
|
|
|
|
scaled_fonts.push(ab_glyph::Font::as_scaled(&font.font, font_size));
|
|
|
|
let section = SectionText {
|
|
font_id,
|
|
scale: PxScale::from(font_size),
|
|
text: §ion.value,
|
|
};
|
|
|
|
Ok(section)
|
|
})
|
|
.collect::<Result<Vec<_>, _>>()?;
|
|
|
|
let section_glyphs = self
|
|
.brush
|
|
.compute_glyphs(§ions, bounds, text_alignment)?;
|
|
|
|
if section_glyphs.is_empty() {
|
|
return Ok(TextLayoutInfo::default());
|
|
}
|
|
|
|
let mut min_x: f32 = std::f32::MAX;
|
|
let mut min_y: f32 = std::f32::MAX;
|
|
let mut max_x: f32 = std::f32::MIN;
|
|
let mut max_y: f32 = std::f32::MIN;
|
|
|
|
for sg in §ion_glyphs {
|
|
let scaled_font = scaled_fonts[sg.section_index];
|
|
let glyph = &sg.glyph;
|
|
min_x = min_x.min(glyph.position.x);
|
|
min_y = min_y.min(glyph.position.y - scaled_font.ascent());
|
|
max_x = max_x.max(glyph.position.x + scaled_font.h_advance(glyph.id));
|
|
max_y = max_y.max(glyph.position.y - scaled_font.descent());
|
|
}
|
|
|
|
let size = Vec2::new(max_x - min_x, max_y - min_y);
|
|
|
|
let glyphs = self.brush.process_glyphs(
|
|
section_glyphs,
|
|
§ions,
|
|
font_atlas_set_storage,
|
|
fonts,
|
|
texture_atlases,
|
|
textures,
|
|
text_settings,
|
|
y_axis_orientation,
|
|
)?;
|
|
|
|
Ok(TextLayoutInfo { glyphs, size })
|
|
}
|
|
}
|