Cache all used font glyphs

This commit is contained in:
Kenny Levinsen
2019-08-06 14:04:34 +02:00
parent b72c8e9cd9
commit a8c5c59b22
8 changed files with 284 additions and 278 deletions
+5 -4
View File
@@ -1,12 +1,13 @@
use crate::buffer::Buffer; use crate::buffer::Buffer;
use crate::color::Color; use crate::color::Color;
use crate::draw::{draw_bar, draw_box, draw_text, ROBOTO_REGULAR}; use crate::draw::{draw_bar, draw_box, Font, ROBOTO_REGULAR};
use crate::module::{Input, ModuleImpl}; use crate::module::{Input, ModuleImpl};
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::{Error, ErrorKind}; use std::io::{Error, ErrorKind};
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::cell::RefCell;
use chrono::{DateTime, Local}; use chrono::{DateTime, Local};
@@ -14,6 +15,7 @@ pub struct Backlight {
device_path: PathBuf, device_path: PathBuf,
cur_brightness: u64, cur_brightness: u64,
max_brightness: u64, max_brightness: u64,
font: RefCell<Font>,
dirty: bool, dirty: bool,
} }
@@ -85,6 +87,7 @@ impl Backlight {
device_path: first_device.path(), device_path: first_device.path(),
cur_brightness: 0, cur_brightness: 0,
max_brightness: 0, max_brightness: 0,
font: RefCell::new(Font::new(&ROBOTO_REGULAR, 24.0)),
dirty: true, dirty: true,
}; };
@@ -103,12 +106,10 @@ impl ModuleImpl for Backlight {
) -> Result<Vec<(i32, i32, i32, i32)>, Error> { ) -> Result<Vec<(i32, i32, i32, i32)>, Error> {
buf.memset(bg); buf.memset(bg);
let c = Color::new(1.0, 1.0, 1.0, 1.0); let c = Color::new(1.0, 1.0, 1.0, 1.0);
draw_text( self.font.borrow_mut().draw_text(
&ROBOTO_REGULAR,
&mut buf.subdimensions((0, 0, 128, 24))?, &mut buf.subdimensions((0, 0, 128, 24))?,
bg, bg,
&c, &c,
24.0,
"backlight", "backlight",
)?; )?;
draw_bar( draw_bar(
+5 -4
View File
@@ -1,11 +1,12 @@
use crate::buffer::Buffer; use crate::buffer::Buffer;
use crate::color::Color; use crate::color::Color;
use crate::draw::{draw_bar, draw_box, draw_text, ROBOTO_REGULAR}; use crate::draw::{draw_bar, draw_box, Font, ROBOTO_REGULAR};
use crate::module::{Input, ModuleImpl}; use crate::module::{Input, ModuleImpl};
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread; use std::thread;
use std::cell::RefCell;
use chrono::{DateTime, Local}; use chrono::{DateTime, Local};
use dbus; use dbus;
@@ -39,6 +40,7 @@ fn get_upower_property(
pub struct UpowerBattery { pub struct UpowerBattery {
device_path: String, device_path: String,
font: RefCell<Font>,
inner: Arc<Mutex<UpowerBatteryInner>>, inner: Arc<Mutex<UpowerBatteryInner>>,
} }
@@ -116,6 +118,7 @@ impl UpowerBattery {
Ok(UpowerBattery { Ok(UpowerBattery {
device_path, device_path,
font: RefCell::new(Font::new(&ROBOTO_REGULAR, 24.0)),
inner: Arc::new(Mutex::new(UpowerBatteryInner { inner: Arc::new(Mutex::new(UpowerBatteryInner {
capacity: capacity, capacity: capacity,
state: state, state: state,
@@ -195,12 +198,10 @@ impl ModuleImpl for UpowerBattery {
}; };
let inner = self.inner.lock().unwrap(); let inner = self.inner.lock().unwrap();
draw_text( self.font.borrow_mut().draw_text(
&ROBOTO_REGULAR,
&mut buf.subdimensions((0, 0, 128, 24))?, &mut buf.subdimensions((0, 0, 128, 24))?,
bg, bg,
&text_color, &text_color,
24.0,
"battery", "battery",
)?; )?;
draw_bar( draw_bar(
+122 -118
View File
@@ -1,149 +1,149 @@
use crate::buffer::Buffer; use crate::buffer::Buffer;
use crate::color::Color; use crate::color::Color;
use crate::draw::{draw_text, DEJAVUSANS_MONO, ROBOTO_REGULAR}; use crate::draw::{Font, DEJAVUSANS_MONO, ROBOTO_REGULAR};
use crate::module::{Input, ModuleImpl}; use crate::module::{Input, ModuleImpl};
use std::cell::RefCell;
use chrono::{Date, DateTime, Datelike, Local}; use chrono::{Date, DateTime, Datelike, Local};
pub struct Calendar { pub struct Calendar {
cur_date: Date<Local>, cur_date: Date<Local>,
dirty: bool, dirty: bool,
offset: f64, offset: f64,
calendar_numeral_cache: RefCell<Font>,
month_cache: RefCell<Font>,
year_cache: RefCell<Font>,
day_cache: RefCell<Font>,
} }
fn draw_month( impl Calendar {
buf: &mut Buffer, fn draw_month(
background_color: &Color, &self,
orig: &Date<Local>, buf: &mut Buffer,
time: &Date<Local>, background_color: &Color,
) -> Result<(i32, i32, i32, i32), ::std::io::Error> { orig: &Date<Local>,
let mut time = time.clone(); time: &Date<Local>,
let mut y_off = 1; ) -> Result<(i32, i32, i32, i32), ::std::io::Error> {
let mut done = false; let mut time = time.clone();
let mut y_off = 1;
let mut done = false;
let month_str = match time.month() { let month_str = match time.month() {
1 => "January", 1 => "January",
2 => "February", 2 => "February",
3 => "March", 3 => "March",
4 => "April", 4 => "April",
5 => "May", 5 => "May",
6 => "June", 6 => "June",
7 => "July", 7 => "July",
8 => "August", 8 => "August",
9 => "September", 9 => "September",
10 => "October", 10 => "October",
11 => "November", 11 => "November",
12 => "December", 12 => "December",
_ => panic!("impossible value"),
};
//
// Draw the of the month
//
draw_text(
&ROBOTO_REGULAR,
&mut buf.subdimensions((0, 0, 304, 72))?,
background_color,
&Color::new(1.0, 1.0, 1.0, 1.0),
64.0,
month_str,
)?;
if time.year() != orig.year() {
draw_text(
&ROBOTO_REGULAR,
&mut buf.subdimensions((320, 0, 64, 32))?,
background_color,
&Color::new(0.8, 0.8, 0.8, 1.0),
24.0,
&format!("{:}", time.year()),
)?;
}
//
// Draw the week day
//
for idx in 1..8 {
let wk_chr = match idx {
1 => "MON",
2 => "TUE",
3 => "WED",
4 => "THU",
5 => "FRI",
6 => "SAT",
7 => "SUN",
_ => panic!("impossible value"), _ => panic!("impossible value"),
}; };
draw_text( //
&DEJAVUSANS_MONO, // Draw the of the month
&mut buf.subdimensions((idx * 48 + 4, (y_off * 32) + 64, 32, 16))?, //
self.month_cache.borrow_mut().draw_text(
&mut buf.subdimensions((0, 0, 304, 72))?,
background_color, background_color,
&Color::new(1.0, 1.0, 1.0, 1.0), &Color::new(1.0, 1.0, 1.0, 1.0),
16.0, month_str,
&wk_chr,
)?; )?;
} if time.year() != orig.year() {
self.year_cache.borrow_mut().draw_text(
y_off += 1; &mut buf.subdimensions((320, 0, 64, 32))?,
background_color,
while !done { &Color::new(0.8, 0.8, 0.8, 1.0),
let mut x_pos = 0; &format!("{:}", time.year()),
)?;
//
// Find the start of this week
//
let mut wkday = time.weekday();
while wkday != chrono::Weekday::Mon {
x_pos += 1;
wkday = wkday.pred();
} }
// //
// Draw the week number // Draw the week day
// //
let wk = time.iso_week();
draw_text(
&DEJAVUSANS_MONO,
&mut buf.subdimensions((0 * 48, (y_off * 32) + 64, 38, 32))?,
background_color,
&Color::new(0.75, 0.75, 0.75, 1.0),
32.0,
&format!("{:02}", wk.week()),
)?;
x_pos += 1;
// for idx in 1..8 {
// Draw the dates let wk_chr = match idx {
// 1 => "MON",
while x_pos < 8 { 2 => "TUE",
let c = if time.day() == orig.day() && time.month() == orig.month() { 3 => "WED",
Color::new(1.0, 1.0, 1.0, 1.0) 4 => "THU",
} else { 5 => "FRI",
Color::new(0.5, 0.5, 0.5, 1.0) 6 => "SAT",
7 => "SUN",
_ => panic!("impossible value"),
}; };
draw_text(
&DEJAVUSANS_MONO, self.day_cache.borrow_mut().draw_text(
&mut buf.subdimensions((x_pos * 48, (y_off * 32) + 64, 38, 32))?, &mut buf.subdimensions((idx * 48 + 4, (y_off * 32) + 64, 32, 16))?,
background_color, background_color,
&c, &Color::new(1.0, 1.0, 1.0, 1.0),
32.0, &wk_chr,
&format!("{:02}", time.day()),
)?; )?;
let t = time.with_day(time.day() + 1);
if t.is_none() {
done = true;
break;
}
time = t.unwrap();
x_pos += 1;
} }
y_off += 1; y_off += 1;
}
Ok(buf.get_signed_bounds()) while !done {
let mut x_pos = 0;
//
// Find the start of this week
//
let mut wkday = time.weekday();
while wkday != chrono::Weekday::Mon {
x_pos += 1;
wkday = wkday.pred();
}
//
// Draw the week number
//
let wk = time.iso_week();
self.calendar_numeral_cache.borrow_mut().draw_text(
&mut buf.subdimensions((0 * 48, (y_off * 32) + 64, 38, 32))?,
background_color,
&Color::new(0.75, 0.75, 0.75, 1.0),
&format!("{:02}", wk.week()),
)?;
x_pos += 1;
//
// Draw the dates
//
while x_pos < 8 {
let c = if time.day() == orig.day() && time.month() == orig.month() {
Color::new(1.0, 1.0, 1.0, 1.0)
} else {
Color::new(0.5, 0.5, 0.5, 1.0)
};
self.calendar_numeral_cache.borrow_mut().draw_text(
&mut buf.subdimensions((x_pos * 48, (y_off * 32) + 64, 38, 32))?,
background_color,
&c,
&format!("{:02}", time.day()),
)?;
let t = time.with_day(time.day() + 1);
if t.is_none() {
done = true;
break;
}
time = t.unwrap();
x_pos += 1;
}
y_off += 1;
}
Ok(buf.get_signed_bounds())
}
} }
impl Calendar { impl Calendar {
@@ -152,6 +152,10 @@ impl Calendar {
cur_date: Local::now().date(), cur_date: Local::now().date(),
dirty: true, dirty: true,
offset: 0.0, offset: 0.0,
calendar_numeral_cache: RefCell::new(Font::new(&DEJAVUSANS_MONO, 32.0)),
month_cache: RefCell::new(Font::new(&ROBOTO_REGULAR, 64.0)),
year_cache: RefCell::new(Font::new(&DEJAVUSANS_MONO, 24.0)),
day_cache: RefCell::new(Font::new(&DEJAVUSANS_MONO, 16.0)),
} }
} }
} }
@@ -184,13 +188,13 @@ impl ModuleImpl for Calendar {
.with_month((month + 1) as u32) .with_month((month + 1) as u32)
.unwrap(); .unwrap();
} }
draw_month( self.draw_month(
&mut buf.subdimensions((0, 0, 384, 344))?, &mut buf.subdimensions((0, 0, 384, 344))?,
background_color, background_color,
&time, &time,
&t.pred().with_day(1).unwrap(), &t.pred().with_day(1).unwrap(),
)?; )?;
draw_month( self.draw_month(
&mut buf.subdimensions((448, 0, 384, 344))?, &mut buf.subdimensions((448, 0, 384, 344))?,
background_color, background_color,
&time, &time,
@@ -201,7 +205,7 @@ impl ModuleImpl for Calendar {
} else { } else {
t.with_month(t.month() + 1).unwrap() t.with_month(t.month() + 1).unwrap()
}; };
draw_month( self.draw_month(
&mut buf.subdimensions((896, 0, 384, 344))?, &mut buf.subdimensions((896, 0, 384, 344))?,
background_color, background_color,
&time, &time,
+8 -7
View File
@@ -1,8 +1,9 @@
use crate::buffer::Buffer; use crate::buffer::Buffer;
use crate::color::Color; use crate::color::Color;
use crate::draw::{draw_text, draw_text_fixed_width, ROBOTO_REGULAR}; use crate::draw::{Font, ROBOTO_REGULAR};
use crate::module::{Input, ModuleImpl}; use crate::module::{Input, ModuleImpl};
use std::cell::RefCell;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use chrono::{DateTime, Datelike, Duration, Local, Timelike}; use chrono::{DateTime, Datelike, Duration, Local, Timelike};
@@ -10,6 +11,8 @@ use chrono::{DateTime, Datelike, Duration, Local, Timelike};
pub struct Clock { pub struct Clock {
cur_time: DateTime<Local>, cur_time: DateTime<Local>,
first_draw: bool, first_draw: bool,
clock_cache: RefCell<Font>,
date_cache: RefCell<Font>,
} }
impl Clock { impl Clock {
@@ -31,6 +34,8 @@ impl Clock {
Clock { Clock {
cur_time: Local::now(), cur_time: Local::now(),
first_draw: true, first_draw: true,
date_cache: RefCell::new(Font::new(&ROBOTO_REGULAR, 64.0)),
clock_cache: RefCell::new(Font::new(&ROBOTO_REGULAR, 256.0)),
} }
} }
} }
@@ -44,12 +49,10 @@ impl ModuleImpl for Clock {
) -> Result<Vec<(i32, i32, i32, i32)>, ::std::io::Error> { ) -> Result<Vec<(i32, i32, i32, i32)>, ::std::io::Error> {
buf.memset(bg); buf.memset(bg);
draw_text( self.date_cache.borrow_mut().draw_text(
&ROBOTO_REGULAR,
&mut buf.subdimensions((0, 0, 448, 64))?, &mut buf.subdimensions((0, 0, 448, 64))?,
bg, bg,
&Color::new(1.0, 1.0, 1.0, 1.0), &Color::new(1.0, 1.0, 1.0, 1.0),
64.0,
&format!( &format!(
"{:?}, {:02}/{:02}/{:4}", "{:?}, {:02}/{:02}/{:4}",
time.weekday(), time.weekday(),
@@ -59,12 +62,10 @@ impl ModuleImpl for Clock {
), ),
)?; )?;
draw_text_fixed_width( self.clock_cache.borrow_mut().draw_text_fixed_width(
&ROBOTO_REGULAR,
&mut buf.subdimensions((0, 64, 288 * 2 + 64, 256))?, &mut buf.subdimensions((0, 64, 288 * 2 + 64, 256))?,
bg, bg,
&Color::new(1.0, 1.0, 1.0, 1.0), &Color::new(1.0, 1.0, 1.0, 1.0),
256.0,
&[120, 120, 64, 120, 120], &[120, 120, 64, 120, 120],
&format!("{:02}:{:02}", time.hour(), time.minute()), &format!("{:02}:{:02}", time.hour(), time.minute()),
)?; )?;
+131 -130
View File
@@ -1,163 +1,164 @@
use crate::buffer::Buffer; use crate::buffer::Buffer;
use crate::color::Color; use crate::color::Color;
use rusttype::{point, Font, Scale};
use std::collections::HashMap;
use rusttype::{point, Font as RustFont, Scale};
use lazy_static::lazy_static; use lazy_static::lazy_static;
pub static DEJAVUSANS_MONO_FONT_DATA: &'static [u8] = include_bytes!("../fonts/dejavu/DejaVuSansMono.ttf"); pub static DEJAVUSANS_MONO_FONT_DATA: &'static [u8] = include_bytes!("../fonts/dejavu/DejaVuSansMono.ttf");
pub static ROBOTO_REGULAR_FONT_DATA: &'static [u8] = include_bytes!("../fonts/Roboto-Regular.ttf"); pub static ROBOTO_REGULAR_FONT_DATA: &'static [u8] = include_bytes!("../fonts/Roboto-Regular.ttf");
lazy_static! { lazy_static! {
pub static ref DEJAVUSANS_MONO: Font<'static> = Font::from_bytes(DEJAVUSANS_MONO_FONT_DATA as &[u8]).expect("error constructing DejaVuSansMono"); pub static ref DEJAVUSANS_MONO: RustFont<'static> = RustFont::from_bytes(DEJAVUSANS_MONO_FONT_DATA as &[u8]).expect("error constructing DejaVuSansMono");
pub static ref ROBOTO_REGULAR: Font<'static> = Font::from_bytes(ROBOTO_REGULAR_FONT_DATA as &[u8]).expect("error constructing Roboto-Regular"); pub static ref ROBOTO_REGULAR: RustFont<'static> = RustFont::from_bytes(ROBOTO_REGULAR_FONT_DATA as &[u8]).expect("error constructing Roboto-Regular");
} }
pub fn draw_text( struct CachedGlyph {
font: &Font, dimensions: (u32, u32),
buf: &mut Buffer, origin: (i32, i32),
background_color: &Color, render: Vec<f32>,
color: &Color, }
size: f32,
s: &str,
) -> Result<(u32, u32), ::std::io::Error> {
// The font size to use impl CachedGlyph {
let scale = Scale::uniform(size); fn new(font: &RustFont, size: f32, ch: char) -> CachedGlyph {
let scale = Scale::uniform(size);
let v_metrics = font.v_metrics(scale);
let glyph = font
.glyph(ch)
.scaled(scale)
.positioned(point(0.0, v_metrics.ascent));
let v_metrics = font.v_metrics(scale);
let glyphs: Vec<_> = font
.layout(s, scale, point(0.0, v_metrics.ascent))
.collect();
let mut x_max: u32 = 0;
let mut y_max: u32 = 0;
// Loop through the glyphs in the text, positing each one on a line
for glyph in glyphs {
if let Some(bounding_box) = glyph.pixel_bounding_box() { if let Some(bounding_box) = glyph.pixel_bounding_box() {
if bounding_box.max.x > x_max as i32 { let origin = (bounding_box.min.x, bounding_box.min.y);
x_max = bounding_box.max.x as u32;
} let dimensions = ((bounding_box.max.x - bounding_box.min.x) as u32, (bounding_box.max.y - bounding_box.min.y) as u32);
if bounding_box.max.y > y_max as i32 { let mut render = vec![0.0; (dimensions.0 * dimensions.1) as usize];
y_max = bounding_box.max.y as u32;
}
// Draw the glyph into the image per-pixel by using the draw closure
glyph.draw(|x, y, o| { glyph.draw(|x, y, o| {
let x = x + bounding_box.min.x as u32; let pos = x + (y * dimensions.0);
let y = y + bounding_box.min.y as u32; render[pos as usize] = o;
let o = if o > 1.0 {
1.0
} else if o < 0.0 {
0.0
} else {
o
};
let _ = buf.put((x, y), &background_color.blend(color, o));
}); });
CachedGlyph{
origin: origin,
dimensions: dimensions,
render: render,
}
} else {
CachedGlyph{
origin: (0,0),
dimensions: ((size/4.0) as u32, 0),
render: Vec::new(),
}
} }
} }
Ok((x_max, y_max)) fn draw(&self, buf: &mut Buffer, pos: (i32, i32), bg: &Color, c: &Color) {
} let mut x = 0;
let mut y = 0;
for v in &self.render {
buf.put(((x + pos.0 + self.origin.0) as u32, (y + pos.1 + self.origin.1) as u32), &bg.blend(&c, *v)).unwrap();
pub fn draw_text_individual_colors( if x == self.dimensions.0 as i32 -1 {
font: &Font, y += 1;
buf: &mut Buffer, x = 0;
background_color: &Color, } else {
color: &[Color], x += 1;
size: f32,
s: &str,
) -> Result<(u32, u32), ::std::io::Error> {
// The font size to use
let scale = Scale::uniform(size);
let v_metrics = font.v_metrics(scale);
let glyphs: Vec<_> = font
.layout(s, scale, point(0.0, v_metrics.ascent))
.collect();
let mut x_max: u32 = 0;
let mut y_max: u32 = 0;
let mut x_pos: usize = 0;
// Loop through the glyphs in the text, positing each one on a line
for glyph in glyphs {
if let Some(bounding_box) = glyph.pixel_bounding_box() {
if bounding_box.max.x > x_max as i32 {
x_max = bounding_box.max.x as u32;
} }
if bounding_box.max.y > y_max as i32 {
y_max = bounding_box.max.y as u32;
}
// Draw the glyph into the image per-pixel by using the draw closure
glyph.draw(|x, y, o| {
let x = x + bounding_box.min.x as u32;
let y = y + bounding_box.min.y as u32;
let o = if o > 1.0 {
1.0
} else if o < 0.0 {
0.0
} else {
o
};
let _ = buf.put((x, y), &background_color.blend(&color[x_pos], o));
});
} }
x_pos += 1;
}
Ok((x_max, y_max)) }
} }
pub fn draw_text_fixed_width( pub struct Font {
font: &Font, glyphs: HashMap<char, CachedGlyph>,
buf: &mut Buffer, font: &'static RustFont<'static>,
background_color: &Color,
color: &Color,
size: f32, size: f32,
distances: &[u32], }
s: &str,
) -> Result<(), ::std::io::Error> {
// The font size to use impl Font {
let scale = Scale::uniform(size); pub fn new(font: &'static RustFont, size: f32) -> Font {
Font{
let v_metrics = font.v_metrics(scale); glyphs: HashMap::new(),
font: font,
let glyphs: Vec<_> = font size: size,
.layout(s, scale, point(0.0, v_metrics.ascent))
.collect();
// Loop through the glyphs in the text, positing each one on a line
let mut x_pos: usize = 0;
let mut x_off: u32 = 0;
for glyph in glyphs {
if let Some(bounding_box) = glyph.pixel_bounding_box() {
let x_dist = distances[x_pos];
let width = (bounding_box.max.x - bounding_box.min.x) as u32;
let offset = (x_dist - width) / 2;
// Draw the glyph into the image per-pixel by using the draw closure
glyph.draw(|x, y, o| {
let off = x_off + offset + 20;
let x = x + off as u32;
let y = y + bounding_box.min.y as u32;
let o = if o > 1.0 {
1.0
} else if o < 0.0 {
0.0
} else {
o
};
let _ = buf.put((x, y), &background_color.blend(color, o));
});
x_pos += 1;
x_off += x_dist;
} }
} }
Ok(()) pub fn draw_text(&mut self, buf: &mut Buffer, bg: &Color, c: &Color, s: &str) -> Result<(u32, u32), ::std::io::Error> {
let mut x_off = 0;
let mut off = 0;
for ch in s.chars() {
let glyph = match self.glyphs.get(&ch) {
Some(glyph) => glyph,
None => {
let glyph = CachedGlyph::new(self.font, self.size, ch);
self.glyphs.insert(ch, glyph);
self.glyphs.get(&ch).unwrap()
}
};
if glyph.origin.1 < off {
off = glyph.origin.1
}
}
for ch in s.chars() {
let glyph = &self.glyphs[&ch];
glyph.draw(buf, (x_off, -off), bg, c);
x_off += glyph.dimensions.0 as i32 + glyph.origin.0;
}
Ok((x_off as u32, self.size as u32))
}
pub fn draw_text_fixed_width(&mut self, buf: &mut Buffer, bg: &Color, c: &Color, distances: &[u32], s: &str) -> Result<(u32, u32), ::std::io::Error> {
let mut x_off = 0;
let mut off = 0;
for ch in s.chars() {
let glyph = match self.glyphs.get(&ch) {
Some(glyph) => glyph,
None => {
let glyph = CachedGlyph::new(self.font, self.size, ch);
self.glyphs.insert(ch, glyph);
self.glyphs.get(&ch).unwrap()
}
};
if glyph.origin.1 < off {
off = glyph.origin.1
}
}
for (idx, ch) in s.chars().enumerate() {
let glyph = &self.glyphs[&ch];
glyph.draw(buf, (x_off, -off), bg, c);
x_off += distances[idx] as i32;
}
Ok((x_off as u32, self.size as u32))
}
pub fn draw_text_individual_colors(&mut self, buf: &mut Buffer, bg: &Color, color: &[Color], s: &str) -> Result<(u32, u32), ::std::io::Error> {
let mut x_off = 0;
let mut off = 0;
for ch in s.chars() {
let glyph = match self.glyphs.get(&ch) {
Some(glyph) => glyph,
None => {
let glyph = CachedGlyph::new(self.font, self.size, ch);
self.glyphs.insert(ch, glyph);
self.glyphs.get(&ch).unwrap()
}
};
if glyph.origin.1 < off {
off = glyph.origin.1
}
}
for (idx, ch) in s.chars().enumerate() {
let glyph = &self.glyphs[&ch];
glyph.draw(buf, (x_off, -off), bg, &color[idx]);
x_off += glyph.dimensions.0 as i32 + glyph.origin.0;
}
Ok((x_off as u32, self.size as u32))
}
} }
pub fn draw_box(buf: &mut Buffer, c: &Color, dim: (u32, u32)) -> Result<(), ::std::io::Error> { pub fn draw_box(buf: &mut Buffer, c: &Color, dim: (u32, u32)) -> Result<(), ::std::io::Error> {
+8 -11
View File
@@ -1,10 +1,11 @@
use crate::buffer::Buffer; use crate::buffer::Buffer;
use crate::color::Color; use crate::color::Color;
use crate::draw::{draw_text, draw_text_individual_colors, ROBOTO_REGULAR}; use crate::draw::{Font, ROBOTO_REGULAR};
use crate::module::{Input, ModuleImpl}; use crate::module::{Input, ModuleImpl};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::io::Read; use std::io::Read;
use std::cell::RefCell;
use atty::Stream; use atty::Stream;
use chrono::{DateTime, Local}; use chrono::{DateTime, Local};
@@ -16,6 +17,7 @@ pub struct Launcher {
matches: Vec<String>, matches: Vec<String>,
cur: String, cur: String,
offset: usize, offset: usize,
font: RefCell<Font>,
dirty: bool, dirty: bool,
} }
@@ -35,6 +37,7 @@ impl Launcher {
matches: vec![], matches: vec![],
cur: "".to_string(), cur: "".to_string(),
offset: 0, offset: 0,
font: RefCell::new(Font::new(&ROBOTO_REGULAR, 32.0)),
dirty: true, dirty: true,
}) })
} else { } else {
@@ -55,26 +58,22 @@ impl ModuleImpl for Launcher {
) -> Result<Vec<(i32, i32, i32, i32)>, ::std::io::Error> { ) -> Result<Vec<(i32, i32, i32, i32)>, ::std::io::Error> {
buf.memset(bg); buf.memset(bg);
draw_text( self.font.borrow_mut().draw_text(
&ROBOTO_REGULAR,
&mut buf.subdimensions((0, 0, 128, 32))?, &mut buf.subdimensions((0, 0, 128, 32))?,
bg, bg,
&Color::new(0.75, 0.75, 0.75, 1.0), &Color::new(0.75, 0.75, 0.75, 1.0),
32.0,
"Run: ", "Run: ",
)?; )?;
let mut x_off: i32 = 0; let mut x_off: i32 = 0;
let mut width_remaining: i32 = 1280 - 64; let mut width_remaining: i32 = 1280 - 64;
if self.matches.len() == 0 && self.cur.len() > 0 { if self.matches.len() == 0 && self.cur.len() > 0 {
draw_text( self.font.borrow_mut().draw_text(
&ROBOTO_REGULAR,
&mut buf &mut buf
.subdimensions((64, 0, width_remaining as u32, 32)) .subdimensions((64, 0, width_remaining as u32, 32))
.unwrap(), .unwrap(),
bg, bg,
&Color::new(1.0, 0.5, 0.5, 1.0), &Color::new(1.0, 0.5, 0.5, 1.0),
32.0,
&self.cur, &self.cur,
)?; )?;
} else { } else {
@@ -95,14 +94,12 @@ impl ModuleImpl for Launcher {
colors.push(Color::new(0.75, 0.75, 0.75, 1.0)); colors.push(Color::new(0.75, 0.75, 0.75, 1.0));
} }
} }
draw_text_individual_colors(&ROBOTO_REGULAR, &mut b, bg, &colors, 32.0, &m)? self.font.borrow_mut().draw_text_individual_colors(&mut b, bg, &colors, &m)?
} else { } else {
draw_text( self.font.borrow_mut().draw_text(
&ROBOTO_REGULAR,
&mut b, &mut b,
bg, bg,
&Color::new(0.5, 0.5, 0.5, 1.0), &Color::new(0.5, 0.5, 0.5, 1.0),
32.0,
m, m,
)? )?
}; };
+1
View File
@@ -4,6 +4,7 @@ use std::io::{Read, Write};
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::sync::mpsc::{channel, Sender}; use std::sync::mpsc::{channel, Sender};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Instant;
use nix::poll::{poll, PollFd, PollFlags}; use nix::poll::{poll, PollFd, PollFlags};
use os_pipe::pipe; use os_pipe::pipe;
+4 -4
View File
@@ -1,6 +1,6 @@
use crate::buffer::Buffer; use crate::buffer::Buffer;
use crate::color::Color; use crate::color::Color;
use crate::draw::{draw_bar, draw_box, draw_text, ROBOTO_REGULAR}; use crate::draw::{draw_bar, draw_box, Font, ROBOTO_REGULAR};
use crate::module::{Input, ModuleImpl}; use crate::module::{Input, ModuleImpl};
use std::cell::RefCell; use std::cell::RefCell;
@@ -399,6 +399,7 @@ impl PulseAudioSoundDevice {
pub struct PulseAudio { pub struct PulseAudio {
device: Arc<Mutex<PulseAudioSoundDevice>>, device: Arc<Mutex<PulseAudioSoundDevice>>,
font: RefCell<Font>,
dirty: Arc<Mutex<bool>>, dirty: Arc<Mutex<bool>>,
} }
@@ -407,6 +408,7 @@ impl PulseAudio {
let (tx, rx) = channel(); let (tx, rx) = channel();
let pa = PulseAudio { let pa = PulseAudio {
device: PulseAudioSoundDevice::new(tx)?, device: PulseAudioSoundDevice::new(tx)?,
font: RefCell::new(Font::new(&ROBOTO_REGULAR, 24.0)),
dirty: Arc::new(Mutex::new(true)), dirty: Arc::new(Mutex::new(true)),
}; };
let device = pa.device.clone(); let device = pa.device.clone();
@@ -436,12 +438,10 @@ impl ModuleImpl for PulseAudio {
} else { } else {
Color::new(1.0, 1.0, 1.0, 1.0) Color::new(1.0, 1.0, 1.0, 1.0)
}; };
draw_text( self.font.borrow_mut().draw_text(
&ROBOTO_REGULAR,
&mut buf.subdimensions((0, 0, 128, 24))?, &mut buf.subdimensions((0, 0, 128, 24))?,
bg, bg,
&Color::new(1.0, 1.0, 1.0, 1.0), &Color::new(1.0, 1.0, 1.0, 1.0),
24.0,
"volume", "volume",
)?; )?;
draw_bar(&mut buf.subdimensions((128, 0, 432, 24))?, &c, 432, 24, vol)?; draw_bar(&mut buf.subdimensions((128, 0, 432, 24))?, &c, 432, 24, vol)?;