Cache all used font glyphs
This commit is contained in:
+5
-4
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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,
|
||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
@@ -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)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user