Fix all the things
This commit is contained in:
+104
@@ -0,0 +1,104 @@
|
||||
use memmap::MmapMut;
|
||||
|
||||
use crate::color::Color;
|
||||
|
||||
pub struct Buffer<'a> {
|
||||
buf: &'a mut MmapMut,
|
||||
dimensions: (u32, u32),
|
||||
subdimensions: Option<(u32, u32, u32, u32)>,
|
||||
}
|
||||
|
||||
impl<'a> Buffer<'a> {
|
||||
pub fn new(buf: &'a mut MmapMut, dimensions: (u32, u32)) -> Buffer {
|
||||
Buffer {
|
||||
buf: buf,
|
||||
dimensions: dimensions,
|
||||
subdimensions: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_bounds(&self) -> (u32, u32, u32, u32) {
|
||||
if let Some(subdim) = self.subdimensions {
|
||||
subdim
|
||||
} else {
|
||||
(0, 0, self.dimensions.0, self.dimensions.1)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn subdimensions(&mut self, subdimensions: (u32, u32, u32, u32)) -> Buffer {
|
||||
let bounds = self.get_bounds();
|
||||
if subdimensions.0 + subdimensions.2 > bounds.2
|
||||
|| subdimensions.1 + subdimensions.3 > bounds.3
|
||||
{
|
||||
panic!(
|
||||
"cannot create subdimensions larger than buffer: {:?} > {:?}",
|
||||
subdimensions, bounds
|
||||
);
|
||||
}
|
||||
|
||||
Buffer {
|
||||
buf: self.buf,
|
||||
dimensions: self.dimensions,
|
||||
subdimensions: Some((
|
||||
subdimensions.0 + bounds.0,
|
||||
subdimensions.1 + bounds.1,
|
||||
subdimensions.2,
|
||||
subdimensions.3,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn memset(&mut self, c: &Color) {
|
||||
unsafe {
|
||||
let ptr = self.buf.as_mut_ptr();
|
||||
for p in 0..(self.dimensions.0 * self.dimensions.1) {
|
||||
*((ptr as *mut u32).offset(p as isize)) = c.as_argb8888();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn highlight_bounds(&mut self, c: &Color) {
|
||||
let end = if let Some(subdim) = self.subdimensions {
|
||||
(subdim.2, subdim.3)
|
||||
} else {
|
||||
(self.dimensions.0, self.dimensions.1)
|
||||
};
|
||||
|
||||
for x in 0..end.0 {
|
||||
self.put((x, 0), c);
|
||||
self.put((x, end.1 - 1), c);
|
||||
}
|
||||
for y in 0..end.1 {
|
||||
self.put((0, y), c);
|
||||
self.put((end.0 - 1, y), c);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn put(&mut self, pos: (u32, u32), c: &Color) {
|
||||
let true_pos = if let Some(subdim) = self.subdimensions {
|
||||
if pos.0 > subdim.2 || pos.1 > subdim.3 {
|
||||
panic!(
|
||||
"put({:?}) is not within subdimensions of buffer ({:?})",
|
||||
pos, subdim
|
||||
);
|
||||
}
|
||||
(pos.0 + subdim.0, pos.1 + subdim.1)
|
||||
} else {
|
||||
if pos.0 >= self.dimensions.0 || pos.1 >= self.dimensions.1 {
|
||||
panic!(
|
||||
"put({:?}) is not within dimensions of buffer ({:?})",
|
||||
pos, self.dimensions
|
||||
);
|
||||
}
|
||||
pos
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let ptr = self
|
||||
.buf
|
||||
.as_mut_ptr()
|
||||
.offset(4 * (true_pos.0 + (true_pos.1 * self.dimensions.0)) as isize);
|
||||
*(ptr as *mut u32) = c.as_argb8888();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#[derive(Debug)]
|
||||
pub struct Color {
|
||||
red: f32,
|
||||
green: f32,
|
||||
blue: f32,
|
||||
opacity: f32,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
pub fn new(red: f32, green: f32, blue: f32, opacity: f32) -> Color {
|
||||
Color {
|
||||
red: if red > 1.0 {
|
||||
1.0
|
||||
} else if red < 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
red
|
||||
},
|
||||
green: if green > 1.0 {
|
||||
1.0
|
||||
} else if green < 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
green
|
||||
},
|
||||
blue: if blue > 1.0 {
|
||||
1.0
|
||||
} else if blue < 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
blue
|
||||
},
|
||||
opacity: if opacity > 1.0 {
|
||||
1.0
|
||||
} else if opacity < 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
opacity
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn blend(&self, other: &Color, ratio: f32) -> Color {
|
||||
let ratio = if ratio > 1.0 {
|
||||
1.0
|
||||
} else if ratio < 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
ratio
|
||||
};
|
||||
|
||||
Color {
|
||||
red: self.red + ((other.red - self.red) * ratio),
|
||||
green: self.green + ((other.green - self.green) * ratio),
|
||||
blue: self.blue + ((other.blue - self.blue) * ratio),
|
||||
opacity: self.opacity + ((other.opacity - self.opacity) * ratio),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_argb8888(&self) -> u32 {
|
||||
((255.0 * self.opacity) as u32) << 24
|
||||
| ((255.0 * self.red) as u32) << 16
|
||||
| ((255.0 * self.green) as u32) << 8
|
||||
| ((255.0 * self.red) as u32)
|
||||
}
|
||||
}
|
||||
+295
@@ -0,0 +1,295 @@
|
||||
use crate::color::Color;
|
||||
use crate::buffer::Buffer;
|
||||
use rusttype::{point, Font, Scale};
|
||||
use chrono::{Date, DateTime, Datelike, Local, Timelike};
|
||||
|
||||
static DEJAVUSANS_MONO: &'static [u8] = include_bytes!("../fonts/dejavu/DejaVuSansMono.ttf");
|
||||
static ROBOTO_REGULAR: &'static [u8] = include_bytes!("../fonts/Roboto-Regular.ttf");
|
||||
|
||||
fn draw_text(
|
||||
font_data: &'static [u8],
|
||||
buf: &mut Buffer,
|
||||
background_color: &Color,
|
||||
color: &Color,
|
||||
size: f32,
|
||||
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 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
|
||||
};
|
||||
buf.put((x, y), &background_color.blend(color, o));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_text_fixed_width(
|
||||
font_data: &'static [u8],
|
||||
buf: &mut Buffer,
|
||||
background_color: &Color,
|
||||
color: &Color,
|
||||
size: f32,
|
||||
distances: Vec<u32>,
|
||||
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
|
||||
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
|
||||
};
|
||||
buf.put((x, y), &background_color.blend(color, o));
|
||||
});
|
||||
x_pos += 1;
|
||||
x_off += x_dist;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn draw_clock(
|
||||
buf: &mut Buffer,
|
||||
background_color: &Color,
|
||||
time: &DateTime<Local>,
|
||||
) -> Result<(), ::std::io::Error> {
|
||||
draw_text(
|
||||
ROBOTO_REGULAR,
|
||||
&mut buf.subdimensions((0, 0, 448, 96)),
|
||||
background_color,
|
||||
&Color::new(1.0, 1.0, 1.0, 1.0),
|
||||
64.0,
|
||||
&format!(
|
||||
"{:?}, {:02}/{:02}/{:4}",
|
||||
time.weekday(),
|
||||
time.day(),
|
||||
time.month(),
|
||||
time.year()
|
||||
),
|
||||
)?;
|
||||
|
||||
draw_text_fixed_width(
|
||||
ROBOTO_REGULAR,
|
||||
&mut buf.subdimensions((0, 64, 288*2+64, 256)),
|
||||
background_color,
|
||||
&Color::new(1.0, 1.0, 1.0, 1.0),
|
||||
256.0,
|
||||
vec![120, 120, 64, 120, 120],
|
||||
&format!("{:02}:{:02}", time.hour(), time.minute()),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_month(
|
||||
buf: &mut Buffer,
|
||||
background_color: &Color,
|
||||
orig: &Date<Local>,
|
||||
time: &Date<Local>,
|
||||
) -> 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 the of the month
|
||||
//
|
||||
|
||||
draw_text(
|
||||
ROBOTO_REGULAR,
|
||||
&mut buf.subdimensions((0, 0, 364, 96)),
|
||||
background_color,
|
||||
&Color::new(1.0, 1.0, 1.0, 1.0),
|
||||
68.0,
|
||||
month_str,
|
||||
)?;
|
||||
|
||||
//
|
||||
// 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 => "SUN",
|
||||
7 => "SAT",
|
||||
_ => panic!("impossible value"),
|
||||
};
|
||||
|
||||
draw_text(
|
||||
DEJAVUSANS_MONO,
|
||||
&mut buf.subdimensions((idx * 48 + 4, (y_off * 32) + 64, 64, 64)),
|
||||
background_color,
|
||||
&Color::new(0.75, 0.75, 0.75, 1.0),
|
||||
16.0,
|
||||
&wk_chr,
|
||||
)?;
|
||||
}
|
||||
|
||||
y_off += 1;
|
||||
|
||||
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();
|
||||
draw_text(
|
||||
DEJAVUSANS_MONO,
|
||||
&mut buf.subdimensions((0 * 48, (y_off * 32) + 64, 64, 64)),
|
||||
background_color,
|
||||
&Color::new(0.75, 0.75, 0.75, 1.0),
|
||||
32.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)
|
||||
};
|
||||
draw_text(
|
||||
DEJAVUSANS_MONO,
|
||||
&mut buf.subdimensions((x_pos * 48, (y_off * 32) + 64, 64, 64)),
|
||||
background_color,
|
||||
&c,
|
||||
32.0,
|
||||
&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(())
|
||||
}
|
||||
|
||||
pub fn draw_calendar(
|
||||
buf: &mut Buffer,
|
||||
background_color: &Color,
|
||||
time: &Date<Local>,
|
||||
) -> Result<(), ::std::io::Error> {
|
||||
// ~1546x384px
|
||||
let t = time.with_day(1).unwrap();
|
||||
draw_month(
|
||||
&mut buf.subdimensions((0, 0, 448, 384)),
|
||||
background_color,
|
||||
time,
|
||||
&t.pred().with_day(1).unwrap(),
|
||||
)?;
|
||||
draw_month(
|
||||
&mut buf.subdimensions((512, 0, 448, 384)),
|
||||
background_color,
|
||||
time,
|
||||
&t,
|
||||
)?;
|
||||
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(
|
||||
&mut buf.subdimensions((1024, 0, 448, 384)),
|
||||
background_color,
|
||||
time,
|
||||
&n,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
+45
-234
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user