Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store font texture atlas handles in a separate list in TextLayoutInfo #9471

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
54 changes: 45 additions & 9 deletions crates/bevy_text/src/glyph_brush.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ use glyph_brush_layout::{
BuiltInLineBreaker, FontId, GlyphPositioner, Layout, SectionGeometry, SectionGlyph,
SectionText, ToSectionText,
};
use std::ops::Range;

use crate::{
error::TextError, BreakLineOn, Font, FontAtlasSet, FontAtlasWarning, GlyphAtlasInfo,
TextAlignment, TextSettings, YAxisOrientation,
error::TextError, BreakLineOn, Font, FontAtlasSet, FontAtlasWarning, TextAlignment,
TextSettings, YAxisOrientation,
};

pub struct GlyphBrush {
Expand Down Expand Up @@ -64,9 +65,9 @@ impl GlyphBrush {
text_settings: &TextSettings,
font_atlas_warning: &mut FontAtlasWarning,
y_axis_orientation: YAxisOrientation,
) -> Result<Vec<PositionedGlyph>, TextError> {
) -> Result<(Vec<PositionedGlyphBatch>, Vec<PositionedGlyph>), TextError> {
if glyphs.is_empty() {
return Ok(Vec::new());
return Ok((Vec::new(), Vec::new()));
}

let sections_data = sections
Expand All @@ -85,8 +86,12 @@ impl GlyphBrush {
.collect::<Result<Vec<_>, _>>()?;

let text_bounds = compute_text_bounds(&glyphs, |index| &sections_data[index].3);

let mut glyph_batches = Vec::new();
let mut positioned_glyphs = Vec::new();
let mut batch_atlas: Option<Handle<TextureAtlas>> = None;
let mut batch_start = 0;
let mut end = 0;

for sg in glyphs {
let SectionGlyph {
section_index: _,
Expand All @@ -98,7 +103,9 @@ impl GlyphBrush {
let glyph_position = glyph.position;
let adjust = GlyphPlacementAdjuster::new(&mut glyph);
let section_data = sections_data[sg.section_index];

if let Some(outlined_glyph) = section_data.1.font.outline_glyph(glyph) {
end += 1;
let bounds = outlined_glyph.px_bounds();
let handle_font_atlas: Handle<FontAtlasSet> = section_data.0.cast_weak();
let font_atlas_set = font_atlas_set_storage
Expand All @@ -120,6 +127,7 @@ impl GlyphBrush {
}

let texture_atlas = texture_atlases.get(&atlas_info.texture_atlas).unwrap();

let glyph_rect = texture_atlas.textures[atlas_info.glyph_index];
let size = Vec2::new(glyph_rect.width(), glyph_rect.height());

Expand All @@ -135,17 +143,39 @@ impl GlyphBrush {
};

let position = adjust.position(Vec2::new(x, y));

positioned_glyphs.push(PositionedGlyph {
position,
size,
atlas_info,
glyph_index: atlas_info.glyph_index,
section_index: sg.section_index,
byte_index,
});

if let Some(ref last_atlas) = batch_atlas {
if last_atlas.id() != atlas_info.texture_atlas.id() {
glyph_batches.push(PositionedGlyphBatch {
texture_atlas: batch_atlas.unwrap(),
range: batch_start..end,
});
batch_start = end;
batch_atlas = Some(atlas_info.texture_atlas.clone());
}
} else {
batch_atlas = Some(atlas_info.texture_atlas.clone());
}
}
}
Ok(positioned_glyphs)

if batch_start != end {
glyph_batches.push(PositionedGlyphBatch {
texture_atlas: batch_atlas.unwrap(),
range: batch_start..end,
});
}

glyph_batches.sort_by_key(|batch| batch.texture_atlas.id());

Ok((glyph_batches, positioned_glyphs))
}

pub fn add_font(&mut self, handle: Handle<Font>, font: FontArc) -> FontId {
Expand All @@ -161,11 +191,17 @@ impl GlyphBrush {
pub struct PositionedGlyph {
pub position: Vec2,
pub size: Vec2,
pub atlas_info: GlyphAtlasInfo,
pub glyph_index: usize,
pub section_index: usize,
pub byte_index: usize,
}

#[derive(Debug, Clone)]
pub struct PositionedGlyphBatch {
pub texture_atlas: Handle<TextureAtlas>,
pub range: Range<usize>,
}

#[cfg(feature = "subpixel_glyph_atlas")]
struct GlyphPlacementAdjuster;

Expand Down
13 changes: 9 additions & 4 deletions crates/bevy_text/src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use glyph_brush_layout::{FontId, GlyphPositioner, SectionGeometry, SectionText};

use crate::{
compute_text_bounds, error::TextError, glyph_brush::GlyphBrush, scale_value, BreakLineOn, Font,
FontAtlasSet, FontAtlasWarning, PositionedGlyph, TextAlignment, TextSection, TextSettings,
YAxisOrientation,
FontAtlasSet, FontAtlasWarning, PositionedGlyph, PositionedGlyphBatch, TextAlignment,
TextSection, TextSettings, YAxisOrientation,
};

#[derive(Default, Resource)]
Expand All @@ -26,6 +26,7 @@ pub struct TextPipeline {
/// Contains scaled glyphs and their size. Generated via [`TextPipeline::queue_text`].
#[derive(Component, Clone, Default, Debug)]
pub struct TextLayoutInfo {
pub batches: Vec<PositionedGlyphBatch>,
pub glyphs: Vec<PositionedGlyph>,
pub size: Vec2,
}
Expand Down Expand Up @@ -87,7 +88,7 @@ impl TextPipeline {

let size = compute_text_bounds(&section_glyphs, |index| &scaled_fonts[index]).size();

let glyphs = self.brush.process_glyphs(
let (batches, glyphs) = self.brush.process_glyphs(
section_glyphs,
&sections,
font_atlas_set_storage,
Expand All @@ -99,7 +100,11 @@ impl TextPipeline {
y_axis_orientation,
)?;

Ok(TextLayoutInfo { glyphs, size })
Ok(TextLayoutInfo {
batches,
glyphs,
size,
})
}

pub fn create_text_measure(
Expand Down
48 changes: 25 additions & 23 deletions crates/bevy_text/src/text2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,30 +112,32 @@ pub fn extract_text2d_sprite(
* GlobalTransform::from_translation(alignment_translation.extend(0.));
let mut color = Color::WHITE;
let mut current_section = usize::MAX;
for PositionedGlyph {
position,
atlas_info,
section_index,
..
} in &text_layout_info.glyphs
{
if *section_index != current_section {
color = text.sections[*section_index].style.color.as_rgba_linear();
current_section = *section_index;
}
let atlas = texture_atlases.get(&atlas_info.texture_atlas).unwrap();
for batch in &text_layout_info.batches {
let atlas = texture_atlases.get(&batch.texture_atlas).unwrap();
for PositionedGlyph {
position,
glyph_index,
section_index,
..
} in &text_layout_info.glyphs[batch.range.start..batch.range.end]
{
if *section_index != current_section {
color = text.sections[*section_index].style.color.as_rgba_linear();
current_section = *section_index;
}

extracted_sprites.sprites.push(ExtractedSprite {
entity,
transform: transform * GlobalTransform::from_translation(position.extend(0.)),
color,
rect: Some(atlas.textures[atlas_info.glyph_index]),
custom_size: None,
image_handle_id: atlas.texture.id(),
flip_x: false,
flip_y: false,
anchor: Anchor::Center.as_vec(),
});
extracted_sprites.sprites.push(ExtractedSprite {
entity,
transform: transform * GlobalTransform::from_translation(position.extend(0.)),
color,
rect: Some(atlas.textures[*glyph_index]),
custom_size: None,
image_handle_id: atlas.texture.id(),
flip_x: false,
flip_y: false,
anchor: Anchor::Center.as_vec(),
});
}
}
}
}
Expand Down
56 changes: 29 additions & 27 deletions crates/bevy_ui/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,34 +544,36 @@ pub fn extract_text_uinodes(

let mut color = Color::WHITE;
let mut current_section = usize::MAX;
for PositionedGlyph {
position,
atlas_info,
section_index,
..
} in &text_layout_info.glyphs
{
if *section_index != current_section {
color = text.sections[*section_index].style.color.as_rgba_linear();
current_section = *section_index;

for batch in &text_layout_info.batches {
let atlas = texture_atlases.get(&batch.texture_atlas).unwrap();
for PositionedGlyph {
position,
glyph_index,
section_index,
..
} in &text_layout_info.glyphs[batch.range.start..batch.range.end]
{
if *section_index != current_section {
color = text.sections[*section_index].style.color.as_rgba_linear();
current_section = *section_index;
}
let mut rect = atlas.textures[*glyph_index];
rect.min *= inverse_scale_factor;
rect.max *= inverse_scale_factor;
extracted_uinodes.uinodes.push(ExtractedUiNode {
stack_index,
transform: transform
* Mat4::from_translation(position.extend(0.) * inverse_scale_factor),
color,
rect,
image: atlas.texture.clone_weak(),
atlas_size: Some(atlas.size * inverse_scale_factor),
clip: clip.map(|clip| clip.clip),
flip_x: false,
flip_y: false,
});
}
let atlas = texture_atlases.get(&atlas_info.texture_atlas).unwrap();

let mut rect = atlas.textures[atlas_info.glyph_index];
rect.min *= inverse_scale_factor;
rect.max *= inverse_scale_factor;
extracted_uinodes.uinodes.push(ExtractedUiNode {
stack_index,
transform: transform
* Mat4::from_translation(position.extend(0.) * inverse_scale_factor),
color,
rect,
image: atlas.texture.clone_weak(),
atlas_size: Some(atlas.size * inverse_scale_factor),
clip: clip.map(|clip| clip.clip),
flip_x: false,
flip_y: false,
});
}
}
}
Expand Down
Loading