Break at word boundaries

This commit is contained in:
Patrick Walton 2017-02-07 14:40:03 -08:00
parent e9fd5d6b1b
commit 66d239cf2f
2 changed files with 29 additions and 21 deletions

View File

@ -94,31 +94,40 @@ fn main() {
let codepoint_ranges = CodepointRanges::from_sorted_chars(&chars); let codepoint_ranges = CodepointRanges::from_sorted_chars(&chars);
let file = Mmap::open_path(font_path, Protection::Read).unwrap(); let file = Mmap::open_path(font_path, Protection::Read).unwrap();
let (font, shaped_glyph_positions, glyph_ranges); let (font, glyph_ranges);
unsafe { unsafe {
font = Font::new(file.as_slice()).unwrap(); font = Font::new(file.as_slice()).unwrap();
glyph_ranges = font.glyph_ranges_for_codepoint_ranges(&codepoint_ranges.ranges).unwrap(); glyph_ranges = font.glyph_ranges_for_codepoint_ranges(&codepoint_ranges.ranges).unwrap();
shaped_glyph_positions = shaper::shape_text(&font, &glyph_ranges, &text)
} }
let paragraph_width = (device_pixel_size.width as f32 * font.units_per_em() as f32 /
INITIAL_POINT_SIZE) as u32;
// Do some basic line breaking. // Do some basic line breaking.
let mut glyph_positions = vec![]; let mut glyph_positions = vec![];
let paragraph_width = (device_pixel_size.width as f32 * font.units_per_em() as f32 /
INITIAL_POINT_SIZE) as u32;
let space_advance = font.metrics_for_glyph(glyph_ranges.glyph_for(' ' as u32).unwrap())
.unwrap()
.advance_width as u32;
let line_spacing = font.units_per_em() as u32; let line_spacing = font.units_per_em() as u32;
let (mut current_x, mut current_y) = (0, line_spacing); let (mut current_x, mut current_y) = (0, line_spacing);
for glyph_position in &shaped_glyph_positions { for word in text.split_whitespace() {
current_x += glyph_position.advance as u32; let shaped_glyph_positions = shaper::shape_text(&font, &glyph_ranges, word);
if current_x > paragraph_width { let total_advance: u32 = shaped_glyph_positions.iter().map(|p| p.advance as u32).sum();
if current_x + total_advance > paragraph_width {
current_x = 0; current_x = 0;
current_y += line_spacing; current_y += line_spacing;
} }
glyph_positions.push(GlyphPos {
x: current_x, for glyph_position in &shaped_glyph_positions {
y: current_y, glyph_positions.push(GlyphPos {
glyph_id: glyph_position.glyph_id, x: current_x,
}); y: current_y,
glyph_id: glyph_position.glyph_id,
});
current_x += glyph_position.advance as u32;
}
current_x += space_advance
} }
let renderer = Renderer::new(); let renderer = Renderer::new();
@ -640,12 +649,12 @@ impl Renderer {
let mut fps_glyphs = vec![]; let mut fps_glyphs = vec![];
let mut current_x = 0; let mut current_x = 0;
for glyph_pos in &shaper::shape_text(&font, &glyph_ranges, &fps_text) { for glyph_pos in &shaper::shape_text(&font, &glyph_ranges, &fps_text) {
current_x += glyph_pos.advance as u32;
fps_glyphs.push(GlyphPos { fps_glyphs.push(GlyphPos {
x: current_x, x: current_x,
y: 0, y: 0,
glyph_id: glyph_pos.glyph_id, glyph_id: glyph_pos.glyph_id,
}); });
current_x += glyph_pos.advance as u32;
} }
self.draw_glyphs(font, self.draw_glyphs(font,

View File

@ -19,20 +19,19 @@ use otf::Font;
use std::cmp; use std::cmp;
pub fn shape_text(font: &Font, glyph_ranges: &GlyphRanges, string: &str) -> Vec<GlyphPos> { pub fn shape_text(font: &Font, glyph_ranges: &GlyphRanges, string: &str) -> Vec<GlyphPos> {
let mut advance = 0;
string.chars().map(|ch| { string.chars().map(|ch| {
let glyph_id = glyph_ranges.glyph_for(ch as u32).unwrap_or(0); let glyph_id = glyph_ranges.glyph_for(ch as u32).unwrap_or(0);
let metrics = font.metrics_for_glyph(glyph_id); let metrics = font.metrics_for_glyph(glyph_id);
let pos = GlyphPos { let advance = match metrics {
glyph_id: glyph_id, Err(_) => 0,
advance: cmp::max(0, advance) as u16, Ok(metrics) => metrics.advance_width,
}; };
if let Ok(ref metrics) = metrics { GlyphPos {
advance = metrics.advance_width as i32 glyph_id: glyph_id,
advance: advance,
} }
pos
}).collect() }).collect()
} }