Signed-off-by: Frank Villaro-Dixon <frank@villaro-dixon.eu>
This commit is contained in:
Frank Villaro-Dixon 2024-05-05 01:07:19 +02:00
parent b1e4921376
commit 6b3a2cfbfc
5 changed files with 202 additions and 28 deletions

View file

@ -92,12 +92,23 @@ pub fn start(
NonZeroU32::new(height).unwrap(), NonZeroU32::new(height).unwrap(),
); );
let surface = unsafe { gl_config.display().create_window_surface(&gl_config, &attrs).unwrap() }; let surface = unsafe {
gl_config
.display()
.create_window_surface(&gl_config, &attrs)
.unwrap()
};
let gl_context = not_current_gl_context.take().unwrap().make_current(&surface).unwrap(); let gl_context = not_current_gl_context
.take()
.unwrap()
.make_current(&surface)
.unwrap();
let renderer = unsafe { OpenGl::new_from_function_cstr(|s| gl_display.get_proc_address(s) as *const _) } let renderer = unsafe {
.expect("Cannot create renderer"); OpenGl::new_from_function_cstr(|s| gl_display.get_proc_address(s) as *const _)
}
.expect("Cannot create renderer");
let mut canvas = Canvas::new(renderer).expect("Cannot create canvas"); let mut canvas = Canvas::new(renderer).expect("Cannot create canvas");
canvas.set_size(width, height, window.scale_factor() as f32); canvas.set_size(width, height, window.scale_factor() as f32);

View file

