Try to improve rendering (positioning) of signed field distance font. (#6868)

* WIP: swrenderer: use fixed point for the pixmap font coordinate

* swrenderer: signed distance field: move the glyph to the middle

* swrenderer: round the advance instead of truncating it in distance field

* swrenderer: actually align the gplyph on the sub-pixel precision

sub-pixel within the source.

* swrenderer: adapt the threshold for signed distance field

sqrt(2) is the distance to the diagonal, seems like this gives sharper fonts

* Fix bug in the elision, and re-upload the screenshort

the screenshot changed because the afvanced is now rounded intead of
truncated
This commit is contained in:
Olivier Goffart 2024-11-30 23:03:31 +01:00 committed by GitHub
parent 17dd773d21
commit 4e7bbcf2ba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 87 additions and 56 deletions

View file

@ -420,11 +420,11 @@ fn embed_alpha_map_glyphs(
.unwrap_or_else(|| font.rasterize(*code_point, *pixel_size as _));
BitmapGlyph {
x: i16::try_from(metrics.xmin).expect("large glyph x coordinate"),
y: i16::try_from(metrics.ymin).expect("large glyph y coordinate"),
x: i16::try_from(metrics.xmin * 64).expect("large glyph x coordinate"),
y: i16::try_from(metrics.ymin * 64).expect("large glyph y coordinate"),
width: i16::try_from(metrics.width).expect("large width"),
height: i16::try_from(metrics.height).expect("large height"),
x_advance: i16::try_from(metrics.advance_width as i64)
x_advance: i16::try_from((metrics.advance_width * 64.) as i64)
.expect("large advance width"),
data: bitmap,
}
@ -467,15 +467,6 @@ fn embed_sdf_glyphs(
.unwrap_or_else(|| {
generate_sdf_for_glyph(font, *code_point, target_pixel_size, RANGE)
})
.map(|(metrics, bitmap)| BitmapGlyph {
x: i16::try_from(metrics.xmin).expect("large glyph x coordinate"),
y: i16::try_from(metrics.ymin).expect("large glyph y coordinate"),
width: i16::try_from(metrics.width).expect("large width"),
height: i16::try_from(metrics.height).expect("large height"),
x_advance: i16::try_from(metrics.advance_width as i64)
.expect("large advance width"),
data: bitmap,
})
.unwrap_or_default()
})
.collect::<Vec<_>>();
@ -489,7 +480,7 @@ fn generate_sdf_for_glyph(
code_point: char,
target_pixel_size: i16,
range: f64,
) -> Option<(fontdue::Metrics, Vec<u8>)> {
) -> Option<BitmapGlyph> {
use fdsm::transform::Transform;
use nalgebra::{Affine2, Similarity2, Vector2};
@ -505,11 +496,10 @@ fn generate_sdf_for_glyph(
// TODO: handle bitmap glyphs (emojis)
let Some(bbox) = face.glyph_bounding_box(glyph_id) else {
// For example, for space
let metrics = fontdue::Metrics {
advance_width: (face.glyph_hor_advance(glyph_id).unwrap_or(0) as f64 * scale) as f32,
return Some(BitmapGlyph {
x_advance: (face.glyph_hor_advance(glyph_id).unwrap_or(0) as f64 * scale * 64.) as i16,
..Default::default()
};
return Some((metrics, vec![]));
});
};
let width = ((bbox.x_max as f64 - bbox.x_min as f64) * scale + 2.).ceil() as u32;
@ -556,17 +546,21 @@ fn generate_sdf_for_glyph(
// (so that the last row will look like `data[len-1]*1 + data[len]*0`)
glyph_data.push(0);
let metrics = fontdue::Metrics {
xmin: -(1. - bbox.x_min as f64 * scale).round() as i32,
ymin: -(1. - bbox.y_min as f64 * scale).round() as i32,
width: width as usize,
height: height as usize,
advance_width: (face.glyph_hor_advance(glyph_id).unwrap() as f64 * scale) as f32,
advance_height: 0., /*unused */
bounds: Default::default(), /*unused */
let bg = BitmapGlyph {
x: i16::try_from((-(1. - bbox.x_min as f64 * scale) * 64.).ceil() as i32)
.expect("large glyph x coordinate"),
y: i16::try_from((-(1. - bbox.y_min as f64 * scale) * 64.).ceil() as i32)
.expect("large glyph y coordinate"),
width: i16::try_from(width).expect("large width"),
height: i16::try_from(height).expect("large height"),
x_advance: i16::try_from(
(face.glyph_hor_advance(glyph_id).unwrap() as f64 * scale * 64.).round() as i32,
)
.expect("large advance width"),
data: glyph_data,
};
Some((metrics, glyph_data))
Some(bg)
}
fn try_extract_font_size_from_element(elem: &ElementRc, property_name: &str) -> Option<f64> {