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.
- Loading branch information
Showing
12 changed files
with
240 additions
and
10 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
Binary file not shown.
Binary file not shown.
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,13 @@ | ||
[package] | ||
name = "bevy_text" | ||
version = "0.1.0" | ||
authors = ["Carter Anderson <[email protected]>"] | ||
edition = "2018" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
bevy_render = { path = "../bevy_render" } | ||
skribo = "0.1.0" | ||
font-kit = "0.6" | ||
pathfinder_geometry = "0.5" |
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,27 @@ | ||
use crate::render::render_text; | ||
use bevy_render::{texture::Texture, Color}; | ||
use font_kit::{error::FontLoadingError, metrics::Metrics}; | ||
use skribo::{FontCollection, FontFamily}; | ||
use std::sync::Arc; | ||
|
||
pub struct Font { | ||
pub collection: FontCollection, | ||
pub metrics: Metrics, | ||
} | ||
|
||
impl Font { | ||
pub fn try_from_bytes(font_data: Vec<u8>) -> Result<Self, FontLoadingError> { | ||
let font = font_kit::font::Font::from_bytes(Arc::new(font_data), 0)?; | ||
let metrics = font.metrics(); | ||
let mut collection = FontCollection::new(); | ||
collection.add_family(FontFamily::new_from_font(font)); | ||
Ok(Font { | ||
collection, | ||
metrics, | ||
}) | ||
} | ||
|
||
pub fn render_text(&self, text: &str, color: Color, width: usize, height: usize) -> Texture { | ||
render_text(self, text, color, width, height) | ||
} | ||
} |
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,4 @@ | ||
mod render; | ||
mod font; | ||
|
||
pub use font::*; |
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,141 @@ | ||
use crate::Font; | ||
use bevy_render::{ | ||
texture::{Texture, TextureType}, | ||
Color, | ||
}; | ||
use font_kit::{ | ||
canvas::{Canvas, Format, RasterizationOptions}, | ||
hinting::HintingOptions, | ||
}; | ||
use pathfinder_geometry::transform2d::Transform2F; | ||
use skribo::{LayoutSession, TextStyle}; | ||
use std::ops::Range; | ||
|
||
struct TextSurface { | ||
width: usize, | ||
height: usize, | ||
pixels: Vec<u8>, | ||
} | ||
|
||
fn composite(a: u8, b: u8) -> u8 { | ||
let y = ((255 - a) as u16) * ((255 - b) as u16); | ||
let y = (y + (y >> 8) + 0x80) >> 8; // fast approx to round(y / 255) | ||
255 - (y as u8) | ||
} | ||
|
||
impl TextSurface { | ||
fn new(width: usize, height: usize) -> TextSurface { | ||
let pixels = vec![0; width * height]; | ||
TextSurface { | ||
width, | ||
height, | ||
pixels, | ||
} | ||
} | ||
|
||
fn paint_from_canvas(&mut self, canvas: &Canvas, x: i32, y: i32) { | ||
let (cw, ch) = (canvas.size.x(), canvas.size.y()); | ||
let (w, h) = (self.width as i32, self.height as i32); | ||
let y = y - ch; | ||
let xmin = 0.max(-x); | ||
let xmax = cw.min(w - x); | ||
let ymin = 0.max(-y); | ||
let ymax = ch.min(h - y); | ||
for yy in ymin..(ymax.max(ymin)) { | ||
for xx in xmin..(xmax.max(xmin)) { | ||
let pix = canvas.pixels[(cw * yy + xx) as usize]; | ||
let dst_ix = ((y + yy) * w + x + xx) as usize; | ||
self.pixels[dst_ix] = composite(self.pixels[dst_ix], pix); | ||
} | ||
} | ||
} | ||
|
||
fn paint_layout_session<S: AsRef<str>>( | ||
&mut self, | ||
layout: &mut LayoutSession<S>, | ||
x: i32, | ||
y: i32, | ||
size: f32, | ||
range: Range<usize>, | ||
) { | ||
for run in layout.iter_substr(range) { | ||
let font = run.font(); | ||
for glyph in run.glyphs() { | ||
let glyph_id = glyph.glyph_id; | ||
let glyph_x = (glyph.offset.x() as i32) + x; | ||
let glyph_y = (glyph.offset.y() as i32) + y; | ||
let bounds = font | ||
.font | ||
.raster_bounds( | ||
glyph_id, | ||
size, | ||
Transform2F::default(), | ||
HintingOptions::None, | ||
RasterizationOptions::GrayscaleAa, | ||
) | ||
.unwrap(); | ||
if bounds.width() > 0 && bounds.height() > 0 { | ||
let origin_adj = bounds.origin().to_f32(); | ||
let neg_origin = -origin_adj; | ||
let mut canvas = Canvas::new(bounds.size(), Format::A8); | ||
font.font | ||
.rasterize_glyph( | ||
&mut canvas, | ||
glyph_id, | ||
size, | ||
Transform2F::from_translation(neg_origin), | ||
HintingOptions::None, | ||
RasterizationOptions::GrayscaleAa, | ||
) | ||
.unwrap(); | ||
self.paint_from_canvas( | ||
&canvas, | ||
glyph_x + bounds.origin_x(), | ||
glyph_y - bounds.origin_y(), | ||
); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
pub fn render_text(font: &Font, text: &str, color: Color, width: usize, height: usize) -> Texture { | ||
let mut surface = TextSurface::new(width, height); | ||
let style = TextStyle { | ||
size: height as f32, | ||
}; | ||
let offset = style.size * (font.metrics.ascent - font.metrics.cap_height) | ||
/ font.metrics.units_per_em as f32; | ||
|
||
let mut layout = LayoutSession::create(&text, &style, &font.collection); | ||
surface.paint_layout_session( | ||
&mut layout, | ||
0, | ||
style.size as i32 - offset as i32, | ||
style.size, | ||
0..text.len(), | ||
); | ||
let color_u8 = [ | ||
(color.r * 255.0) as u8, | ||
(color.g * 255.0) as u8, | ||
(color.b * 255.0) as u8, | ||
]; | ||
|
||
Texture::load(TextureType::Data( | ||
surface | ||
.pixels | ||
.iter() | ||
.map(|p| { | ||
vec![ | ||
color_u8[0], | ||
color_u8[1], | ||
color_u8[2], | ||
(color.a * *p as f32) as u8, | ||
] | ||
}) | ||
.flatten() | ||
.collect::<Vec<u8>>(), | ||
surface.width, | ||
surface.height, | ||
)) | ||
} |
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,41 @@ | ||
use bevy::prelude::*; | ||
use std::{fs::File, io::Read}; | ||
|
||
fn main() { | ||
App::build() | ||
.add_default_plugins() | ||
.add_startup_system(setup) | ||
.run(); | ||
} | ||
|
||
fn setup(world: &mut World, resources: &mut Resources) { | ||
let mut texture_storage = resources.get_mut::<AssetStorage<Texture>>().unwrap(); | ||
let font_path = concat!( | ||
env!("CARGO_MANIFEST_DIR"), | ||
"/assets/fonts/FiraSans-Bold.ttf" | ||
); | ||
let mut font_file = File::open(&font_path).unwrap(); | ||
let mut buffer = Vec::new(); | ||
font_file.read_to_end(&mut buffer).unwrap(); | ||
let font = Font::try_from_bytes(buffer).unwrap(); | ||
|
||
let texture = font.render_text("Hello from Bevy!", Color::rgba(0.9, 0.9, 0.9, 1.0), 500, 60); | ||
let half_width = texture.width as f32 / 2.0; | ||
let half_height = texture.height as f32 / 2.0; | ||
let texture_handle = texture_storage.add(texture); | ||
let mut color_materials = resources.get_mut::<AssetStorage<ColorMaterial>>().unwrap(); | ||
world | ||
.build() | ||
// 2d camera | ||
.add_entity(Camera2dEntity::default()) | ||
// texture | ||
.add_entity(UiEntity { | ||
node: Node::new( | ||
math::vec2(0.0, 0.0), | ||
Anchors::CENTER, | ||
Margins::new(-half_width, half_width, -half_height, half_height), | ||
), | ||
material: color_materials.add(ColorMaterial::texture(texture_handle)), | ||
..Default::default() | ||
}); | ||
} |
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