imageproc/drawing/
text.rs1use crate::definitions::{Clamp, Image};
2use crate::drawing::Canvas;
3use conv::ValueInto;
4use image::{GenericImage, ImageBuffer, Pixel};
5use std::f32;
6use std::i32;
7
8use crate::pixelops::weighted_sum;
9use rusttype::{point, Font, PositionedGlyph, Rect, Scale};
10use std::cmp::max;
11
12fn layout_glyphs(
13 scale: Scale,
14 font: &Font,
15 text: &str,
16 mut f: impl FnMut(PositionedGlyph, Rect<i32>),
17) -> (i32, i32) {
18 let v_metrics = font.v_metrics(scale);
19
20 let (mut w, mut h) = (0, 0);
21
22 for g in font.layout(text, scale, point(0.0, v_metrics.ascent)) {
23 if let Some(bb) = g.pixel_bounding_box() {
24 w = max(w, bb.max.x);
25 h = max(h, bb.max.y);
26 f(g, bb);
27 }
28 }
29
30 (w, h)
31}
32
33pub fn text_size(scale: Scale, font: &Font, text: &str) -> (i32, i32) {
37 layout_glyphs(scale, font, text, |_, _| {})
38}
39
40pub fn draw_text_mut<'a, C>(
46 canvas: &'a mut C,
47 color: C::Pixel,
48 x: i32,
49 y: i32,
50 scale: Scale,
51 font: &'a Font<'a>,
52 text: &'a str,
53) where
54 C: Canvas,
55 <C::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32>,
56{
57 let image_width = canvas.width() as i32;
58 let image_height = canvas.height() as i32;
59
60 layout_glyphs(scale, font, text, |g, bb| {
61 g.draw(|gx, gy, gv| {
62 let gx = gx as i32 + bb.min.x;
63 let gy = gy as i32 + bb.min.y;
64
65 let image_x = gx + x;
66 let image_y = gy + y;
67
68 if (0..image_width).contains(&image_x) && (0..image_height).contains(&image_y) {
69 let pixel = canvas.get_pixel(image_x as u32, image_y as u32);
70 let weighted_color = weighted_sum(pixel, color, 1.0 - gv, gv);
71 canvas.draw_pixel(image_x as u32, image_y as u32, weighted_color);
72 }
73 })
74 });
75}
76
77#[must_use = "the function does not modify the original image"]
83pub fn draw_text<'a, I>(
84 image: &'a I,
85 color: I::Pixel,
86 x: i32,
87 y: i32,
88 scale: Scale,
89 font: &'a Font<'a>,
90 text: &'a str,
91) -> Image<I::Pixel>
92where
93 I: GenericImage,
94 <I::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32>,
95{
96 let mut out = ImageBuffer::new(image.width(), image.height());
97 out.copy_from(image, 0, 0).unwrap();
98 draw_text_mut(&mut out, color, x, y, scale, font, text);
99 out
100}