diff --git a/crates/bevy_text/src/font_atlas.rs b/crates/bevy_text/src/font_atlas.rs index c696adc318ac5..92bef4ef048bd 100644 --- a/crates/bevy_text/src/font_atlas.rs +++ b/crates/bevy_text/src/font_atlas.rs @@ -91,6 +91,7 @@ impl FontAtlas { key: GlyphCacheKey, texture: &Image, offset: Vec2, + is_alpha_mask: bool, ) -> Result<(), TextError> { let mut atlas_texture = textures .get_mut(&self.texture) @@ -106,6 +107,7 @@ impl FontAtlas { GlyphAtlasLocation { glyph_index, offset, + is_alpha_mask, }, ); Ok(()) @@ -134,9 +136,16 @@ pub fn add_glyph_to_atlas( font_smoothing: FontSmoothing, glyph_id: u16, ) -> Result { - let (glyph_texture, offset) = get_outlined_glyph_texture(scaler, glyph_id, font_smoothing)?; + let (glyph_texture, offset, is_alpha_mask) = + get_outlined_glyph_texture(scaler, glyph_id, font_smoothing)?; let mut add_char_to_font_atlas = |atlas: &mut FontAtlas| -> Result<(), TextError> { - atlas.add_glyph(textures, GlyphCacheKey { glyph_id }, &glyph_texture, offset) + atlas.add_glyph( + textures, + GlyphCacheKey { glyph_id }, + &glyph_texture, + offset, + is_alpha_mask, + ) }; if !font_atlases .iter_mut() @@ -153,7 +162,13 @@ pub fn add_glyph_to_atlas( let mut new_atlas = FontAtlas::new(textures, UVec2::splat(containing), font_smoothing); - new_atlas.add_glyph(textures, GlyphCacheKey { glyph_id }, &glyph_texture, offset)?; + new_atlas.add_glyph( + textures, + GlyphCacheKey { glyph_id }, + &glyph_texture, + offset, + is_alpha_mask, + )?; font_atlases.push(new_atlas); } @@ -171,7 +186,7 @@ pub fn get_outlined_glyph_texture( scaler: &mut Scaler, glyph_id: u16, font_smoothing: FontSmoothing, -) -> Result<(Image, Vec2), TextError> { +) -> Result<(Image, Vec2, bool), TextError> { let image = swash::scale::Render::new(&[ swash::scale::Source::ColorOutline(0), swash::scale::Source::ColorBitmap(swash::scale::StrikeWith::BestFit), @@ -187,27 +202,35 @@ pub fn get_outlined_glyph_texture( let height = image.placement.height; let px = (width * height) as usize; - let mut rgba = vec![0u8; px * 4]; - match font_smoothing { - FontSmoothing::AntiAliased => { - for i in 0..px { - let a = image.data[i]; - rgba[i * 4 + 0] = 255; // R - rgba[i * 4 + 1] = 255; // G - rgba[i * 4 + 2] = 255; // B - rgba[i * 4 + 3] = a; // A from swash + let rgba = match image.content { + swash::scale::image::Content::Mask => { + let mut rgba = vec![0u8; px * 4]; + match font_smoothing { + FontSmoothing::AntiAliased => { + for i in 0..px { + let a = image.data[i]; + rgba[i * 4 + 0] = 255; // R + rgba[i * 4 + 1] = 255; // G + rgba[i * 4 + 2] = 255; // B + rgba[i * 4 + 3] = a; // A from swash + } + } + FontSmoothing::None => { + for i in 0..px { + let a = image.data[i]; + rgba[i * 4 + 0] = 255; // R + rgba[i * 4 + 1] = 255; // G + rgba[i * 4 + 2] = 255; // B + rgba[i * 4 + 3] = if 127 < a { 255 } else { 0 }; // A from swash + } + } } + rgba } - FontSmoothing::None => { - for i in 0..px { - let a = image.data[i]; - rgba[i * 4 + 0] = 255; // R - rgba[i * 4 + 1] = 255; // G - rgba[i * 4 + 2] = 255; // B - rgba[i * 4 + 3] = if 127 < a { 255 } else { 0 }; // A from swash - } + swash::scale::image::Content::Color | swash::scale::image::Content::SubpixelMask => { + image.data } - } + }; Ok(( Image::new( @@ -222,6 +245,7 @@ pub fn get_outlined_glyph_texture( RenderAssetUsages::MAIN_WORLD, ), Vec2::new(left as f32, -top as f32), + image.content == swash::scale::image::Content::Mask, )) } @@ -237,6 +261,7 @@ pub fn get_glyph_atlas_info( offset: location.offset, rect: atlas.texture_atlas.textures[location.glyph_index].as_rect(), texture: atlas.texture.id(), + is_alpha_mask: location.is_alpha_mask, }) }) } diff --git a/crates/bevy_text/src/glyph.rs b/crates/bevy_text/src/glyph.rs index e1afcbb1b9719..0325baa942ac4 100644 --- a/crates/bevy_text/src/glyph.rs +++ b/crates/bevy_text/src/glyph.rs @@ -40,6 +40,8 @@ pub struct GlyphAtlasInfo { pub rect: Rect, /// The required offset (relative positioning) when placed pub offset: Vec2, + /// True if this glyph is stored as a tintable alpha mask + pub is_alpha_mask: bool, } /// The location of a glyph in an atlas, @@ -53,4 +55,6 @@ pub struct GlyphAtlasLocation { pub glyph_index: usize, /// The required offset (relative positioning) when placed pub offset: Vec2, + /// True if this glyph is stored as a tintable alpha mask + pub is_alpha_mask: bool, } diff --git a/crates/bevy_ui_render/src/lib.rs b/crates/bevy_ui_render/src/lib.rs index 83855833da7fe..21fa1f301da98 100644 --- a/crates/bevy_ui_render/src/lib.rs +++ b/crates/bevy_ui_render/src/lib.rs @@ -1022,7 +1022,9 @@ pub fn extract_text_sections( current_section_index = *section_index; } - let color = if let Some(selected_text_color) = selected_text_color + let color = if !atlas_info.is_alpha_mask { + LinearRgba::WHITE + } else if let Some(selected_text_color) = selected_text_color && text_layout_info .selection_rects .iter() @@ -1030,7 +1032,8 @@ pub fn extract_text_sections( let glyph_rect = Rect::from_center_size(*position, atlas_info.rect.size()); selection_rect.contains(glyph_rect.min) && selection_rect.contains(glyph_rect.max) - }) { + }) + { selected_text_color } else { color