Skip to content

Commit

Permalink
new text
Browse files Browse the repository at this point in the history
  • Loading branch information
cospectrum committed Oct 19, 2024
1 parent 38ce601 commit f8d8b62
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 10 deletions.
72 changes: 62 additions & 10 deletions src/drawing/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,22 @@ use crate::definitions::{Clamp, Image};
use crate::drawing::Canvas;
use crate::pixelops::weighted_sum;

use ab_glyph::{point, Font, GlyphId, OutlinedGlyph, PxScale, Rect, ScaleFont};
use ab_glyph::{point, Font, GlyphId, OutlinedGlyph, PxScale, ScaleFont};

fn layout_glyphs(
scale: impl Into<PxScale> + Copy,
font: &impl Font,
text: &str,
mut f: impl FnMut(OutlinedGlyph, Rect),
mut f: impl FnMut(OutlinedGlyph, (i32, i32)),
) -> (u32, u32) {
if text.is_empty() {
return (0, 0);
}
let font = font.as_scaled(scale);

let mut w = 0f32;
let first_char = text.chars().next().unwrap();
let first_glyph = font.glyph_id(first_char);
let mut w = font.h_side_bearing(first_glyph).abs();
let mut prev: Option<GlyphId> = None;

for c in text.chars() {
Expand All @@ -28,11 +33,17 @@ fn layout_glyphs(
}
prev = Some(glyph_id);
let bb = g.px_bounds();
f(g, bb);
let bbx = bb.min.x as i32;
let bby = bb.min.y as i32;
f(g, (bbx, bby));
}
}

(w as u32, font.height() as u32)
let w = w.ceil();
let h = font.height().ceil();
assert!(w >= 0.0);
assert!(h >= 0.0);
(w as u32, h as u32)
}

/// Get the width and height of the given text, rendered with the given font and scale.
Expand Down Expand Up @@ -64,6 +75,7 @@ where
draw_text_mut(&mut out, color, x, y, scale, font, text);
out
}

#[doc=generate_mut_doc_comment!("draw_text")]
pub fn draw_text_mut<C>(
canvas: &mut C,
Expand All @@ -80,12 +92,12 @@ pub fn draw_text_mut<C>(
let image_width = canvas.width() as i32;
let image_height = canvas.height() as i32;

layout_glyphs(scale, font, text, |g, bb| {
let bbx = x + bb.min.x.round() as i32;
let bby = y + bb.min.y.round() as i32;
layout_glyphs(scale, font, text, |g, (bbx, bby)| {
let x_shift = x + bbx;
let y_shift = y + bby;
g.draw(|gx, gy, gv| {
let image_x = gx as i32 + bbx;
let image_y = gy as i32 + bby;
let image_x = gx as i32 + x_shift;
let image_y = gy as i32 + y_shift;

if (0..image_width).contains(&image_x) && (0..image_height).contains(&image_y) {
let image_x = image_x as u32;
Expand All @@ -98,3 +110,43 @@ pub fn draw_text_mut<C>(
})
});
}

//#[cfg(not(miri))]
#[cfg(test)]
mod proptests {
use super::*;
use crate::{
proptest_utils::arbitrary_image_with,
rect::{Rect, Region},
};
use ab_glyph::FontRef;
use image::Luma;
use proptest::prelude::*;

const FONT_BYTES: &[u8] = include_bytes!("../../tests/data/fonts/DejaVuSans.ttf");

proptest! {
#[test]
fn proptest_text_size(
x in 0..100,
y in 0..100,
scale in 0.0..100f32,
ref text in "[0-9a-zA-Z]*",
img in arbitrary_image_with::<Luma<u8>>(Just(0), 0..=100, 0..=100),
) {
let font = FontRef::try_from_slice(FONT_BYTES).unwrap();
let background = Luma([0]);
let text_color = Luma([255u8]);

let img = draw_text(&img, text_color, x, y, scale, &font, text);

let (text_w, text_h) = text_size(scale, &font, text);
let rect = Rect::at(x, y).of_size(1 + text_w, 1 + text_h); // TODO: fix Rect::contains
for (px, py, &p) in img.enumerate_pixels() {
if !rect.contains(px as i32, py as i32) {
assert_eq!(p, background, "pixel_position: {:?}, rect: {:?}", (px, py), rect);
}
}
}
}
}
Binary file modified tests/data/truth/text.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f8d8b62

Please sign in to comment.