forked from bevyengine/bevy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes bevyengine#7616. Cosmic-text is a more mature text-rendering library that handles scripts and ligatures better than ab_glyph, it can also handle system fonts which can be implemented in bevy in the future Rebase of bevyengine#8808 Replaces text renderer ab_glyph with cosmic-text The definition of the font size has changed with the migration to cosmic text. The behavior is now consistent with other platforms (e.g. the web), where the font size in pixels measures the height of the font (the distance between the top of the highest ascender and the bottom of the lowest descender). Font sizes in your app need to be rescaled to approximately 1.2x smaller; for example, if you were using a font size of 60.0, you should now use a font size of 50.0. - `Text2dBounds` has been replaced with `TextBounds`, and it now accepts `Option`s to the bounds, instead of using `f32::INFINITY` to inidicate lack of bounds - Textsizes should be changed, dividing the current size with 1.2 will result in the same size as before. - `TextSettings` struct is removed - Feature `subpixel_alignment` has been removed since cosmic-text already does this automatically - TextBundles and things rendering texts requires the `CosmicBuffer` Component on them as well - TextPipeline: reconstruct byte indices for keeping track of eventual cursors in text input - TextPipeline: (future work) split text entities into section entities - TextPipeline: (future work) text editing - Support line height as an option. Unitless `1.2` is the default used in browsers (1.2x font size). - Support System Fonts and font families - Example showing of animated text styles. Eg. throbbing hyperlinks --------- Co-authored-by: tigregalis <[email protected]> Co-authored-by: Nico Burns <[email protected]> Co-authored-by: sam edelsten <[email protected]> Co-authored-by: Dimchikkk <[email protected]> Co-authored-by: Alice Cecile <[email protected]> Co-authored-by: Rob Parrett <[email protected]>
- Loading branch information
Showing
32 changed files
with
1,088 additions
and
615 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
use bevy_ecs::{component::Component, reflect::ReflectComponent}; | ||
use bevy_math::Vec2; | ||
use bevy_reflect::Reflect; | ||
|
||
/// The maximum width and height of text. The text will wrap according to the specified size. | ||
/// Characters out of the bounds after wrapping will be truncated. Text is aligned according to the | ||
/// specified [`JustifyText`](crate::text::JustifyText). | ||
/// | ||
/// Note: only characters that are completely out of the bounds will be truncated, so this is not a | ||
/// reliable limit if it is necessary to contain the text strictly in the bounds. Currently this | ||
/// component is mainly useful for text wrapping only. | ||
#[derive(Component, Copy, Clone, Debug, Reflect)] | ||
#[reflect(Component)] | ||
pub struct TextBounds { | ||
/// The maximum width of text in logical pixels. | ||
/// If `None`, the width is unbounded. | ||
pub width: Option<f32>, | ||
/// The maximum height of text in logical pixels. | ||
/// If `None`, the height is unbounded. | ||
pub height: Option<f32>, | ||
} | ||
|
||
impl Default for TextBounds { | ||
#[inline] | ||
fn default() -> Self { | ||
Self::UNBOUNDED | ||
} | ||
} | ||
|
||
impl TextBounds { | ||
/// Unbounded text will not be truncated or wrapped. | ||
pub const UNBOUNDED: Self = Self { | ||
width: None, | ||
height: None, | ||
}; | ||
|
||
/// Creates a new `TextBounds`, bounded with the specified width and height values. | ||
#[inline] | ||
pub const fn new(width: f32, height: f32) -> Self { | ||
Self { | ||
width: Some(width), | ||
height: Some(height), | ||
} | ||
} | ||
|
||
/// Creates a new `TextBounds`, bounded with the specified width value and unbounded on height. | ||
#[inline] | ||
pub const fn new_horizontal(width: f32) -> Self { | ||
Self { | ||
width: Some(width), | ||
height: None, | ||
} | ||
} | ||
|
||
/// Creates a new `TextBounds`, bounded with the specified height value and unbounded on width. | ||
#[inline] | ||
pub const fn new_vertical(height: f32) -> Self { | ||
Self { | ||
width: None, | ||
height: Some(height), | ||
} | ||
} | ||
} | ||
|
||
impl From<Vec2> for TextBounds { | ||
#[inline] | ||
fn from(v: Vec2) -> Self { | ||
Self::new(v.x, v.y) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,17 @@ | ||
use ab_glyph::GlyphId; | ||
use cosmic_text::CacheKey; | ||
use thiserror::Error; | ||
|
||
#[derive(Debug, PartialEq, Eq, Error)] | ||
/// Errors related to the textsystem | ||
pub enum TextError { | ||
/// Font was not found, this could be that the font has not yet been loaded, or | ||
/// that the font failed to load for some other reason | ||
#[error("font not found")] | ||
NoSuchFont, | ||
/// Failed to add glyph to a newly created atlas for some reason | ||
#[error("failed to add glyph to newly-created atlas {0:?}")] | ||
FailedToAddGlyph(GlyphId), | ||
FailedToAddGlyph(u16), | ||
/// Failed to get scaled glyph image for cache key | ||
#[error("failed to get scaled glyph image for cache key: {0:?}")] | ||
FailedToGetGlyphImage(CacheKey), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,35 @@ | ||
use ab_glyph::{FontArc, FontVec, InvalidFont, OutlinedGlyph}; | ||
use std::sync::Arc; | ||
|
||
use bevy_asset::Asset; | ||
use bevy_reflect::TypePath; | ||
use bevy_render::{ | ||
render_asset::RenderAssetUsages, | ||
render_resource::{Extent3d, TextureDimension, TextureFormat}, | ||
texture::Image, | ||
}; | ||
|
||
#[derive(Asset, TypePath, Debug, Clone)] | ||
/// An [`Asset`] that contains the data for a loaded font, if loaded as an asset. | ||
/// | ||
/// Loaded by [`FontLoader`](crate::FontLoader). | ||
/// | ||
/// # A note on fonts | ||
/// | ||
/// `Font` may differ from the everyday notion of what a "font" is. | ||
/// A font *face* (e.g. Fira Sans Semibold Italic) is part of a font *family* (e.g. Fira Sans), | ||
/// and is distinguished from other font faces in the same family | ||
/// by its style (e.g. italic), its weight (e.g. bold) and its stretch (e.g. condensed). | ||
/// | ||
/// Bevy currently loads a single font face as a single `Font` asset. | ||
#[derive(Debug, TypePath, Clone, Asset)] | ||
pub struct Font { | ||
pub font: FontArc, | ||
/// Content of a font file as bytes | ||
pub data: Arc<Vec<u8>>, | ||
} | ||
|
||
impl Font { | ||
pub fn try_from_bytes(font_data: Vec<u8>) -> Result<Self, InvalidFont> { | ||
let font = FontVec::try_from_vec(font_data)?; | ||
let font = FontArc::new(font); | ||
Ok(Font { font }) | ||
} | ||
|
||
pub fn get_outlined_glyph_texture(outlined_glyph: OutlinedGlyph) -> Image { | ||
let bounds = outlined_glyph.px_bounds(); | ||
// Increase the length of the glyph texture by 2-pixels on each axis to make space | ||
// for a pixel wide transparent border along its edges. | ||
let width = bounds.width() as usize + 2; | ||
let height = bounds.height() as usize + 2; | ||
let mut alpha = vec![0.0; width * height]; | ||
outlined_glyph.draw(|x, y, v| { | ||
// Displace the glyph by 1 pixel on each axis so that it is drawn in the center of the texture. | ||
// This leaves a pixel wide transparent border around the glyph. | ||
alpha[(y + 1) as usize * width + x as usize + 1] = v; | ||
}); | ||
|
||
// TODO: make this texture grayscale | ||
Image::new( | ||
Extent3d { | ||
width: width as u32, | ||
height: height as u32, | ||
depth_or_array_layers: 1, | ||
}, | ||
TextureDimension::D2, | ||
alpha | ||
.iter() | ||
.flat_map(|a| vec![255, 255, 255, (*a * 255.0) as u8]) | ||
.collect::<Vec<u8>>(), | ||
TextureFormat::Rgba8UnormSrgb, | ||
// This glyph image never needs to reach the render world because it's placed | ||
// into a font texture atlas that'll be used for rendering. | ||
RenderAssetUsages::MAIN_WORLD, | ||
) | ||
/// Creates a [`Font`] from bytes | ||
pub fn try_from_bytes( | ||
font_data: Vec<u8>, | ||
) -> Result<Self, cosmic_text::ttf_parser::FaceParsingError> { | ||
use cosmic_text::ttf_parser; | ||
ttf_parser::Face::parse(&font_data, 0)?; | ||
Ok(Self { | ||
data: Arc::new(font_data), | ||
}) | ||
} | ||
} |
Oops, something went wrong.