Fix all the things

This commit is contained in:
Kenny Levinsen
2019-07-30 16:31:42 +02:00
parent 247286fc5e
commit 9d2dd4ec37
6 changed files with 536 additions and 246 deletions
+45 -234
View File
@@ -5,17 +5,14 @@ extern crate chrono;
extern crate smithay_client_toolkit as sctk;
use std::collections::VecDeque;
use std::io::{Read, Write};
use std::os::unix::io::AsRawFd;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use memmap::MmapMut;
use nix::poll::{poll, PollFd, PollFlags};
use os_pipe::pipe;
use chrono::{Date, DateTime, Datelike, Local, Timelike};
use rusttype::{point, Font, Scale};
use chrono::{Duration as ChronoDuration, Local, Timelike};
use sctk::keyboard::{map_keyboard_auto_with_repeat, Event as KbEvent, KeyRepeatKind};
use sctk::reexports::client::protocol::wl_shm;
@@ -24,9 +21,15 @@ use sctk::utils::DoubleMemPool;
use sctk::window::{ConceptFrame, Event as WEvent, Window};
use sctk::Environment;
static DEJAVUSANS_MONO: &'static [u8] = include_bytes!("../fonts/dejavu/DejaVuSansMono.ttf");
static ROBOTO_REGULAR: &'static [u8] = include_bytes!("../fonts/Roboto-Regular.ttf");
mod color;
mod buffer;
mod draw;
use crate::color::Color;
use crate::buffer::Buffer;
use crate::draw::{draw_clock, draw_calendar};
#[derive(Debug)]
enum Cmd {
Exit,
Configure,
@@ -43,207 +46,6 @@ struct App {
dimensions: (u32, u32),
}
fn draw_text(
font_data: &'static [u8],
mmap: &mut MmapMut,
pos: (u32, u32),
dimensions: (u32, u32),
size: f32,
color: (u8, u8, u8),
s: &str,
) -> Result<(), ::std::io::Error> {
// Load the font
// This only succeeds if collection consists of one font
let font = Font::from_bytes(font_data as &[u8]).expect("Error constructing Font");
// The font size to use
let scale = Scale::uniform(size);
let v_metrics = font.v_metrics(scale);
// layout the glyphs in a line with 20 pixels padding
let glyphs: Vec<_> = font
.layout(s, scale, point(20.0, 20.0 + v_metrics.ascent))
.collect();
// 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() {
// Draw the glyph into the image per-pixel by using the draw closure
glyph.draw(|x, y, o| {
let p = (((pos.1 + y + bounding_box.min.y as u32) * dimensions.0)
+ (pos.0 + x + bounding_box.min.x as u32))
* 4;
let a: u32 = 255 << 24;
let r: u32 = (((color.0 as f32) * o) as u32) << 16;
let g: u32 = (((color.1 as f32) * o) as u32) << 8;
let b: u32 = ((color.2 as f32) * o) as u32;
let v = a | r | g | b;
unsafe {
let ptr = mmap.as_mut_ptr().offset(p as isize);
*(ptr as *mut u32) = v;
}
});
}
}
Ok(())
}
fn draw_clock(
mmap: &mut MmapMut,
time: &DateTime<Local>,
pos: (u32, u32),
dimensions: (u32, u32),
) -> Result<(), ::std::io::Error> {
draw_text(
ROBOTO_REGULAR,
mmap,
pos,
dimensions,
64.0,
(255, 255, 255),
&format!(
"{:?}, {:02}/{:02}/{:4}",
time.weekday(),
time.day(),
time.month(),
time.year()
),
)?;
draw_text(
ROBOTO_REGULAR,
mmap,
(pos.0, pos.1 + 64),
dimensions,
256.0,
(255, 255, 255),
&format!("{:02}", time.hour()),
)?;
draw_text(
ROBOTO_REGULAR,
mmap,
(pos.0 + 256, pos.1 + 64),
dimensions,
256.0,
(255, 255, 255),
":",
)?;
draw_text(
ROBOTO_REGULAR,
mmap,
(pos.0 + 320, pos.1 + 64),
dimensions,
256.0,
(255, 255, 255),
&format!("{:02}", time.minute()),
)?;
Ok(())
}
fn draw_month(
mmap: &mut MmapMut,
orig: &Date<Local>,
time: &Date<Local>,
pos: (u32, u32),
dimensions: (u32, u32),
) -> Result<(), ::std::io::Error> {
let mut time = time.clone();
let mut y_off = 1;
let mut done = false;
let month_str = match time.month() {
1 => "January",
2 => "February",
3 => "March",
4 => "April",
5 => "May",
6 => "June",
7 => "July",
8 => "August",
9 => "September",
10 => "October",
11 => "November",
12 => "December",
_ => panic!("impossible value"),
};
draw_text(
ROBOTO_REGULAR,
mmap,
pos,
dimensions,
68.0,
(255, 255, 255),
month_str,
)?;
while !done {
let mut x_pos = 0;
let mut wk = time.weekday();
while wk != chrono::Weekday::Sun {
x_pos += 1;
wk = wk.pred();
}
while x_pos < 7 {
let c = if time.day() == orig.day() && time.month() == orig.month() {
(255, 255, 255)
} else {
(96, 96, 96)
};
draw_text(
DEJAVUSANS_MONO,
mmap,
(pos.0 + (x_pos * 48), pos.1 + (y_off * 32) + 64),
dimensions,
32.0,
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(())
}
fn draw_calendar(
mmap: &mut MmapMut,
time: &Date<Local>,
pos: (u32, u32),
dimensions: (u32, u32),
) -> Result<(), ::std::io::Error> {
// ~1546x384px
let t = time.with_day(1).unwrap();
draw_month(
mmap,
time,
&t.pred().with_day(1).unwrap(),
(pos.0, pos.1),
dimensions,
)?;
draw_month(mmap, time, &t, (pos.0 + 512, pos.1), dimensions)?;
let n = if t.month() == 12 {
t.with_year(t.year() + 1).unwrap().with_month(1).unwrap()
} else {
t.with_month(t.month() + 1).unwrap()
};
draw_month(mmap, time, &n, (pos.0 + 1024, pos.1), dimensions)?;
Ok(())
}
impl App {
fn redraw(&mut self) -> Result<(), ::std::io::Error> {
let pool = match self.pools.pool() {
@@ -259,19 +61,18 @@ impl App {
.expect("Failed to resize the memory pool.");
let mmap = pool.mmap();
{
unsafe {
let ptr = mmap.as_mut_ptr();
for p in 0..(buf_x * buf_y) {
*((ptr as *mut u32).offset(p as isize)) = 0xC0000000;
}
}
}
let mut buf = Buffer::new(mmap, self.dimensions);
let bg = Color::new(0.0, 0.0, 0.0, 0.8);
buf.memset(&bg);
let time = Local::now();
draw_clock(mmap, &time, (0, 0), (buf_x, buf_y))?;
draw_calendar(mmap, &time.date(), (0, 384), (buf_x, buf_y))?;
draw_clock(&mut buf.subdimensions((0, 0, 720, 320)), &bg, &time)?;
draw_calendar(
&mut buf.subdimensions((0, 384, 1472, 384)),
&bg,
&time.date(),
)?;
mmap.flush().unwrap();
@@ -376,18 +177,32 @@ impl App {
}
fn main() {
let mut app = App::new((1408u32, 734u32));
let (mut rx_pipe, mut tx_pipe) = pipe().unwrap();
let mut app = App::new((1600u32, 784u32));
let mut last_time = Local::now();
let mut tfd = timerfd::TimerFd::new_custom(timerfd::ClockId::Monotonic, true, true).unwrap();
tfd.set_state(
timerfd::TimerState::Periodic {
current: Duration::from_millis(2000),
interval: Duration::from_millis(2000),
},
timerfd::SetTimeFlags::Default,
);
let worker_queue = app.cmd_queue();
std::thread::spawn(move || loop {
let n = Local::now();
let target = (n + ChronoDuration::seconds(60))
.with_second(0)
.unwrap()
.with_nanosecond(0)
.unwrap();
let d = target - n;
std::thread::sleep(d.to_std().unwrap());
worker_queue.lock().unwrap().push_back(Cmd::MaybeDraw);
tx_pipe.write_all(&[0x1]).unwrap();
});
let mut fds = [
PollFd::new(app.event_queue().get_connection_fd(), PollFlags::POLLIN),
PollFd::new(rx_pipe.as_raw_fd(), PollFlags::POLLIN),
];
let q = app.cmd_queue();
loop {
@@ -417,10 +232,6 @@ fn main() {
None => {
app.flush_display();
let mut fds = [
PollFd::new(app.event_queue().get_connection_fd(), PollFlags::POLLIN),
PollFd::new(tfd.as_raw_fd(), PollFlags::POLLIN),
];
poll(&mut fds, -1).unwrap();
if fds[0].revents().unwrap().contains(PollFlags::POLLIN) {
@@ -441,8 +252,8 @@ fn main() {
}
if fds[1].revents().unwrap().contains(PollFlags::POLLIN) {
tfd.read();
q.lock().unwrap().push_back(Cmd::MaybeDraw);
let mut v: Vec<u8> = vec![0x00];
rx_pipe.read_exact(&mut v).unwrap();
}
}
}