Use pango for text layout

This commit is contained in:
Armin Friedl 2021-10-31 18:38:19 +01:00
parent dc62753629
commit 673fef7c84
4 changed files with 88 additions and 18 deletions

53
Cargo.lock generated
View file

@ -909,6 +909,58 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "pango"
version = "0.14.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "546fd59801e5ca735af82839007edd226fe7d3bb06433ec48072be4439c28581"
dependencies = [
"bitflags",
"glib",
"libc",
"once_cell",
"pango-sys",
]
[[package]]
name = "pango-sys"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2367099ca5e761546ba1d501955079f097caa186bb53ce0f718dca99ac1942fe"
dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps",
]
[[package]]
name = "pangocairo"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f03ac1e8d456f8f436168aeac41201f0bf49d1dc6c8d01bfb04de2cca25df631"
dependencies = [
"bitflags",
"cairo-rs",
"glib",
"libc",
"pango",
"pangocairo-sys",
]
[[package]]
name = "pangocairo-sys"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3b9b679ad5c8503e3e533ce06e1619d033274b246e977a6fa1655a6c6ef2b51"
dependencies = [
"cairo-sys-rs",
"glib-sys",
"libc",
"pango-sys",
"system-deps",
]
[[package]]
name = "parking_lot"
version = "0.11.2"
@ -1099,6 +1151,7 @@ dependencies = [
"log",
"mlua",
"nix 0.23.0",
"pangocairo",
"rayon",
"walkdir",
"winit",

View file

@ -13,6 +13,7 @@ rayon = "1.5.1"
winit = {git="https://github.com/rust-windowing/winit"}
cairo-rs = {version = "0.14.0", features = ["xcb"]}
cairo-sys-rs = {version = "0.14.0", features = ["xcb"]}
pangocairo = "0.14.0"
xcb = "0.9.0"
xcb-util = {version = "0.3.0", features = ["ewmh", "icccm"]}

View file

@ -64,7 +64,7 @@ impl<'a> Painter<'a> {
ctx.fill().unwrap();
// draw text
ctx.move_to(x + 0.2, y + 0.8);
ctx.move_to(x + 0.2, y+0.8);
ctx.theme_text(&input, false, &[], &self.theme);
}

View file

@ -1,8 +1,11 @@
use log::debug;
use pangocairo::pango::{self, AttrList, Attribute, FontDescription};
// (r,g,b,a)
#[derive(Clone, Copy)]
pub struct Color(f64, f64, f64, f64);
// (name, size)
pub struct Font(String, f64);
pub struct Font(String, i32);
struct ColorScheme {
base: Color,
@ -44,7 +47,7 @@ impl Default for Theme {
Theme {
colors,
font: Font("sans".into(), 17.0),
font: Font("Sans Regular".into(), 13),
border: 2.0,
divider: 3.0
@ -94,27 +97,40 @@ impl ThemedContextExt for cairo::Context {
}
fn theme_text(&self, text: &str, selected: bool, indices: &[usize], theme: &Theme) {
self.save().unwrap();
self.identity_matrix(); // this is extremely important otherwise pango
// gets totally confused by active cairo transformations
// which then messes with font size, size of attributes, etc
let Color(r,g,b,a) = if selected { theme.colors.text_highlight }
else { theme.colors.text };
self.set_source_rgba(r,g,b,a);
let font_size = self.device_to_user_point(theme.font.1);
self.set_font_size(font_size);
let layout = pangocairo::create_layout(self).unwrap();
pangocairo::update_layout(self, &layout);
for i in 0..text.len() {
if indices.contains(&i) {
self.select_font_face(&theme.font.0,
cairo::FontSlant::Italic,
cairo::FontWeight::Normal);
} else {
self.select_font_face(&theme.font.0,
cairo::FontSlant::Normal,
cairo::FontWeight::Normal);
}
self.show_text(&text[i..i+1])
.expect("Could not draw themed text");
let attrlist = AttrList::new();
for i in indices {
let (start, end) = ((*i as u32), (*i as u32)+1);
let mut attr = Attribute::new_underline(pangocairo::pango::Underline::Single);
attr.set_start_index(start);
attr.set_end_index(end);
attrlist.insert(attr);
}
layout.set_attributes(Some(&attrlist));
let mut font = FontDescription::default();
font.set_family(&theme.font.0);
font.set_size(theme.font.1*pango::SCALE);
layout.set_font_description(Some(&font));
layout.set_text(text);
let (_width,height) = layout.size();
self.rel_move_to(0.0, -(height as f64)/(pango::SCALE as f64));
pangocairo::show_layout(self, &layout);
self.restore().unwrap();
}
fn device_to_user_point(&self, point: f64) -> f64 {