From 70775b8350be257df8173d2386d2cff3b4fccf4e Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Mon, 19 Aug 2024 19:28:53 -0400 Subject: [PATCH] core: graphics: adjust size for glyphs outside regular vertical bounds Some glyphs, specifically some Arabic text, may have a top that is higher than the ascent value of the font, or a bottom that is lower than the descent value of the font. For glyphs that fit inside the area, the ascent and descent should be used for aligning with the top or bottom of a key respectively. For glyphs that do not, align the top and bottom of the text with the top and bottom of the key. --- src/core/graphics.rs | 72 ++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/src/core/graphics.rs b/src/core/graphics.rs index 4fab16f..62c6d9b 100644 --- a/src/core/graphics.rs +++ b/src/core/graphics.rs @@ -16,6 +16,7 @@ use rgb::alt::BGRA; use std::collections::HashMap; use std::fs::File; use std::io::Read; +use std::cmp; use std::iter; use std::ptr; use std::sync::atomic::AtomicPtr; @@ -73,12 +74,17 @@ pub trait Display { fn end(&mut self, x: u32, y: u32, width: u32, height: u32); } +struct TextRaster { + img: ImgVec, + y: usize, +} + pub struct Graphics { disp: D, fonts: Vec<(String, freetype::FT_Long)>, fontbufs: Vec>, - labels: HashMap>, - sublabels: HashMap>, + labels: HashMap, + sublabels: HashMap, ft: AtomicPtr, x_scale: f64, @@ -279,7 +285,7 @@ impl Graphics { ftface } - fn rasterize_text(&mut self, size: f64, text: &str) -> ImgVec + fn rasterize_text(&mut self, size: f64, text: &str) -> TextRaster { let ftface = self.open_font_for_text(text).unwrap(); unsafe { @@ -303,12 +309,26 @@ impl Graphics { metrics.max_advance as usize / 64 * (text.len() - 1) + glyph_width }; - let height = (metrics.ascender - metrics.descender) as usize / 64; + let y_max = cmp::max(metrics.ascender as isize / 64, + bbox.yMax as isize + * metrics.y_ppem as isize + / units_per_em as isize); + let y_min = cmp::min(metrics.descender as isize / 64, + bbox.yMin as isize + * metrics.y_ppem as isize + / units_per_em as isize); + let mut y = y_max as usize - metrics.ascender as usize / 64; + let height = (y_max - y_min) as usize; + + println!("{} {}, {}", (-bbox.yMin) as usize, + metrics.y_ppem as usize, + metrics.descender); let vec: Vec = vec![0; stride * height]; let mut img = ImgVec::new(vec, stride, height); let mut pen: i64 = 0; + let mut height = (y_max as i64 - metrics.descender / 64) as usize; for c in text.chars() { let glyph = unsafe { @@ -323,7 +343,11 @@ impl Graphics { } let dest_x = pen + glyph.bitmap_left as i64; - let dest_y = metrics.ascender / 64 - glyph.bitmap_top as i64; + let dest_y = y_max as i64 - glyph.bitmap_top as i64; + + if y > dest_y as usize { + y = dest_y as usize; + } let src = bitmap_to_imgref(&glyph.bitmap); let dest = img.sub_image_mut(dest_x as usize, @@ -347,7 +371,14 @@ impl Graphics { }; let vec = img.into_buf(); - ImgVec::new_stride(vec, width, height, stride) + println!("{}, {}x{}", vec.len(), stride, height); + let img = ImgVec::new_stride(vec, width, height, stride); + img.sub_image(0, 0, width, height - y); + + TextRaster { + img, + y, + } } /* @@ -420,31 +451,31 @@ impl Graphics { } } - fn draw_label_part(labels: &HashMap>, + fn draw_label_part(labels: &HashMap, x_anchor: Anchor, y_anchor: Anchor, - img: &mut ImgRefMut>, + dest: &mut ImgRefMut>, label: &str, fg_color: BGR) { let src = labels.get(label) .expect("Layout and size should be set before drawing"); + let width = src.img.width(); + let height = src.img.height() - src.y; + let x = match x_anchor { Anchor::Min => 0, - Anchor::Center => (img.width() - src.width()) / 2, - Anchor::Max => img.width() - src.width(), + Anchor::Center => (dest.width() - width) / 2, + Anchor::Max => dest.width() - width, }; let y = match y_anchor { Anchor::Min => 0, - Anchor::Center => (img.height() - src.height()) / 2, - Anchor::Max => img.height() - src.height(), + Anchor::Center => (dest.height() - height) / 2, + Anchor::Max => dest.height() - height, }; - let width = src.width(); - let height = src.height(); - - let src = src.sub_image(0, 0, width, height); - let dest = img.sub_image_mut(x, y, width, height); + let src = src.img.sub_image(0, src.y, width, height); + let dest = dest.sub_image_mut(x, y, width, height); convert_gray_to_bgrx(dest, src, fg_color); } @@ -461,7 +492,8 @@ impl Graphics { if modifier != 0 { let modifier = modifier - 1; if mod_state[modifier] == ModState::Locked - || mod_state[modifier] == ModState::HeldLocked { + || mod_state[modifier] == ModState::HeldLocked + || mod_state[modifier] == ModState::HeldLockedPressed { return color_locked; } else if mod_state[modifier] != ModState::Released { return color_pressed; @@ -487,8 +519,8 @@ impl Graphics { color_label } - fn draw_key(labels: &HashMap>, - sublabels: &HashMap>, + fn draw_key(labels: &HashMap, + sublabels: &HashMap, x_scale: f64, y_scale: f64, img: &mut ImgRefMut>, key: &Key, mod_state: &[ModState])