Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions src/drawing/text.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use image::{GenericImage, Pixel};
use num::Zero;
use std::f32;

use crate::definitions::{Clamp, Image};
Expand All @@ -21,6 +22,39 @@ fn layout_glyphs(
let mut w = 0.0;
let mut prev: Option<GlyphId> = None;

let mut y_max = 0.0_f32;
let mut y_min = 0.0_f32;
let mut y_above_ascent = 0.0_f32;
let mut y_below_ascent = f32::MAX;

// Find the peak `y_above_ascent` value which above ascent across all glyphs
// And the minimum `y_below_ascent` value which below ascent across all glyphs
for c in text.chars() {
let glyph_id = font.glyph_id(c);
let glyph = glyph_id.with_scale_and_position(scale, point(w, font.ascent()));
if let Some(g) = font.outline_glyph(glyph) {
let bb = g.px_bounds();

// for correct offset
y_above_ascent = y_above_ascent.min(bb.min.y);
y_below_ascent = y_below_ascent.min(bb.min.y).max(0.0);

// for correct height
y_min = y_min.min(bb.min.y);
y_max = y_max.max(bb.max.y);
}
}

// height and remove overflow ascent
let h = y_max - y_min - y_below_ascent;

// select offset
let offset_y = if y_above_ascent.is_zero() {
y_below_ascent
} else {
y_above_ascent
};

for c in text.chars() {
let glyph_id = font.glyph_id(c);
let glyph = glyph_id.with_scale_and_position(scale, point(w, font.ascent()));
Expand All @@ -30,13 +64,15 @@ fn layout_glyphs(
w += font.kern(glyph_id, prev);
}
prev = Some(glyph_id);
let bb = g.px_bounds();
let mut bb = g.px_bounds();
bb.min.y -= offset_y;
bb.max.y -= offset_y;
f(g, bb);
}
}

let w = w.ceil();
let h = font.height().ceil();
let h = h.ceil();
assert!(w >= 0.0);
assert!(h >= 0.0);
(1 + w as u32, h as u32)
Expand Down
Binary file added tests/data/truth/overflow_glyph_number.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/data/truth/overflow_glyph_out.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/data/truth/overflow_glyph_symbol.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/data/truth/overflow_glyph_symbols.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions tests/regression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,3 +1021,44 @@ fn test_draw_text_with_alpha() {

compare_to_truth("elephant.png", "text_alpha.png", draw_text_with_alpha);
}

#[test]
#[cfg(feature = "text")]
fn test_draw_text_without_overflow_glyphs() {
use image::RgbaImage;

fn txt_img(word: &str) -> RgbaImage {
let mplantin = include_bytes!("data/fonts/DejaVuSans.ttf");
let mplantin = ab_glyph::FontArc::try_from_slice(mplantin).unwrap();

let font_size = 128.0;

let (w, h) = imageproc::drawing::text_size(font_size, &mplantin, word);
let mut image: DynamicImage = DynamicImage::new_rgba8(w, h);

imageproc::drawing::draw_text_mut(
&mut image,
image::Rgba([100u8, 100u8, 100u8, 255u8]),
0,
0,
font_size,
&mplantin,
word,
);

image.to_rgba8()
}

let words = [
("ÁÄAaaa", "out"),
("A", "symbol"),
("Äabcpghky", "symbols"),
("abcpghky", "symbols_little"),
("1.", "number"),
];

for (word, filename) in words {
let img = txt_img(word);
compare_to_truth_image(&img, &format!("overflow_glyph_{}.png", filename));
}
}
Loading