Skip to content
Snippets Groups Projects
Commit 8ea62832 authored by StarArawn's avatar StarArawn
Browse files

Added horz alignment..

parent ee29cae6
No related branches found
No related tags found
No related merge requests found
...@@ -4,7 +4,7 @@ use bevy::{ ...@@ -4,7 +4,7 @@ use bevy::{
sprite2::Rect, sprite2::Rect,
}; };
use kayak_core::render_primitive::RenderPrimitive; use kayak_core::render_primitive::RenderPrimitive;
use kayak_font::{CoordinateSystem, KayakFont}; use kayak_font::{Alignment, CoordinateSystem, KayakFont};
use crate::{ use crate::{
render::unified::pipeline::{ExtractQuadBundle, ExtractedQuad, UIQuadType}, render::unified::pipeline::{ExtractQuadBundle, ExtractedQuad, UIQuadType},
...@@ -54,8 +54,11 @@ pub fn extract_texts( ...@@ -54,8 +54,11 @@ pub fn extract_texts(
let chars_layouts = font.get_layout( let chars_layouts = font.get_layout(
CoordinateSystem::PositiveYDown, CoordinateSystem::PositiveYDown,
Alignment::Start,
Vec2::new(layout.posx, layout.posy), Vec2::new(layout.posx, layout.posy),
Vec2::new(layout.width, layout.height),
content, content,
font_size * 1.2,
font_size, font_size,
); );
......
...@@ -5,7 +5,7 @@ use bevy::{ ...@@ -5,7 +5,7 @@ use bevy::{
window::WindowDescriptor, window::WindowDescriptor,
PipelinedDefaultPlugins, PipelinedDefaultPlugins,
}; };
use kayak_font::{KayakFont, KayakFontPlugin}; use kayak_font::{Alignment, KayakFont, KayakFontPlugin};
mod renderer; mod renderer;
use renderer::FontRenderPlugin; use renderer::FontRenderPlugin;
...@@ -19,11 +19,39 @@ fn startup(mut commands: Commands, asset_server: Res<AssetServer>) { ...@@ -19,11 +19,39 @@ fn startup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands commands
.spawn() .spawn()
.insert(Text { .insert(Text {
horz_alignment: Alignment::Start,
color: Color::WHITE, color: Color::WHITE,
content: "Hello World!".into(), content: "Hello World! This text should wrap because its super long!".into(),
font_size: 32.0, font_size: 32.0,
line_height: 32.0 * 1.2, // Firefox method of calculating default line heights see: https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
position: Vec2::new(5.0, 5.0), position: Vec2::new(5.0, 5.0),
size: Vec2::new(100.0, 100.0), size: Vec2::new(250.0, 100.0),
})
.insert(font_handle.clone());
commands
.spawn()
.insert(Text {
horz_alignment: Alignment::End,
color: Color::WHITE,
content: "This is some text that will wrap and also be aligned to the right.".into(),
font_size: 32.0,
line_height: 32.0 * 1.2, // Firefox method of calculating default line heights see: https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
position: Vec2::new(-255.0, 5.0),
size: Vec2::new(250.0, 100.0),
})
.insert(font_handle.clone());
commands
.spawn()
.insert(Text {
horz_alignment: Alignment::Middle,
color: Color::WHITE,
content: "This is some text that will wrap and also be aligned in the middle.".into(),
font_size: 32.0,
line_height: 32.0 * 1.2, // Firefox method of calculating default line heights see: https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
position: Vec2::new(-125.0, -155.0),
size: Vec2::new(250.0, 100.0),
}) })
.insert(font_handle); .insert(font_handle);
} }
......
...@@ -20,8 +20,11 @@ pub fn extract( ...@@ -20,8 +20,11 @@ pub fn extract(
if let Some(font) = fonts.get(font_handle) { if let Some(font) = fonts.get(font_handle) {
let layouts = font.get_layout( let layouts = font.get_layout(
CoordinateSystem::PositiveYUp, CoordinateSystem::PositiveYUp,
text.horz_alignment,
text.position, text.position,
text.size,
&text.content, &text.content,
text.line_height,
text.font_size, text.font_size,
); );
......
use bevy::{math::Vec2, prelude::Component, render2::color::Color}; use bevy::{math::Vec2, prelude::Component, render2::color::Color};
use kayak_font::Alignment;
#[derive(Component)] #[derive(Component)]
pub struct Text { pub struct Text {
pub horz_alignment: Alignment,
pub content: String, pub content: String,
pub position: Vec2, pub position: Vec2,
pub size: Vec2, pub size: Vec2,
pub font_size: f32, pub font_size: f32,
pub line_height: f32,
pub color: Color, pub color: Color,
} }
...@@ -25,12 +25,19 @@ pub struct LayoutRect { ...@@ -25,12 +25,19 @@ pub struct LayoutRect {
pub content: char, pub content: char,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum CoordinateSystem { pub enum CoordinateSystem {
PositiveYUp, PositiveYUp,
PositiveYDown, PositiveYDown,
} }
#[derive(Copy, Clone, PartialEq)]
pub enum Alignment {
Start,
Middle,
End,
}
impl KayakFont { impl KayakFont {
pub fn new(sdf: Sdf, atlas_image: Handle<Image>) -> Self { pub fn new(sdf: Sdf, atlas_image: Handle<Image>) -> Self {
Self { Self {
...@@ -52,11 +59,36 @@ impl KayakFont { ...@@ -52,11 +59,36 @@ impl KayakFont {
self.char_ids.get(&c).and_then(|id| Some(*id)) self.char_ids.get(&c).and_then(|id| Some(*id))
} }
pub fn get_word_width(&self, word: &str, font_size: f32) -> f32 {
let mut width = 0.0;
for c in word.chars() {
if let Some(glyph) = self.sdf.glyphs.iter().find(|glyph| glyph.unicode == c) {
let plane_bounds = glyph.plane_bounds.as_ref();
let (_, _, char_width, _) = match plane_bounds {
Some(val) => (
val.left,
val.top,
val.size().x * font_size,
val.size().y * font_size,
),
None => (0.0, 0.0, 0.0, 0.0),
};
width += char_width;
}
}
width
}
pub fn get_layout( pub fn get_layout(
&self, &self,
axis_alignment: CoordinateSystem, axis_alignment: CoordinateSystem,
alignment: Alignment,
position: Vec2, position: Vec2,
max_size: Vec2,
content: &String, content: &String,
line_height: f32,
font_size: f32, font_size: f32,
) -> Vec<LayoutRect> { ) -> Vec<LayoutRect> {
let mut positions_and_size = Vec::new(); let mut positions_and_size = Vec::new();
...@@ -64,35 +96,90 @@ impl KayakFont { ...@@ -64,35 +96,90 @@ impl KayakFont {
let font_ratio = font_size / self.sdf.atlas.size; let font_ratio = font_size / self.sdf.atlas.size;
let resized_max_glyph_size = (max_glyph_size.x * font_ratio, max_glyph_size.y * font_ratio); let resized_max_glyph_size = (max_glyph_size.x * font_ratio, max_glyph_size.y * font_ratio);
let mut x = 0.0; // TODO: Make this configurable?
for c in content.chars() { let split_chars = vec![' ', '\t', '-', '\n'];
if let Some(glyph) = self.sdf.glyphs.iter().find(|glyph| glyph.unicode == c) { let missing_chars: Vec<char> = content
let plane_bounds = glyph.plane_bounds.as_ref(); .chars()
let (left, top, _width, _height) = match plane_bounds { .filter(|c| split_chars.iter().any(|c2| c == c2))
Some(val) => ( .collect();
val.left,
val.top,
val.size().x * font_size,
val.size().y * font_size,
),
None => (0.0, 0.0, 0.0, 0.0),
};
let shift_sign = match axis_alignment { let shift_sign = match axis_alignment {
CoordinateSystem::PositiveYDown => -1.0, CoordinateSystem::PositiveYDown => -1.0,
CoordinateSystem::PositiveYUp => 1.0, CoordinateSystem::PositiveYUp => 1.0,
}; };
let position_x = position.x + x + left * font_size; let mut line_widths = Vec::new();
let position_y = (position.y + (shift_sign * top * font_size)) + font_size;
positions_and_size.push(LayoutRect { let mut x = 0.0;
position: Vec2::new(position_x, position_y), let mut y = 0.0;
size: Vec2::new(resized_max_glyph_size.0, resized_max_glyph_size.1), let mut i = 0;
content: c, let mut line_starting_index = 0;
}); let mut last_width = 0.0;
for word in content.split(&split_chars[..]) {
let word_width = self.get_word_width(word, font_size);
if x + word_width > max_size.x {
y -= shift_sign * line_height;
line_widths.push((x, line_starting_index, positions_and_size.len()));
line_starting_index = positions_and_size.len();
x = 0.0;
}
for c in word.chars() {
if let Some(glyph) = self.sdf.glyphs.iter().find(|glyph| glyph.unicode == c) {
let plane_bounds = glyph.plane_bounds.as_ref();
let (left, top, width, _height) = match plane_bounds {
Some(val) => (
val.left,
val.top,
val.size().x * font_size,
val.size().y * font_size,
),
None => (0.0, 0.0, 0.0, 0.0),
};
last_width = width;
let position_x = x + left * font_size;
let position_y = y + (shift_sign * top * font_size);
positions_and_size.push(LayoutRect {
position: Vec2::new(position_x, position_y),
size: Vec2::new(resized_max_glyph_size.0, resized_max_glyph_size.1),
content: c,
});
x += glyph.advance * font_size;
}
}
if let Some(next_missing) = missing_chars.get(i) {
if let Some(glyph) = self
.sdf
.glyphs
.iter()
.find(|glyph| glyph.unicode == *next_missing)
{
x += glyph.advance * font_size;
}
i += 1;
}
}
x += glyph.advance * font_size; line_widths.push((
x + last_width,
line_starting_index,
positions_and_size.len(),
));
for (line_width, starting_index, end_index) in line_widths {
let shift_x = match alignment {
Alignment::Start => 0.0,
Alignment::Middle => (max_size.x - line_width) / 2.0,
Alignment::End => max_size.x - line_width,
};
for i in starting_index..end_index {
let layout_rect = &mut positions_and_size[i];
layout_rect.position.x += position.x + shift_x;
layout_rect.position.y += position.y;
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment