mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 20:29:04 +03:00
trying to sort out line height
This commit is contained in:
parent
c51c37caba
commit
f262317b7e
@ -24,4 +24,4 @@ serde_derive = "1.0.98"
|
||||
simsearch = "0.1.4"
|
||||
stretch = "0.3.2"
|
||||
textwrap = "0.11"
|
||||
usvg = { git = "https://github.com/dabreegster/resvg" }
|
||||
usvg = { path = "/home/dabreegster/Downloads/resvg/usvg" }
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::text::Font;
|
||||
use crate::GeomBatch;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
@ -6,27 +7,46 @@ use usvg::Options;
|
||||
// TODO We don't need refcell maybe? Can we take &mut Assets?
|
||||
pub struct Assets {
|
||||
pub default_line_height: f64,
|
||||
pub font_size: usize,
|
||||
pub default_font_size: usize,
|
||||
text_cache: RefCell<HashMap<String, GeomBatch>>,
|
||||
line_height_cache: RefCell<HashMap<(Font, usize), f64>>,
|
||||
pub text_opts: Options,
|
||||
}
|
||||
|
||||
impl Assets {
|
||||
pub fn new(font_size: usize, font_dir: String) -> Assets {
|
||||
pub fn new(default_font_size: usize, font_dir: String) -> Assets {
|
||||
let mut a = Assets {
|
||||
default_line_height: 0.0,
|
||||
font_size,
|
||||
default_font_size,
|
||||
text_cache: RefCell::new(HashMap::new()),
|
||||
line_height_cache: RefCell::new(HashMap::new()),
|
||||
text_opts: Options::default(),
|
||||
};
|
||||
a.default_line_height = a.line_height(a.font_size);
|
||||
a.default_line_height = a.line_height(Font::DejaVu, a.default_font_size);
|
||||
a.text_opts.font_directories.push(font_dir);
|
||||
a
|
||||
}
|
||||
|
||||
pub fn line_height(&self, font_size: usize) -> f64 {
|
||||
// TODO Ahhh this stops working.
|
||||
font_size as f64
|
||||
pub fn line_height(&self, font: Font, font_size: usize) -> f64 {
|
||||
let key = (font, font_size);
|
||||
if let Some(height) = self.line_height_cache.borrow().get(&key) {
|
||||
return *height;
|
||||
}
|
||||
|
||||
// TODO This is expensive and hacky!
|
||||
let mut db = usvg::Database::new();
|
||||
db.populate(&self.text_opts);
|
||||
let height = db
|
||||
.load_font_idx(match font {
|
||||
Font::DejaVu => 0,
|
||||
Font::RobotoBold => 1,
|
||||
Font::Roboto => 2,
|
||||
})
|
||||
.unwrap()
|
||||
.height(font_size as f64);
|
||||
|
||||
self.line_height_cache.borrow_mut().insert(key, height);
|
||||
height
|
||||
}
|
||||
|
||||
pub fn get_cached_text(&self, key: &str) -> Option<GeomBatch> {
|
||||
|
@ -381,7 +381,7 @@ impl GeomBatch {
|
||||
}
|
||||
|
||||
// Sets the top-left to 0, 0. Not sure exactly when this should be used.
|
||||
pub(crate) fn realign(mut self) -> GeomBatch {
|
||||
pub(crate) fn autocrop(mut self) -> GeomBatch {
|
||||
let mut bounds = Bounds::new();
|
||||
for (_, poly) in &self.list {
|
||||
bounds.union(poly.get_bounds());
|
||||
|
@ -16,8 +16,8 @@ pub const INACTIVE_CHOICE_COLOR: Color = Color::grey(0.4);
|
||||
// TODO Don't do this!
|
||||
const MAX_CHAR_WIDTH: f64 = 25.0;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
enum Font {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Font {
|
||||
DejaVu,
|
||||
Roboto,
|
||||
RobotoBold,
|
||||
@ -199,20 +199,24 @@ impl Text {
|
||||
return batch;
|
||||
}
|
||||
|
||||
// TODO Bad guess
|
||||
let empty_line_height = 30.0;
|
||||
|
||||
let mut output_batch = GeomBatch::new();
|
||||
let mut master_batch = GeomBatch::new();
|
||||
|
||||
let mut y = 0.0;
|
||||
let mut max_width = 0.0_f64;
|
||||
for (line_color, line) in self.lines {
|
||||
let line_batch = render_text(line, tolerance, &assets.text_opts);
|
||||
// Assume size doesn't change mid-line. Always use this fixed line height per font
|
||||
// size.
|
||||
let line_height = assets.line_height(
|
||||
line[0].font,
|
||||
line[0].size.unwrap_or(assets.default_font_size),
|
||||
);
|
||||
|
||||
let line_batch = render_text(line, tolerance, assets);
|
||||
let line_dims = if line_batch.is_empty() {
|
||||
ScreenDims::new(0.0, empty_line_height)
|
||||
ScreenDims::new(0.0, line_height)
|
||||
} else {
|
||||
line_batch.get_dims()
|
||||
ScreenDims::new(line_batch.get_dims().width, line_height)
|
||||
};
|
||||
|
||||
if let Some(c) = line_color {
|
||||
@ -222,7 +226,6 @@ impl Text {
|
||||
);
|
||||
}
|
||||
|
||||
// TODO Do this first or not? Should we call realign() around here?
|
||||
y += line_dims.height;
|
||||
|
||||
for (color, poly) in line_batch.consume() {
|
||||
@ -244,7 +247,7 @@ impl Text {
|
||||
}
|
||||
|
||||
pub fn render_to_batch(self, prerender: &Prerender) -> GeomBatch {
|
||||
self.render(&prerender.assets).realign()
|
||||
self.render(&prerender.assets).autocrop()
|
||||
}
|
||||
|
||||
fn hash_key(&self) -> String {
|
||||
@ -254,15 +257,14 @@ impl Text {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_text(spans: Vec<TextSpan>, tolerance: f32, opts: &usvg::Options) -> GeomBatch {
|
||||
fn render_text(spans: Vec<TextSpan>, tolerance: f32, assets: &Assets) -> GeomBatch {
|
||||
// TODO This assumes size and font don't change mid-line. We might be able to support that now,
|
||||
// actually.
|
||||
|
||||
// Just set a sufficiently large view box
|
||||
let mut svg = format!(
|
||||
r##"<svg width="9999" height="9999" viewBox="0 0 9999 9999" xmlns="http://www.w3.org/2000/svg"><text x="0" y="0" font-size="{}" {}>"##,
|
||||
// TODO Plumb through default font size?
|
||||
spans[0].size.unwrap_or(30),
|
||||
spans[0].size.unwrap_or(assets.default_font_size),
|
||||
match spans[0].font {
|
||||
Font::DejaVu => "font-family=\"DejaVu Sans\"",
|
||||
Font::Roboto => "font-family=\"Roboto\"",
|
||||
@ -284,7 +286,7 @@ fn render_text(spans: Vec<TextSpan>, tolerance: f32, opts: &usvg::Options) -> Ge
|
||||
|
||||
//println!("- Rendering: {}", contents);
|
||||
|
||||
let svg_tree = match usvg::Tree::from_str(&svg, opts) {
|
||||
let svg_tree = match usvg::Tree::from_str(&svg, &assets.text_opts) {
|
||||
Ok(t) => t,
|
||||
Err(err) => panic!("render_text({}): {}", contents, err),
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user