|
1 | | -use ab_glyph::{FontArc, FontVec, InvalidFont, OutlinedGlyph}; |
| 1 | +use std::sync::Arc; |
| 2 | + |
2 | 3 | use bevy_asset::Asset; |
3 | 4 | use bevy_reflect::TypePath; |
4 | | -use bevy_render::{ |
5 | | - render_asset::RenderAssetUsages, |
6 | | - render_resource::{Extent3d, TextureDimension, TextureFormat}, |
7 | | - texture::Image, |
8 | | -}; |
9 | 5 |
|
10 | | -#[derive(Asset, TypePath, Debug, Clone)] |
| 6 | +/// An [`Asset`] that contains the data for a loaded font, if loaded as an asset. |
| 7 | +/// |
| 8 | +/// Loaded by [`FontLoader`](crate::FontLoader). |
| 9 | +/// |
| 10 | +/// # A note on fonts |
| 11 | +/// |
| 12 | +/// `Font` may differ from the everyday notion of what a "font" is. |
| 13 | +/// A font *face* (e.g. Fira Sans Semibold Italic) is part of a font *family* (e.g. Fira Sans), |
| 14 | +/// and is distinguished from other font faces in the same family |
| 15 | +/// by its style (e.g. italic), its weight (e.g. bold) and its stretch (e.g. condensed). |
| 16 | +/// |
| 17 | +/// Bevy currently loads a single font face as a single `Font` asset. |
| 18 | +#[derive(Debug, TypePath, Clone, Asset)] |
11 | 19 | pub struct Font { |
12 | | - pub font: FontArc, |
| 20 | + /// Content of a font file as bytes |
| 21 | + pub data: Arc<Vec<u8>>, |
13 | 22 | } |
14 | 23 |
|
15 | 24 | impl Font { |
16 | | - pub fn try_from_bytes(font_data: Vec<u8>) -> Result<Self, InvalidFont> { |
17 | | - let font = FontVec::try_from_vec(font_data)?; |
18 | | - let font = FontArc::new(font); |
19 | | - Ok(Font { font }) |
20 | | - } |
21 | | - |
22 | | - pub fn get_outlined_glyph_texture(outlined_glyph: OutlinedGlyph) -> Image { |
23 | | - let bounds = outlined_glyph.px_bounds(); |
24 | | - // Increase the length of the glyph texture by 2-pixels on each axis to make space |
25 | | - // for a pixel wide transparent border along its edges. |
26 | | - let width = bounds.width() as usize + 2; |
27 | | - let height = bounds.height() as usize + 2; |
28 | | - let mut alpha = vec![0.0; width * height]; |
29 | | - outlined_glyph.draw(|x, y, v| { |
30 | | - // Displace the glyph by 1 pixel on each axis so that it is drawn in the center of the texture. |
31 | | - // This leaves a pixel wide transparent border around the glyph. |
32 | | - alpha[(y + 1) as usize * width + x as usize + 1] = v; |
33 | | - }); |
34 | | - |
35 | | - // TODO: make this texture grayscale |
36 | | - Image::new( |
37 | | - Extent3d { |
38 | | - width: width as u32, |
39 | | - height: height as u32, |
40 | | - depth_or_array_layers: 1, |
41 | | - }, |
42 | | - TextureDimension::D2, |
43 | | - alpha |
44 | | - .iter() |
45 | | - .flat_map(|a| vec![255, 255, 255, (*a * 255.0) as u8]) |
46 | | - .collect::<Vec<u8>>(), |
47 | | - TextureFormat::Rgba8UnormSrgb, |
48 | | - // This glyph image never needs to reach the render world because it's placed |
49 | | - // into a font texture atlas that'll be used for rendering. |
50 | | - RenderAssetUsages::MAIN_WORLD, |
51 | | - ) |
| 25 | + /// Creates a [`Font`] from bytes |
| 26 | + pub fn try_from_bytes( |
| 27 | + font_data: Vec<u8>, |
| 28 | + ) -> Result<Self, cosmic_text::ttf_parser::FaceParsingError> { |
| 29 | + use cosmic_text::ttf_parser; |
| 30 | + ttf_parser::Face::parse(&font_data, 0)?; |
| 31 | + Ok(Self { |
| 32 | + data: Arc::new(font_data), |
| 33 | + }) |
52 | 34 | } |
53 | 35 | } |
0 commit comments