rounded corners
This commit is contained in:
parent
604d2e4134
commit
a0d8bbd1f4
2 changed files with 137 additions and 10 deletions
|
|
@ -64,6 +64,9 @@ pub struct Configuration {
|
|||
wayland_height: i32,
|
||||
wayland_im_enable: bool,
|
||||
|
||||
key_padding: u64,
|
||||
key_corner_radius: u64,
|
||||
|
||||
colors: KeyboardColors,
|
||||
}
|
||||
|
||||
|
|
@ -160,6 +163,9 @@ impl Configuration {
|
|||
wayland_im_enable: true,
|
||||
evfb_height: 0.25,
|
||||
|
||||
key_padding: 2,
|
||||
key_corner_radius: 5,
|
||||
|
||||
colors: KeyboardColors::default(),
|
||||
};
|
||||
|
||||
|
|
@ -212,6 +218,27 @@ impl Configuration {
|
|||
cfg.load_evfb(evfb);
|
||||
}
|
||||
|
||||
let key_padding = yaml.get(&Yaml::String(String::from("key_padding")));
|
||||
if let Some(key_padding) = key_padding {
|
||||
let key_padding = match key_padding.as_i64() {
|
||||
Some(l) => l.try_into().ok(),
|
||||
None => None,
|
||||
};
|
||||
let key_padding = key_padding.expect("Key padding should be a 64-bit unsigned integer");
|
||||
cfg.key_padding = key_padding;
|
||||
}
|
||||
|
||||
let key_corner_radius = yaml.get(&Yaml::String(String::from("key_corner_radius")));
|
||||
if let Some(key_corner_radius) = key_corner_radius {
|
||||
let key_corner_radius = match key_corner_radius.as_i64() {
|
||||
Some(l) => l.try_into().ok(),
|
||||
None => None,
|
||||
};
|
||||
let key_corner_radius = key_corner_radius.expect("Key corner radius should be a 64-bit unsigned integer");
|
||||
cfg.key_corner_radius = key_corner_radius;
|
||||
}
|
||||
|
||||
|
||||
let colors = yaml.get(&Yaml::String(String::from("colors")));
|
||||
if let Some(colors) = colors {
|
||||
let colors = colors.as_hash().expect("Color configuration should be a YAML mapping");
|
||||
|
|
@ -269,4 +296,17 @@ impl Configuration {
|
|||
{
|
||||
&self.colors
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn key_padding(&self) -> u64
|
||||
{
|
||||
self.key_padding
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn key_corner_radius(&self) -> u64
|
||||
{
|
||||
self.key_corner_radius
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,70 @@ fn fill_image(dest: &mut ImgRefMut<BGRA<u8>>, src: BGRA<u8>)
|
|||
}
|
||||
}
|
||||
|
||||
fn distance(x1: usize, y1: usize, x2: usize, y2: usize) -> f32
|
||||
{
|
||||
(((x1 as isize - x2 as isize).pow(2) + (y1 as isize - y2 as isize).pow(2)) as f32).sqrt()
|
||||
}
|
||||
|
||||
fn is_point_in_rounded_rectangle(
|
||||
x: usize,
|
||||
y: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
radius: usize,
|
||||
) -> bool
|
||||
{
|
||||
// Check if the point is within the rectangle's main area
|
||||
if x >= radius && x <= width - radius && y <= height {
|
||||
return true;
|
||||
}
|
||||
if x <= width && y >= radius && y <= height - radius {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check the corners
|
||||
// Top-left corner
|
||||
|
||||
|
||||
|
||||
|
||||
if distance(x, y, radius, radius) < radius as f32 {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Top-right corner
|
||||
if distance(x, y, width - radius, radius) < radius as f32 {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Bottom-left corner
|
||||
if distance(x, y, radius, height - radius) < radius as f32 {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Bottom-right corner
|
||||
if distance(x, y, width - radius, height - radius) < radius as f32 {
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
|
||||
fn rounded_rectangle(dest: &mut ImgRefMut<BGRA<u8>>, src: BGRA<u8>, radius: usize)
|
||||
{
|
||||
let (width, height) = (dest.width(), dest.height());
|
||||
|
||||
for (y, row) in dest.rows_mut().enumerate() {
|
||||
for (x, dest) in row.iter_mut().enumerate() {
|
||||
if is_point_in_rounded_rectangle(x, y, width, height, radius) {
|
||||
*dest = src;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn bitmap_to_imgref(bitmap: &freetype::FT_Bitmap) -> ImgRef<u8>
|
||||
{
|
||||
unsafe {
|
||||
|
|
@ -93,6 +157,9 @@ pub struct Graphics<D: Display> {
|
|||
x_scale: f64,
|
||||
y_scale: f64,
|
||||
|
||||
key_padding: u64,
|
||||
key_corner_radius: u64,
|
||||
|
||||
colors: KeyboardColors,
|
||||
}
|
||||
|
||||
|
|
@ -217,6 +284,9 @@ impl<D: Display> Graphics<D> {
|
|||
x_scale: 0.0,
|
||||
y_scale: 0.0,
|
||||
|
||||
key_padding: cfg.key_padding(),
|
||||
key_corner_radius: cfg.key_corner_radius(),
|
||||
|
||||
colors: cfg.colors().clone(),
|
||||
}
|
||||
}
|
||||
|
|
@ -473,6 +543,9 @@ impl<D: Display> Graphics<D> {
|
|||
let src = labels.get(label)
|
||||
.expect("Layout and size should be set before drawing");
|
||||
|
||||
assert!(src.img.height() > src.y, "Not enough space to draw label, reduce padding and/or corner radius");
|
||||
|
||||
|
||||
let width = src.img.width();
|
||||
let height = src.img.height() - src.y;
|
||||
|
||||
|
|
@ -533,12 +606,13 @@ impl<D: Display> Graphics<D> {
|
|||
x_scale: f64, y_scale: f64,
|
||||
img: &mut ImgRefMut<BGRA<u8>>,
|
||||
key: &Key, mod_state: &[ModState],
|
||||
key_padding: usize, key_corner_radius: usize,
|
||||
colors: &KeyboardColors)
|
||||
{
|
||||
let x1 = (key.x1 * x_scale) as usize;
|
||||
let y1 = (key.y1 * y_scale) as usize;
|
||||
let x2 = (key.x2 * x_scale) as usize;
|
||||
let y2 = (key.y2 * y_scale) as usize;
|
||||
let x1 = (key.x1 * x_scale) as usize + key_padding;
|
||||
let y1 = (key.y1 * y_scale) as usize + key_padding;
|
||||
let x2 = (key.x2 * x_scale) as usize - key_padding;
|
||||
let y2 = (key.y2 * y_scale) as usize - key_padding;
|
||||
|
||||
let mut keyimg = img.sub_image_mut(x1, y1, x2 - x1, y2 - y1);
|
||||
|
||||
|
|
@ -557,21 +631,30 @@ impl<D: Display> Graphics<D> {
|
|||
}
|
||||
|
||||
if pressed {
|
||||
fill_image(&mut keyimg, colors.keycap_pressed);
|
||||
rounded_rectangle(&mut keyimg, colors.keycap_pressed, key_corner_radius);
|
||||
} else {
|
||||
fill_image(&mut keyimg, colors.keycap);
|
||||
rounded_rectangle(&mut keyimg, colors.keycap, key_corner_radius);
|
||||
}
|
||||
|
||||
let half_radius = key_corner_radius / 2;
|
||||
let mut labelimg = keyimg.sub_image_mut(
|
||||
half_radius,
|
||||
half_radius,
|
||||
keyimg.width() - half_radius * 2,
|
||||
keyimg.height() - half_radius * 2
|
||||
);
|
||||
|
||||
|
||||
let color = Self::keypart_to_color(&key.parts[0], false, mod_state, colors);
|
||||
let label = key.parts[0].display_label();
|
||||
Self::draw_label_part(labels, Anchor::Center, Anchor::Center,
|
||||
&mut keyimg, label, color.map(|c| c as f32 / 255.));
|
||||
&mut labelimg, label, color.map(|c| c as f32 / 255.));
|
||||
|
||||
for i in 0..8 {
|
||||
let color = Self::keypart_to_color(&key.parts[i + 1], true, mod_state, colors);
|
||||
let label = key.parts[i + 1].display_label();
|
||||
Self::draw_label_part(sublabels, ANCHORS[i].0, ANCHORS[i].1,
|
||||
&mut keyimg, label, color.map(|c| c as f32 / 255.));
|
||||
&mut labelimg, label, color.map(|c| c as f32 / 255.));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -586,7 +669,9 @@ impl<D: Display> Graphics<D> {
|
|||
|
||||
Self::draw_key(&self.labels, &self.sublabels,
|
||||
self.x_scale, self.y_scale,
|
||||
&mut img, key, mod_state, &self.colors);
|
||||
&mut img, key, mod_state,
|
||||
self.key_padding as usize, self.key_corner_radius as usize,
|
||||
&self.colors);
|
||||
|
||||
self.disp.end(x1, y1, x2 - x1, y2 - y1);
|
||||
}
|
||||
|
|
@ -617,7 +702,9 @@ impl<D: Display> Graphics<D> {
|
|||
for key in row {
|
||||
Self::draw_key(&self.labels, &self.sublabels,
|
||||
self.x_scale, self.y_scale,
|
||||
&mut img, key, mod_state, &self.colors);
|
||||
&mut img, key, mod_state,
|
||||
self.key_padding as usize, self.key_corner_radius as usize,
|
||||
&self.colors);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue