diff --git a/Cargo.lock b/Cargo.lock index 454b0b1..cd860c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/Cargo.toml b/Cargo.toml index 45fe7c1..34aacef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"]} diff --git a/src/ui/painter.rs b/src/ui/painter.rs index 4620947..7f9b420 100644 --- a/src/ui/painter.rs +++ b/src/ui/painter.rs @@ -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); } diff --git a/src/ui/theme.rs b/src/ui/theme.rs index 344d4c0..adfc9e6 100644 --- a/src/ui/theme.rs +++ b/src/ui/theme.rs @@ -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 {