132 lines
3.7 KiB
Rust
132 lines
3.7 KiB
Rust
use std::cmp::min;
|
|
use eframe::egui;
|
|
use eframe::egui::Color32;
|
|
use image::{GenericImage, Pixel, Rgb, Rgba};
|
|
use rusttype::{point, Font, Scale};
|
|
use crate::canvas::Canvas;
|
|
|
|
impl Canvas {
|
|
|
|
pub fn text_center(
|
|
&mut self,
|
|
font: &Font,
|
|
color: egui::Color32,
|
|
x: f32,
|
|
y: f32,
|
|
text: &str,
|
|
scale: Scale,
|
|
) {
|
|
self.refresh();
|
|
|
|
let v_metrics = font.v_metrics(scale);
|
|
|
|
let glyphs: Vec<_> = font
|
|
.layout(text, scale, point(0.0, 0.0 + v_metrics.ascent))
|
|
.collect();
|
|
|
|
let (width, height) = {
|
|
let mut min_x = i32::MAX;
|
|
let mut min_y = i32::MAX;
|
|
let mut max_x = i32::MIN;
|
|
let mut max_y = i32::MIN;
|
|
|
|
for g in glyphs.iter()
|
|
.map(|p|p.pixel_bounding_box())
|
|
.flatten() {
|
|
min_x = min_x.min(g.min.x);
|
|
min_y = min_y.min(g.min.y);
|
|
max_x = max_x.max(g.max.x);
|
|
max_y = max_y.max(g.max.y);
|
|
// self.debug_rect(
|
|
// Color32::GREEN,
|
|
// g.min.x as _,
|
|
// g.min.y as _,
|
|
// g.max.x as _,
|
|
// g.max.y as _,
|
|
// );
|
|
}
|
|
|
|
// self.debug_rect(
|
|
// Color32::PURPLE,
|
|
// min_x as _, min_y as _,
|
|
// max_x as _, max_y as _);
|
|
((max_x/* - min_x*/) as f32,
|
|
(max_y/* - min_y*/) as f32)
|
|
};
|
|
let (x, y) = (
|
|
x - (width / 2.0),
|
|
y - (height / 2.0)
|
|
);
|
|
|
|
// self.debug_rect(Color32::RED, x, y, x + width, y + height);
|
|
|
|
let glyphs: Vec<_> = font
|
|
.layout(text, scale, point(x, y + v_metrics.ascent))
|
|
.collect();
|
|
|
|
for glyph in glyphs {
|
|
if let Some(bounding_box) = glyph.pixel_bounding_box() {
|
|
|
|
// self.debug_rect(
|
|
// Color32::RED,
|
|
// bounding_box.min.x as _,
|
|
// bounding_box.min.y as _,
|
|
// bounding_box.max.x as _,
|
|
// bounding_box.max.y as _);
|
|
|
|
glyph.draw(|x, y, v| {
|
|
let p = self.image.get_pixel_mut(
|
|
x + bounding_box.min.x as u32,
|
|
y + bounding_box.min.y as u32,
|
|
);
|
|
|
|
let mut op = p.to_rgba();
|
|
let np = Rgba([
|
|
color.r(),
|
|
color.g(),
|
|
color.b(),
|
|
(color.a() as f32 * v) as u8
|
|
]);
|
|
op.blend(&np);
|
|
*p = op.to_rgb()
|
|
});
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
fn debug_rect(
|
|
&mut self,
|
|
color: Color32,
|
|
mnx: f32,
|
|
mny: f32,
|
|
mxx: f32,
|
|
mxy: f32,
|
|
) {
|
|
self.refresh();
|
|
|
|
// sort the values just in case
|
|
let (mnx, mxx) = (mnx.min(mxx), mxx.max(mxx));
|
|
let (mny, mxy) = (mny.min(mxy), mxy.max(mxy));
|
|
|
|
let rgb = Rgb([
|
|
color.r(),
|
|
color.g(),
|
|
color.b(),
|
|
]);
|
|
|
|
let w = (mxx - mnx) as u32;
|
|
let h = (mxy - mny) as u32;
|
|
for w in 0..w {
|
|
self.image.put_pixel(mnx as u32 + w, mny as u32, rgb);
|
|
self.image.put_pixel(mnx as u32 + w, mxy as u32, rgb);
|
|
self.image.put_pixel(mnx as u32 + w, mny as u32 + h, rgb);
|
|
|
|
}
|
|
for h in 0..h {
|
|
self.image.put_pixel(mnx as u32, mny as u32 + h, rgb);
|
|
self.image.put_pixel(mxx as u32, mny as u32 + h, rgb);
|
|
}
|
|
}
|
|
|
|
} |