preps for variable font size

This commit is contained in:
Dustin Carlino 2019-04-22 19:01:55 -07:00
parent 1aa1be6df2
commit 008b2f9de5
11 changed files with 59 additions and 40 deletions

View File

@ -245,7 +245,7 @@ pub struct DrawCtx<'a> {
fn styled_kv(txt: &mut Text, tags: &BTreeMap<String, String>) {
for (k, v) in tags {
txt.add_styled_line(k.to_string(), Some(Color::RED), None);
txt.add_styled_line(k.to_string(), Some(Color::RED), None, None);
txt.append(" = ".to_string(), None);
txt.append(v.to_string(), Some(Color::CYAN));
}

View File

@ -56,7 +56,7 @@ fn panel(ctx: &mut PluginCtx) -> ShowScoreState {
}
fn summarize(txt: &mut Text, summary: ScoreSummary) {
txt.add_styled_line("Walking".to_string(), None, Some(Color::RED.alpha(0.8)));
txt.add_styled_line("Walking".to_string(), None, Some(Color::RED.alpha(0.8)), None);
txt.add_line(format!(
" {}/{} trips done",
(summary.total_walking_trips - summary.pending_walking_trips),
@ -64,7 +64,7 @@ fn summarize(txt: &mut Text, summary: ScoreSummary) {
));
txt.add_line(format!(" {} total", summary.total_walking_trip_time));
txt.add_styled_line("Driving".to_string(), None, Some(Color::BLUE.alpha(0.8)));
txt.add_styled_line("Driving".to_string(), None, Some(Color::BLUE.alpha(0.8)), None);
txt.add_line(format!(
" {}/{} trips done",
(summary.total_driving_trips - summary.pending_driving_trips),

View File

@ -1,8 +1,10 @@
use crate::screen_geom::ScreenRectangle;
use crate::{ScreenPt, Text, UserInput};
use crate::{text, ScreenPt, Text, UserInput};
use geom::{Bounds, Pt2D};
use glium_glyph::glyph_brush::rusttype::Scale;
use glium_glyph::GlyphBrush;
use std::cell::RefCell;
use std::collections::HashMap;
const ZOOM_SPEED: f64 = 0.1;
@ -24,7 +26,7 @@ pub struct Canvas {
pub window_height: f64,
pub(crate) glyphs: RefCell<GlyphBrush<'static, 'static>>,
pub(crate) line_height: f64,
line_height_per_font_size: RefCell<HashMap<usize, f64>>,
// TODO Bit weird and hacky to mutate inside of draw() calls.
pub(crate) covered_areas: RefCell<Vec<ScreenRectangle>>,
@ -35,7 +37,6 @@ impl Canvas {
initial_width: f64,
initial_height: f64,
glyphs: GlyphBrush<'static, 'static>,
line_height: f64,
) -> Canvas {
Canvas {
cam_x: 0.0,
@ -51,7 +52,7 @@ impl Canvas {
window_height: initial_height,
glyphs: RefCell::new(glyphs),
line_height,
line_height_per_font_size: RefCell::new(HashMap::new()),
covered_areas: RefCell::new(Vec::new()),
}
}
@ -168,12 +169,25 @@ impl Canvas {
// TODO Not super happy about exposing this; fork_screenspace for external callers should be
// smarter.
pub fn top_menu_height(&self) -> f64 {
self.line_height
self.line_height(text::FONT_SIZE)
}
pub fn text_dims(&self, txt: &Text) -> (f64, f64) {
txt.dims(self)
}
// Don't call this while glyphs are mutably borrowed.
pub(crate) fn line_height(&self, font_size: usize) -> f64 {
let mut hash = self.line_height_per_font_size.borrow_mut();
if hash.contains_key(&font_size) {
return hash[&font_size];
}
let vmetrics = self.glyphs.borrow().fonts()[0].v_metrics(Scale::uniform(font_size as f32));
// TODO This works for this font, but could be more paranoid with abs()
let line_height = f64::from(vmetrics.ascent - vmetrics.descent + vmetrics.line_gap);
hash.insert(font_size, line_height);
line_height
}
}
pub enum HorizontalAlignment {

View File

@ -155,7 +155,7 @@ impl<'a> GfxCtx<'a> {
};
let y1 = match vert {
VerticalAlignment::Top => 0.0,
VerticalAlignment::BelowTopMenu => self.canvas.line_height,
VerticalAlignment::BelowTopMenu => self.canvas.line_height(text::FONT_SIZE),
VerticalAlignment::Center => (self.canvas.window_height - height) / 2.0,
VerticalAlignment::Bottom => self.canvas.window_height - height,
};

View File

@ -1,11 +1,10 @@
use crate::input::{ContextMenu, ModalMenuState};
use crate::{
text, widgets, Canvas, Event, EventCtx, GfxCtx, HorizontalAlignment, ModalMenu, Prerender,
Text, TopMenu, UserInput, VerticalAlignment,
widgets, Canvas, Event, EventCtx, GfxCtx, HorizontalAlignment, ModalMenu, Prerender, Text,
TopMenu, UserInput, VerticalAlignment,
};
use glium::glutin;
use glium_glyph::glyph_brush::rusttype::Font;
use glium_glyph::glyph_brush::rusttype::Scale;
use glium_glyph::GlyphBrush;
use std::cell::Cell;
use std::time::{Duration, Instant};
@ -211,13 +210,9 @@ pub fn run<G: GUI, F: FnOnce(&mut Canvas, &Prerender) -> G>(
.unwrap();
let dejavu: &[u8] = include_bytes!("assets/DejaVuSans.ttf");
let fonts = vec![Font::from_bytes(dejavu).unwrap()];
let vmetrics = fonts[0].v_metrics(Scale::uniform(text::FONT_SIZE));
// TODO This works for this font, but could be more paranoid with abs()
let line_height = f64::from(vmetrics.ascent - vmetrics.descent + vmetrics.line_gap);
let glyphs = GlyphBrush::new(&display, fonts);
let glyphs = GlyphBrush::new(&display, vec![Font::from_bytes(dejavu).unwrap()]);
let mut canvas = Canvas::new(initial_width, initial_height, glyphs, line_height);
let mut canvas = Canvas::new(initial_width, initial_height, glyphs);
let prerender = Prerender {
display: &display,
num_uploads: Cell::new(0),

View File

@ -13,7 +13,7 @@ pub const SELECTED_COLOR: Color = Color::RED;
pub const HOTKEY_COLOR: Color = Color::GREEN;
pub const INACTIVE_CHOICE_COLOR: Color = Color::grey(0.4);
pub const FONT_SIZE: f32 = 30.0;
pub const FONT_SIZE: usize = 30;
// TODO Don't do this!
const MAX_CHAR_WIDTH: f64 = 25.0;
@ -21,7 +21,8 @@ const MAX_CHAR_WIDTH: f64 = 25.0;
struct TextSpan {
text: String,
fg_color: Color,
// TODO bold, italic, font size, font style
size: usize,
// TODO bold, italic, font style
}
impl TextSpan {
@ -29,6 +30,7 @@ impl TextSpan {
TextSpan {
text,
fg_color: FG_COLOR,
size: FONT_SIZE,
}
}
}
@ -85,12 +87,14 @@ impl Text {
line: String,
fg_color: Option<Color>,
highlight_color: Option<Color>,
font_size: Option<usize>,
) {
self.lines.push((
highlight_color,
vec![TextSpan {
text: line,
fg_color: fg_color.unwrap_or(FG_COLOR),
size: font_size.unwrap_or(FONT_SIZE),
}],
));
}
@ -103,6 +107,7 @@ impl Text {
self.lines.last_mut().unwrap().1.push(TextSpan {
text,
fg_color: fg_color.unwrap_or(FG_COLOR),
size: FONT_SIZE,
});
}
@ -115,6 +120,9 @@ impl Text {
}
pub(crate) fn dims(&self, canvas: &Canvas) -> (f64, f64) {
// Always use the max height, since other stuff like menus assume a fixed height.
let height = (self.lines.len() as f64) * canvas.line_height(FONT_SIZE);
let mut glyphs = canvas.glyphs.borrow_mut();
let width = f64::from(
self.lines
@ -128,7 +136,7 @@ impl Text {
glyphs
.pixel_bounds(Section {
text: &full_line,
scale: Scale::uniform(FONT_SIZE),
scale: Scale::uniform(FONT_SIZE as f32),
..Section::default()
})
.map(|rect| rect.width())
@ -138,8 +146,7 @@ impl Text {
.unwrap(),
);
// Always use the max height, since other stuff like menus assume a fixed height.
(width, (self.lines.len() as f64) * canvas.line_height)
(width, height)
}
}
@ -164,7 +171,6 @@ pub fn draw_text_bubble(
);
}
let mut glyphs = g.canvas.glyphs.borrow_mut();
let mut y = top_left.y;
for (line_color, line) in &txt.lines {
let section = VariedSection {
@ -174,7 +180,7 @@ pub fn draw_text_bubble(
.map(|span| SectionText {
text: &span.text,
color: span.fg_color.0,
scale: Scale::uniform(FONT_SIZE),
scale: Scale::uniform(FONT_SIZE as f32),
..SectionText::default()
})
.collect(),
@ -187,13 +193,13 @@ pub fn draw_text_bubble(
&Polygon::rectangle_topleft(
Pt2D::new(top_left.x, y),
total_width,
g.canvas.line_height,
g.canvas.line_height(FONT_SIZE),
),
);
}
y += g.canvas.line_height;
glyphs.queue(section);
y += g.canvas.line_height(FONT_SIZE);
g.canvas.glyphs.borrow_mut().queue(section);
}
g.unfork();

View File

@ -8,7 +8,7 @@ pub struct LogScroller {
impl LogScroller {
pub fn new(title: String, lines: Vec<String>) -> LogScroller {
let mut text = Text::new();
text.add_styled_line(title, None, Some(text::PROMPT_COLOR));
text.add_styled_line(title, None, Some(text::PROMPT_COLOR), Some(50));
for line in lines {
text.add_line(line);
}

View File

@ -66,7 +66,7 @@ impl<T: Clone> Menu<T> {
} else {
total_width
};
ScreenPt::new(canvas.window_width - w, canvas.line_height)
ScreenPt::new(canvas.window_width - w, canvas.line_height(text::FONT_SIZE))
}
};
@ -197,7 +197,7 @@ impl<T: Clone> Menu<T> {
pub fn draw(&self, g: &mut GfxCtx) {
let mut txt = Text::new();
if let Some(ref line) = self.prompt {
txt.add_styled_line(line.to_string(), None, Some(text::PROMPT_COLOR));
txt.add_styled_line(line.to_string(), None, Some(text::PROMPT_COLOR), None);
}
for (idx, (hotkey, choice, active, _)) in self.choices.iter().enumerate() {
let bg = if Some(idx) == self.current_idx {
@ -207,10 +207,10 @@ impl<T: Clone> Menu<T> {
};
if *active {
if let Some(key) = hotkey {
txt.add_styled_line(key.describe(), Some(text::HOTKEY_COLOR), bg);
txt.add_styled_line(key.describe(), Some(text::HOTKEY_COLOR), bg, None);
txt.append(format!(" - {}", choice), None);
} else {
txt.add_styled_line(choice.to_string(), None, bg);
txt.add_styled_line(choice.to_string(), None, bg, None);
}
} else {
if let Some(key) = hotkey {
@ -218,9 +218,10 @@ impl<T: Clone> Menu<T> {
format!("{} - {}", key.describe(), choice),
Some(text::INACTIVE_CHOICE_COLOR),
bg,
None,
);
} else {
txt.add_styled_line(choice.to_string(), Some(text::INACTIVE_CHOICE_COLOR), bg);
txt.add_styled_line(choice.to_string(), Some(text::INACTIVE_CHOICE_COLOR), bg, None);
}
}
}

View File

@ -49,7 +49,7 @@ impl<T: Clone> ScrollingMenu<T> {
pub fn draw(&self, g: &mut GfxCtx) {
let mut txt = Text::new();
txt.add_styled_line(self.prompt.clone(), None, Some(text::PROMPT_COLOR));
txt.add_styled_line(self.prompt.clone(), None, Some(text::PROMPT_COLOR), None);
// TODO Silly results from doing this:
// - The menu width changes as we scroll
@ -59,7 +59,10 @@ impl<T: Clone> ScrollingMenu<T> {
let can_fit = {
// Subtract 1 for the prompt, and an additional TODO hacky
// few to avoid the bottom OSD and stuff.
let n = (g.canvas.window_height / g.canvas.line_height).floor() as isize - 1 - 6;
let n = (g.canvas.window_height / g.canvas.line_height(text::FONT_SIZE)).floor()
as isize
- 1
- 6;
if n <= 0 {
// Weird small window, just display the prompt and bail out.
g.draw_blocking_text(&txt, CENTERED);
@ -84,7 +87,7 @@ impl<T: Clone> ScrollingMenu<T> {
continue;
}
if self.current_idx == idx {
txt.add_styled_line(line.clone(), None, Some(text::SELECTED_COLOR));
txt.add_styled_line(line.clone(), None, Some(text::SELECTED_COLOR), None);
} else {
txt.add_line(line.clone());
}

View File

@ -24,7 +24,7 @@ impl TextBox {
pub fn draw(&self, g: &mut GfxCtx) {
let mut txt = Text::new();
txt.add_styled_line(self.prompt.clone(), None, Some(text::PROMPT_COLOR));
txt.add_styled_line(self.prompt.clone(), None, Some(text::PROMPT_COLOR), None);
txt.add_line(self.line[0..self.cursor_x].to_string());
if self.cursor_x < self.line.len() {

View File

@ -126,7 +126,7 @@ impl TopMenu {
x1: 0.0,
y1: 0.0,
x2: g.canvas.window_width,
y2: g.canvas.line_height,
y2: g.canvas.line_height(text::FONT_SIZE),
});
g.fork_screenspace();
@ -135,7 +135,7 @@ impl TopMenu {
&Polygon::rectangle_topleft(
Pt2D::new(0.0, 0.0),
g.canvas.window_width,
g.canvas.line_height,
g.canvas.line_height(text::FONT_SIZE),
),
);
g.unfork();