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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" 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]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.11.2" version = "0.11.2"
@ -1099,6 +1151,7 @@ dependencies = [
"log", "log",
"mlua", "mlua",
"nix 0.23.0", "nix 0.23.0",
"pangocairo",
"rayon", "rayon",
"walkdir", "walkdir",
"winit", "winit",

View file

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

View file

@ -1,8 +1,11 @@
use log::debug;
use pangocairo::pango::{self, AttrList, Attribute, FontDescription};
// (r,g,b,a) // (r,g,b,a)
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Color(f64, f64, f64, f64); pub struct Color(f64, f64, f64, f64);
// (name, size) // (name, size)
pub struct Font(String, f64); pub struct Font(String, i32);
struct ColorScheme { struct ColorScheme {
base: Color, base: Color,
@ -44,7 +47,7 @@ impl Default for Theme {
Theme { Theme {
colors, colors,
font: Font("sans".into(), 17.0), font: Font("Sans Regular".into(), 13),
border: 2.0, border: 2.0,
divider: 3.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) { 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 } let Color(r,g,b,a) = if selected { theme.colors.text_highlight }
else { theme.colors.text }; else { theme.colors.text };
self.set_source_rgba(r,g,b,a); self.set_source_rgba(r,g,b,a);
let font_size = self.device_to_user_point(theme.font.1); let layout = pangocairo::create_layout(self).unwrap();
self.set_font_size(font_size); pangocairo::update_layout(self, &layout);
for i in 0..text.len() { let attrlist = AttrList::new();
if indices.contains(&i) { for i in indices {
self.select_font_face(&theme.font.0, let (start, end) = ((*i as u32), (*i as u32)+1);
cairo::FontSlant::Italic, let mut attr = Attribute::new_underline(pangocairo::pango::Underline::Single);
cairo::FontWeight::Normal); attr.set_start_index(start);
} else { attr.set_end_index(end);
self.select_font_face(&theme.font.0, attrlist.insert(attr);
cairo::FontSlant::Normal,
cairo::FontWeight::Normal);
} }
layout.set_attributes(Some(&attrlist));
self.show_text(&text[i..i+1]) let mut font = FontDescription::default();
.expect("Could not draw themed text"); 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 { fn device_to_user_point(&self, point: f64) -> f64 {