@ -60,7 +60,12 @@ impl PerfGraph {
text_paint.set_font_size(14.0); text_paint.set_font_size(14.0);
text_paint.set_text_align(Align::Right); text_paint.set_text_align(Align::Right);
text_paint.set_text_baseline(Baseline::Top); text_paint.set_text_baseline(Baseline::Top);
let _ = canvas.fill_text(x + w - 5.0, y, &format!("{:.2} FPS", 1.0 / avg), &text_paint); let _ = canvas.fill_text(
x + w - 5.0,
y,
&format!("{:.2} FPS", 1.0 / avg),
&text_paint,
);
let mut text_paint = Paint::color(Color::rgba(240, 240, 240, 200)); let mut text_paint = Paint::color(Color::rgba(240, 240, 240, 200));
text_paint.set_font_size(12.0); text_paint.set_font_size(12.0);

View file

@ -1,4 +1,9 @@
use femtovg::{renderer::OpenGl, Align, Baseline, Canvas, Color, FontId, ImageFlags, ImageId, Paint, Path, Renderer}; use core::panic;
use femtovg::{
renderer::OpenGl, Align, Baseline, Canvas, Color, FontId, ImageFlags, ImageId, Paint, Path,
Renderer,
};
use instant::Instant; use instant::Instant;
use resource::resource; use resource::resource;
use winit::{ use winit::{
@ -21,6 +26,8 @@ fn main() {
use glutin::prelude::*; use glutin::prelude::*;
mod roundy_math;
mod ui;
fn run( fn run(
mut canvas: Canvas<OpenGl>, mut canvas: Canvas<OpenGl>,
@ -36,11 +43,12 @@ fn run(
bold: canvas bold: canvas
.add_font_mem(&resource!("assets/Roboto-Bold.ttf")) .add_font_mem(&resource!("assets/Roboto-Bold.ttf"))
.expect("Cannot add font"), .expect("Cannot add font"),
light: canvas
.add_font_mem(&resource!("assets/Roboto-Light.ttf"))
.expect("Cannot add font"),
}; };
let beo = ui::Beo::new();
for app in &beo.apps {
println!("{}", app.name());
}
let flags = ImageFlags::GENERATE_MIPMAPS | ImageFlags::REPEAT_X | ImageFlags::REPEAT_Y; let flags = ImageFlags::GENERATE_MIPMAPS | ImageFlags::REPEAT_X | ImageFlags::REPEAT_Y;
let image_id = canvas let image_id = canvas
@ -100,7 +108,7 @@ fn run(
x += 0.1; x += 0.1;
} }
if *keycode == VirtualKeyCode::NumpadAdd || *keycode == VirtualKeyCode::B{ if *keycode == VirtualKeyCode::NumpadAdd || *keycode == VirtualKeyCode::B {
println!("Add"); println!("Add");
font_size += 1.0; font_size += 1.0;
} }
@ -134,7 +142,6 @@ fn run(
_ => (), _ => (),
}, },
Event::RedrawRequested(_) => { Event::RedrawRequested(_) => {
println!("Redraw");
let dpi_factor = window.scale_factor(); let dpi_factor = window.scale_factor();
let size = window.inner_size(); let size = window.inner_size();
canvas.set_size(size.width, size.height, dpi_factor as f32); canvas.set_size(size.width, size.height, dpi_factor as f32);
@ -147,7 +154,8 @@ fn run(
perf.update(dt); perf.update(dt);
draw_main_menu(&mut canvas, &fonts, &beo);
/*
draw_baselines(&mut canvas, &fonts, 5.0, 50.0, font_size); draw_baselines(&mut canvas, &fonts, 5.0, 50.0, font_size);
draw_alignments(&mut canvas, &fonts, 120.0, 200.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_paragraph(&mut canvas, &fonts, x, y, font_size, LOREM_TEXT);
@ -176,10 +184,11 @@ fn run(
format!("Click to show font atlas texture. Current: {:?}", font_texture_to_show), format!("Click to show font atlas texture. Current: {:?}", font_texture_to_show),
paint, paint,
); );
*/
canvas.save(); canvas.save();
canvas.reset(); canvas.reset();
perf.render(&mut canvas, 5.0, 5.0); perf.render(&mut canvas, 500.0, 5.0);
canvas.restore(); canvas.restore();
#[cfg(feature = "debug_inspector")] #[cfg(feature = "debug_inspector")]
@ -202,6 +211,50 @@ fn run(
}); });
} }
fn draw_main_menu<T: Renderer>(canvas: &mut Canvas<T>, fonts: &Fonts, beo: &ui::Beo) {
let canvas_width = canvas.width();
let canvas_height = canvas.height();
// circle is centered on the right side of the screen
let main_menu_circle = roundy_math::VirtualCircle {
center: roundy_math::Point {
x: canvas_width as f64,
y: canvas_height as f64 / 2.0 + 10.,
},
//radius: canvas_width as f64 - 30.0,
radius: 400.0,
};
println!("Canvas width: {}, height: {}", canvas_width, canvas_height);
let canvas_size = roundy_math::Point {
x: canvas_width as f64,
y: canvas_height as f64,
};
let pts = main_menu_circle.get_equidistant_points(8, canvas_size);
for i in 0..pts.len() {
println!(">>> {:?}", pts[i]);
let mut paint = Paint::color(Color::hex("B7410E"));
paint.set_font(&[fonts.bold]);
paint.set_text_baseline(Baseline::Top);
let _ = canvas.fill_text(pts[i].x as f32, pts[i].y as f32, format!("XX {i}"), &paint);
}
/*
let mut y = 40.0;
for app in &beo.apps {
println!("{}", app.name());
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(50.0, y, app.name(), &paint);
y += 20.0;
}
*/
}
fn draw_baselines<T: Renderer>( fn draw_baselines<T: Renderer>(
canvas: &mut Canvas<T>, canvas: &mut Canvas<T>,
fonts: &Fonts, fonts: &Fonts,
@ -209,7 +262,12 @@ fn draw_baselines<T: Renderer>(
y: f32, y: f32,
font_size: f32, font_size: f32,
) { ) {
let baselines = [Baseline::Top, Baseline::Middle, Baseline::Alphabetic, Baseline::Bottom]; let baselines = [
Baseline::Top,
Baseline::Middle,
Baseline::Alphabetic,
Baseline::Bottom,
];
let mut paint = Paint::color(Color::black()); let mut paint = Paint::color(Color::black());
paint.set_font(&[fonts.sans]); paint.set_font(&[fonts.sans]);
@ -227,7 +285,9 @@ fn draw_baselines<T: Renderer>(
paint.set_text_baseline(*baseline); paint.set_text_baseline(*baseline);
if let Ok(res) = canvas.fill_text(x, y, format!("{base_text} Baseline::{baseline:?}"), &paint) { 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 res = canvas.fill_text(10.0, y, format!("d النص العربي جميل جدا {:?}", baseline), &paint);
let mut path = Path::new(); let mut path = Path::new();
@ -237,7 +297,13 @@ fn draw_baselines<T: Renderer>(
} }
} }
fn draw_alignments<T: Renderer>(canvas: &mut Canvas<T>, fonts: &Fonts, x: f32, y: f32, font_size: f32) { 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 alignments = [Align::Left, Align::Center, Align::Right];
let mut path = Path::new(); let mut path = Path::new();
@ -252,7 +318,12 @@ fn draw_alignments<T: Renderer>(canvas: &mut Canvas<T>, fonts: &Fonts, x: f32, y
for (i, alignment) in alignments.iter().enumerate() { for (i, alignment) in alignments.iter().enumerate() {
paint.set_text_align(*alignment); paint.set_text_align(*alignment);
if let Ok(res) = canvas.fill_text(x, y + i as f32 * 30.0, format!("Align::{alignment:?}"), &paint) { if let Ok(res) = canvas.fill_text(
x,
y + i as f32 * 30.0,
format!("Align::{alignment:?}"),
&paint,
) {
let mut path = Path::new(); let mut path = Path::new();
path.rect(res.x, res.y, res.width(), res.height()); path.rect(res.x, res.y, res.width(), res.height());
canvas.stroke_path(&path, &Paint::color(Color::rgba(100, 100, 100, 64))); canvas.stroke_path(&path, &Paint::color(Color::rgba(100, 100, 100, 64)));
@ -260,9 +331,16 @@ fn draw_alignments<T: Renderer>(canvas: &mut Canvas<T>, fonts: &Fonts, x: f32, y
} }
} }
fn draw_paragraph<T: Renderer>(canvas: &mut Canvas<T>, fonts: &Fonts, x: f32, y: f32, font_size: f32, text: &str) { 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()); let mut paint = Paint::color(Color::black());
paint.set_font(&[fonts.light]); paint.set_font(&[fonts.bold]);
//paint.set_text_align(Align::Right); //paint.set_text_align(Align::Right);
paint.set_font_size(font_size); paint.set_font_size(font_size);
@ -308,7 +386,12 @@ fn draw_inc_size<T: Renderer>(canvas: &mut Canvas<T>, fonts: &Fonts, x: f32, y:
let font_metrics = canvas.measure_font(&paint).expect("Error measuring font"); 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) { 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(); cursor_y += font_metrics.height();
} }
} }
@ -353,7 +436,14 @@ fn draw_gradient_fill<T: Renderer>(canvas: &mut Canvas<T>, fonts: &Fonts, x: f32
let _ = canvas.fill_text(x, y, "RUST", &paint); 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) { 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")); let mut paint = Paint::color(Color::hex("#7300AB"));
paint.set_line_width(3.0); paint.set_line_width(3.0);
let mut path = Path::new(); let mut path = Path::new();
@ -389,4 +479,3 @@ fn draw_complex<T: Renderer>(canvas: &mut Canvas<T>, x: f32, y: f32, font_size:
//let _ = canvas.fill_text(x, y, "اللغة العربية", &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); //canvas.fill_text(x, y, "Traditionally, text is composed to create a readable, coherent, and visually satisfying", &paint);
} }

63
src/roundy_math.rs Normal file
View file

@ -0,0 +1,63 @@
use std::f64::consts::PI;
//use std::f64;
#[derive(Debug)]
pub struct Point {
pub x: f64,
pub y: f64,
}
pub struct VirtualCircle {
pub center: Point,
// radius of the circle in pixels
pub radius: f64,
}
impl VirtualCircle {
pub fn get_equidistant_points(&self, n: usize, viewport_size: Point) -> Vec<Point> {
// Note: this only works when the circle's origin is at the middle right of the viewport.
// because I'm not clever enough to figure out how to calculate the intersection points
// in the general case.
println!(
"center: {:?}, radius: {}, viewport_size: {:?}",
self.center, self.radius, viewport_size
);
// Calculate the angles at which the circle intersects with the viewport
let upper_x = self.center.x - (self.radius.powf(2.) - (0. - self.center.y).powf(2.)).sqrt();
let lower_x = self.center.x
- (self.radius.powf(2.) - (viewport_size.y - self.center.y).powf(2.)).sqrt();
let upper_point = Point { x: upper_x, y: 0. };
let lower_point = Point {
x: lower_x,
y: viewport_size.y,
};
println!("up/low: {:?} {:?}", upper_point, lower_point);
let intersection_angles = (
(upper_point.x - self.center.x).atan2(upper_point.y - self.center.y),
(lower_point.x - self.center.x).atan2(lower_point.y - self.center.y),
);
println!("int angles: {:?}", intersection_angles);
let mut points = Vec::new();
// Calculate the angle step to distribute points evenly
let angle_step = (intersection_angles.1 - intersection_angles.0) / (n as f64);
println!("angle step: {}", angle_step);
// Generate the points
for i in 0..n {
let theta = intersection_angles.0 + angle_step * (i as f64 + 0.5);
let x = theta.sin() * self.radius + viewport_size.x;
let y = theta.cos() * self.radius + viewport_size.y - self.center.y;
println!("x: {}, y: {}", x, y);
points.push(Point { x: x, y: y });
}
points
}
}

View file

@ -1,8 +1,8 @@
struct Beo { pub struct Beo {
apps: Vec<App>, pub apps: Vec<Box<dyn App>>,
} }
trait App { pub trait App {
fn name(&self) -> &str; fn name(&self) -> &str;
} }
@ -19,6 +19,12 @@ impl App for Radio {
} }
} }
fn get_apps() -> Vec<App> { impl Beo {
vec![Stotify{}, Radio{}] pub fn new() -> Beo {
} Beo { apps: get_apps() }
}
}
fn get_apps() -> Vec<Box<dyn App>> {
vec![Box::new(Spotify {}), Box::new(Radio {})]
}