Closed john01dav closed 4 years ago
Have you tried rounding your x_pos
and y_pos
variables before converting them to usize
?
I'm aware of the positioning challenges for smaller font sizes. Adding a proper layout utility in fontdue will happen before 1.0 and I'll address this issue.
Turns out the issue was I'm aligning to the wrong baseline during rasterization. I'll have a fix out soonish, along with some more subpixel positioning options for people rolling their own layout before Fontdue's is finished.
Yeah I have it fixed locally. There's some optimization work I need to do because it added 30ns to raster to calculate the alignment.
I just pushed it,
@mooman219 I'm having some trouble using the new fix. Would you be willing to look at my rendering code briefly? I'm not a font expert, so I suspect that there's some error in my code wrt how I'm using your library. Thank you!
Output:
Code (the second function, render
, is the important bit):
use fontdue::{Metrics, Font, FontSettings};
use crate::error::Result;
use crate::bitmap::Bitmap;
use crate::bitmap::Color;
pub struct TextData{
font: Font,
chars: Vec<CharData>,
total_width: usize,
}
struct CharData{
metrics: Metrics,
bitmap: Vec<u8>,
}
impl TextData{
pub fn rasterize_string(string: &str, font_size: f32) -> Result<TextData>{
let font = include_bytes!("roboto/Roboto-Regular.ttf") as &[u8];
let font = Font::from_bytes(font, FontSettings::default()).unwrap();
let mut text_data = TextData{
font, chars: Vec::new(), total_width: 0
};
for c in string.chars(){
let (metrics, bitmap) = text_data.font.rasterize(c, font_size, 0.0);
text_data.chars.push(CharData{
metrics, bitmap
});
text_data.total_width += metrics.advance_width as usize;
}
Ok(text_data)
}
pub fn render(&self, bitmap: &mut Bitmap, x: usize, y: usize){
let xf = x as f32;
let yf = y as f32;
let mut x_offset: f32 = 0.0;
for char_data in &self.chars{
let xmin = char_data.metrics.bounds.xmin;
let ymax = char_data.metrics.bounds.ymax;
for cx in 0..char_data.metrics.width{
for cy in 0..char_data.metrics.height{
let intensity = char_data.bitmap[cy*char_data.metrics.width+cx];
let x_pos = xf+x_offset+(cx as f32)+xmin;
let y_pos = yf+(cy as f32)-ymax;
if x_pos >= 0.0 && y_pos >= 0.0 {
bitmap.set_pixel(x_pos as usize, y_pos as usize, Color::new(intensity, intensity, intensity));
}
}
}
x_offset += char_data.metrics.advance_width;
}
}
}
At a glance, I believe it's to do with not flooring your y positions at the right spot, but the root of the issue is that proper layout is actually just hard (several hundred lines and some state management). I'm implementing a proper layout utility for the next revision so Fontdue will handle it for you.
Thanks for your help! I have a few things to say/ask in response to what you said:
Spanish uses some accented letters that don't exist in English. These include "í" "ó" and "á". Consider the sample string:
As can be seen when Github+Firefox render this string, the vertical alignment of the accented letters is fine. Yet, when I render this same string using fontdue, the letters are slightly lower than they should be, but only with smaller font sizes.
Font size 12:
Font size 17:
Font size 22:
This is the code that handles the rendering: