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.
This commit is contained in:
parent
8ae15780b7
commit
70775b8350
1 changed files with 52 additions and 20 deletions
|
|
@ -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<u8>,
|
||||
y: usize,
|
||||
}
|
||||
|
||||
pub struct Graphics<D: Display> {
|
||||
disp: D,
|
||||
fonts: Vec<(String, freetype::FT_Long)>,
|
||||
fontbufs: Vec<Vec<u8>>,
|
||||
labels: HashMap<String, ImgVec<u8>>,
|
||||
sublabels: HashMap<String, ImgVec<u8>>,
|
||||
labels: HashMap<String, TextRaster>,
|
||||
sublabels: HashMap<String, TextRaster>,
|
||||
ft: AtomicPtr<freetype::FT_LibraryRec_>,
|
||||
|
||||
x_scale: f64,
|
||||
|
|
@ -279,7 +285,7 @@ impl<D: Display> Graphics<D> {
|
|||
ftface
|
||||
}
|
||||
|
||||
fn rasterize_text(&mut self, size: f64, text: &str) -> ImgVec<u8>
|
||||
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<D: Display> Graphics<D> {
|
|||
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<u8> = 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<D: Display> Graphics<D> {
|
|||
}
|
||||
|
||||
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<D: Display> Graphics<D> {
|
|||
};
|
||||
|
||||
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<D: Display> Graphics<D> {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw_label_part(labels: &HashMap<String, ImgVec<u8>>,
|
||||
fn draw_label_part(labels: &HashMap<String, TextRaster>,
|
||||
x_anchor: Anchor, y_anchor: Anchor,
|
||||
img: &mut ImgRefMut<BGRA<u8>>,
|
||||
dest: &mut ImgRefMut<BGRA<u8>>,
|
||||
label: &str, fg_color: BGR<f32>)
|
||||
{
|
||||
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<D: Display> Graphics<D> {
|
|||
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<D: Display> Graphics<D> {
|
|||
color_label
|
||||
}
|
||||
|
||||
fn draw_key(labels: &HashMap<String, ImgVec<u8>>,
|
||||
sublabels: &HashMap<String, ImgVec<u8>>,
|
||||
fn draw_key(labels: &HashMap<String, TextRaster>,
|
||||
sublabels: &HashMap<String, TextRaster>,
|
||||
x_scale: f64, y_scale: f64,
|
||||
img: &mut ImgRefMut<BGRA<u8>>,
|
||||
key: &Key, mod_state: &[ModState])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue