gui/src/main.rs

482 lines
15 KiB
Rust
Raw Normal View History

use apps::get_beo_apps;
use femtovg::{
renderer::OpenGl, Align, Baseline, Canvas, Color, FontId, ImageId, Paint, Path, Renderer,
};
use instant::Instant;
use resource::resource;
use winit::{
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::Window,
};
mod helpers;
use helpers::PerfGraph;
// XXX rename to smth else
struct Fonts {
sans: FontId,
bold: FontId,
app_title: Paint,
app_menu: Paint,
app_menu_selected: Paint,
}
fn main() {
helpers::start(1024, 768, "Text demo");
}
use glutin::prelude::*;
mod apps;
mod hid;
mod roundy_math;
mod ui;
enum UiEvent<'e> {
WinitEvent(winit::event::Event<'e, ()>),
HardwareEvent(evdev::InputEvent),
}
fn run(
mut canvas: Canvas<OpenGl>,
el: EventLoop<()>,
context: glutin::context::PossiblyCurrentContext,
surface: glutin::surface::Surface<glutin::surface::WindowSurface>,
window: Window,
) {
let font_bold = canvas
.add_font_mem(&resource!("assets/Roboto-Bold.ttf"))
.expect("Cannot add font");
let font_sans = canvas
.add_font_mem(&resource!("assets/Roboto-Regular.ttf"))
.expect("Cannot add font");
let mut app_title = Paint::color(Color::hex("FFFFFF"));
app_title.set_font(&[font_bold]);
app_title.set_text_baseline(Baseline::Top);
app_title.set_text_align(Align::Center);
app_title.set_font_size(20.);
let mut app_menu = Paint::color(Color::hex("F0F0FF"));
app_menu.set_font(&[font_sans]);
app_menu.set_text_baseline(Baseline::Top);
app_menu.set_text_align(Align::Center);
app_menu.set_font_size(14.);
let mut app_menu_selected = Paint::color(Color::hex("F0F0FF"));
app_menu_selected.set_font(&[font_bold]);
app_menu_selected.set_text_baseline(Baseline::Top);
app_menu_selected.set_text_align(Align::Center);
app_menu_selected.set_font_size(14.);
let fonts = Fonts {
sans: font_sans,
bold: font_bold,
app_title,
app_menu,
app_menu_selected,
};
let apps = get_beo_apps();
let mut beo = ui::BeoUi::new(apps);
let start = Instant::now();
let mut prevt = start;
let mut perf = PerfGraph::new();
let mut font_size = 18.0;
#[cfg(feature = "debug_inspector")]
let mut font_texture_to_show: Option<usize> = None;
let mut beo_device = hid::Beo5Device::new_autodiscover().expect("Couldn't find Beo5 device");
/*
loop {
let ev = beo_device.get_event_nonblocking();
}
*/
let mut t = 0;
el.run(move |event, _, control_flow| {
t += 1;
*control_flow = ControlFlow::Poll;
let hw_event = beo_device.get_event_nonblocking();
match hw_event {
Some(ev) => {
println!("HW Event: {:?}", ev);
beo.accept_event(ev);
}
None => {}
}
match event {
Event::LoopDestroyed => *control_flow = ControlFlow::Exit,
Event::WindowEvent { ref event, .. } => match event {
WindowEvent::Resized(physical_size) => {
surface.resize(
&context,
physical_size.width.try_into().unwrap(),
physical_size.height.try_into().unwrap(),
);
}
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(keycode),
state: ElementState::Pressed,
..
},
..
} => {
if keycode == &VirtualKeyCode::Escape {
*control_flow = ControlFlow::Exit;
}
println!("INput {:?}", keycode);
//if *keycode == VirtualKeyCode::W {
// y -= 0.1;
//}
if *keycode == VirtualKeyCode::NumpadAdd || *keycode == VirtualKeyCode::B {
println!("Add");
font_size += 1.0;
}
if *keycode == VirtualKeyCode::NumpadSubtract {
println!("DEL");
font_size -= 1.0;
}
}
#[cfg(feature = "debug_inspector")]
WindowEvent::MouseInput {
device_id: _,
state: ElementState::Pressed,
..
} => {
let len = canvas.debug_inspector_get_font_textures().len();
let next = match font_texture_to_show {
None => 0,
Some(i) => i + 1,
};
font_texture_to_show = if next < len { Some(next) } else { None };
}
WindowEvent::MouseWheel {
device_id: _,
delta: winit::event::MouseScrollDelta::LineDelta(_, y),
..
} => {
println!("Scroll {:?}", y);
font_size += *y / 2.0;
font_size = font_size.max(2.0);
}
_ => {
println!("{:?}", event);
}
},
Event::RedrawRequested(_) => {
let dpi_factor = window.scale_factor();
let size = window.inner_size();
canvas.set_size(size.width, size.height, dpi_factor as f32);
canvas.clear_rect(0, 0, size.width, size.height, Color::rgbf(0., 0., 0.));
let elapsed = start.elapsed().as_secs_f32();
let now = Instant::now();
let dt = (now - prevt).as_secs_f32();
prevt = now;
perf.update(dt);
//draw_main_menu(&mut canvas, &fonts, &beo);
beo.draw(&mut canvas, &fonts);
let mut paint = Paint::color(Color::hex("B7410E"));
paint.set_font(&[fonts.bold]);
paint.set_text_baseline(Baseline::Top);
paint.set_text_align(Align::Right);
let _ = canvas.fill_text(size.width as f32 - 10.0, 10.0, format!("{t}"), &paint);
/*
draw_baselines(&mut canvas, &fonts, 5.0, 50.0, font_size);
draw_alignments(&mut canvas, &fonts, 120.0, 200.0, font_size);
//draw_paragraph(&mut canvas, &fonts, x, y, font_size, LOREM_TEXT);
draw_inc_size(&mut canvas, &fonts, 300.0, 10.0);
draw_complex(&mut canvas, 300.0, 340.0, font_size);
draw_stroked(&mut canvas, &fonts, size.width as f32 - 200.0, 100.0);
draw_gradient_fill(&mut canvas, &fonts, size.width as f32 - 200.0, 180.0);
draw_image_fill(&mut canvas, &fonts, size.width as f32 - 200.0, 260.0, image_id, elapsed);
let mut paint = Paint::color(Color::hex("B7410E"));
paint.set_font(&[fonts.bold]);
paint.set_text_baseline(Baseline::Top);
paint.set_text_align(Align::Right);
let _ = canvas.fill_text(
size.width as f32 - 10.0,
10.0,
format!("Scroll to increase / decrease font size. Current: {font_size}"),
&paint,
);
#[cfg(feature = "debug_inspector")]
let _ = canvas.fill_text(
size.width as f32 - 10.0,
24.0,
format!("Click to show font atlas texture. Current: {:?}", font_texture_to_show),
paint,
);
*/
// XXX Why the save/reset/restore ?
canvas.save();
canvas.reset();
perf.render(&mut canvas, 1024. - 220., 768. - 60.);
canvas.restore();
#[cfg(feature = "debug_inspector")]
if let Some(index) = font_texture_to_show {
canvas.save();
canvas.reset();
let textures = canvas.debug_inspector_get_font_textures();
if let Some(&id) = textures.get(index) {
canvas.debug_inspector_draw_image(id);
}
canvas.restore();
}
canvas.flush();
surface.swap_buffers(&context).unwrap();
}
Event::MainEventsCleared => window.request_redraw(),
_ => (),
}
});
}
fn draw_baselines<T: Renderer>(
canvas: &mut Canvas<T>,
fonts: &Fonts,
x: f32,
y: f32,
font_size: f32,
) {
let baselines = [
Baseline::Top,
Baseline::Middle,
Baseline::Alphabetic,
Baseline::Bottom,
];
let mut paint = Paint::color(Color::black());
paint.set_font(&[fonts.sans]);
paint.set_font_size(font_size);
let base_text = "AbcpKjgF".to_string();
for (i, baseline) in baselines.iter().enumerate() {
let y = y + i as f32 * 40.0;
let mut path = Path::new();
path.move_to(x, y + 0.5);
path.line_to(x + 250., y + 0.5);
canvas.stroke_path(&path, &Paint::color(Color::rgba(255, 32, 32, 128)));
paint.set_text_baseline(*baseline);
if let Ok(res) =
canvas.fill_text(x, y, format!("{base_text} Baseline::{baseline:?}"), &paint)
{
//let res = canvas.fill_text(10.0, y, format!("d النص العربي جميل جدا {:?}", baseline), &paint);
let mut path = Path::new();
path.rect(res.x, res.y, res.width(), res.height());
canvas.stroke_path(&path, &Paint::color(Color::rgba(100, 100, 100, 64)));
}
}
}
fn draw_alignments<T: Renderer>(
canvas: &mut Canvas<T>,
fonts: &Fonts,
x: f32,
y: f32,
font_size: f32,
) {
let alignments = [Align::Left, Align::Center, Align::Right];
let mut path = Path::new();
path.move_to(x + 0.5, y - 20.);
path.line_to(x + 0.5, y + 80.);
canvas.stroke_path(&path, &Paint::color(Color::rgba(255, 32, 32, 128)));
let mut paint = Paint::color(Color::black());
paint.set_font(&[fonts.sans]);
paint.set_font_size(font_size);
for (i, alignment) in alignments.iter().enumerate() {
paint.set_text_align(*alignment);
if let Ok(res) = canvas.fill_text(
x,
y + i as f32 * 30.0,
format!("Align::{alignment:?}"),
&paint,
) {
let mut path = Path::new();
path.rect(res.x, res.y, res.width(), res.height());
canvas.stroke_path(&path, &Paint::color(Color::rgba(100, 100, 100, 64)));
}
}
}
fn draw_paragraph<T: Renderer>(
canvas: &mut Canvas<T>,
fonts: &Fonts,
x: f32,
y: f32,
font_size: f32,
text: &str,
) {
let mut paint = Paint::color(Color::black());
paint.set_font(&[fonts.bold]);
//paint.set_text_align(Align::Right);
paint.set_font_size(font_size);
let font_metrics = canvas.measure_font(&paint).expect("Error measuring font");
let width = canvas.width() as f32;
let mut y = y;
let lines = canvas
.break_text_vec(width, text, &paint)
.expect("Error while breaking text");
for line_range in lines {
if let Ok(_res) = canvas.fill_text(x, y, &text[line_range], &paint) {
y += font_metrics.height();
}
}
// let mut start = 0;
// while start < text.len() {
// let substr = &text[start..];
// if let Ok(index) = canvas.break_text(width, substr, &paint) {
// if let Ok(res) = canvas.fill_text(x, y, &substr[0..index], &paint) {
// y += res.height;
// }
// start += &substr[0..index].len();
// } else {
// break;
// }
// }
}
fn draw_inc_size<T: Renderer>(canvas: &mut Canvas<T>, fonts: &Fonts, x: f32, y: f32) {
let mut cursor_y = y;
for i in 4..23 {
let mut paint = Paint::color(Color::black());
paint.set_font(&[fonts.sans]);
paint.set_font_size(i as f32);
let font_metrics = canvas.measure_font(&paint).expect("Error measuring font");
if let Ok(_res) = canvas.fill_text(
x,
cursor_y,
"The quick brown fox jumps over the lazy dog",
&paint,
) {
cursor_y += font_metrics.height();
}
}
}
fn draw_stroked<T: Renderer>(canvas: &mut Canvas<T>, fonts: &Fonts, x: f32, y: f32) {
let mut paint = Paint::color(Color::rgba(0, 0, 0, 128));
paint.set_font(&[fonts.bold]);
paint.set_line_width(12.0);
paint.set_font_size(72.0);
let _ = canvas.stroke_text(x + 5.0, y + 5.0, "RUST", &paint);
paint.set_color(Color::black());
paint.set_line_width(10.0);
let _ = canvas.stroke_text(x, y, "RUST", &paint);
paint.set_line_width(6.0);
paint.set_color(Color::hex("#B7410E"));
let _ = canvas.stroke_text(x, y, "RUST", &paint);
paint.set_color(Color::white());
let _ = canvas.fill_text(x, y, "RUST", &paint);
}
fn draw_gradient_fill<T: Renderer>(canvas: &mut Canvas<T>, fonts: &Fonts, x: f32, y: f32) {
let mut paint = Paint::color(Color::rgba(0, 0, 0, 255));
paint.set_font(&[fonts.bold]);
paint.set_line_width(6.0);
paint.set_font_size(72.0);
let _ = canvas.stroke_text(x, y, "RUST", &paint);
let mut paint = Paint::linear_gradient(
x,
y - 60.0,
x,
y,
Color::rgba(225, 133, 82, 255),
Color::rgba(93, 55, 70, 255),
);
paint.set_font(&[fonts.bold]);
paint.set_font_size(72.0);
let _ = canvas.fill_text(x, y, "RUST", &paint);
}
fn draw_image_fill<T: Renderer>(
canvas: &mut Canvas<T>,
fonts: &Fonts,
x: f32,
y: f32,
image_id: ImageId,
t: f32,
) {
let mut paint = Paint::color(Color::hex("#7300AB"));
paint.set_line_width(3.0);
let mut path = Path::new();
path.move_to(x, y - 2.0);
path.line_to(x + 180.0, y - 2.0);
canvas.stroke_path(&path, &paint);
let text = "RUST";
let mut paint = Paint::color(Color::rgba(0, 0, 0, 128));
paint.set_font(&[fonts.bold]);
paint.set_line_width(4.0);
paint.set_font_size(72.0);
let _ = canvas.stroke_text(x, y, text, &paint);
let mut paint = Paint::image(image_id, x, y - t * 10.0, 120.0, 120.0, 0.0, 0.50);
//let mut paint = Paint::image(image_id, x + 50.0, y - t*10.0, 120.0, 120.0, t.sin() / 10.0, 0.70);
paint.set_font(&[fonts.bold]);
paint.set_font_size(72.0);
let _ = canvas.fill_text(x, y, text, &paint);
}
fn draw_complex<T: Renderer>(canvas: &mut Canvas<T>, x: f32, y: f32, font_size: f32) {
let mut paint = Paint::color(Color::rgb(34, 34, 34));
paint.set_font_size(font_size);
let _ = canvas.fill_text(
x,
y,
"Latin اللغة العربية Кирилица тест iiiiiiiiiiiiiiiiiiiiiiiiiiiii\nasdasd",
&paint,
);
//let _ = canvas.fill_text(x, y, "اللغة العربية", &paint);
//canvas.fill_text(x, y, "Traditionally, text is composed to create a readable, coherent, and visually satisfying", &paint);
}