104 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use std::ffi::{CStr, CString};
 | |
| 
 | |
| use anyhow::{anyhow, bail};
 | |
| use x11::{xft::{FcPattern, XftColor, XftFont, XftFontOpenName, XftFontOpenPattern, XftNameParse}, xlib::{CapButt, Cursor, Drawable, JoinMiter, LineSolid, Window, XCreateGC, XCreatePixmap, XDefaultDepth, XSetLineAttributes, _XDisplay, GC}};
 | |
| 
 | |
| 
 | |
| #[derive(Debug)]
 | |
| pub struct Drw {
 | |
|     w: i32,
 | |
|     h: i32,
 | |
|     display: *mut _XDisplay,
 | |
|     screen: i32,
 | |
|     drawable: Drawable,
 | |
|     gc: GC,
 | |
|     scheme: *mut Clr,
 | |
|     fontset: Vec<Fnt>,
 | |
|     root: Window,
 | |
| }
 | |
| 
 | |
| #[derive(Debug)]
 | |
| pub struct Cur {
 | |
|     cursor: Cursor,
 | |
| }
 | |
| 
 | |
| type Clr = XftColor;
 | |
| 
 | |
| #[derive(Debug)]
 | |
| pub struct Fnt {
 | |
|     display: *mut _XDisplay,
 | |
| 	h: i32,
 | |
| 	xfont: *mut XftFont,
 | |
| 	pattern: *mut FcPattern,
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| impl Drw {
 | |
|     pub fn new(display: *mut _XDisplay, screen: i32, root: Window, w: i32, h: i32, fonts: Vec<&str>) -> anyhow::Result<Self> {
 | |
|         unsafe { 
 | |
|             let mut s = Self {
 | |
|                 display,
 | |
|                 screen,
 | |
|                 root,
 | |
|                 w,
 | |
|                 h,
 | |
|                 drawable: Drawable::from(XCreatePixmap(display, root, w as u32, h as u32, XDefaultDepth(display, screen) as u32)),
 | |
|                 gc: XCreateGC(display, root, 0, std::ptr::null_mut()),
 | |
|                 fontset: Vec::new(),
 | |
|                 scheme: std::ptr::null_mut(),
 | |
|             };
 | |
|             XSetLineAttributes(display, s.gc, 1, LineSolid, CapButt, JoinMiter);
 | |
|             s.fontset = s.font_set_create(fonts)?;
 | |
|             Ok(s)
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     fn font_set_create(&mut self, fonts: Vec<&str>) -> anyhow::Result<Vec<Fnt>> {
 | |
|         let mut set = Vec::new();
 | |
|         for i in 1..=fonts.len() {
 | |
|             if let Ok(next) = unsafe { self.font_create(Some(fonts[fonts.len() - i]), std::ptr::null_mut()) } {
 | |
|                 set.push(next); 
 | |
|             }
 | |
|         }
 | |
|         Ok(set)
 | |
|     }
 | |
| 
 | |
|     unsafe fn font_create(&mut self, fontname: Option<&str>, fontpattern: *mut FcPattern) -> anyhow::Result<Fnt> {
 | |
|         let mut font: Fnt = std::mem::zeroed();
 | |
|         let xfont: *mut XftFont;
 | |
|         let mut pattern: *mut FcPattern = std::ptr::null_mut();
 | |
| 
 | |
|         if let Some(fontname) = fontname {
 | |
|             let font_name_c = CString::new(fontname)?.as_ptr();
 | |
|             xfont = XftFontOpenName(self.display, self.screen, font_name_c);
 | |
|             if xfont.is_null() {
 | |
|                 log::error!("Cannot load font from name {}", fontname);
 | |
|                 bail!("");
 | |
|             }
 | |
| 
 | |
|             pattern = XftNameParse(font_name_c);
 | |
|             if pattern.is_null() {
 | |
|                 log::error!("Cannot parse font name to pattern");
 | |
|                 bail!("");
 | |
|             }
 | |
|         } else if !fontpattern.is_null() {
 | |
|             xfont = XftFontOpenPattern(self.display, fontpattern);
 | |
|             if xfont.is_null() {
 | |
|                 log::error!("Cannot load font from pattern");
 | |
|                 bail!("");
 | |
|             }
 | |
|         } else {
 | |
|             log::error!("No font name specified"); 
 | |
|             bail!("");
 | |
|         }
 | |
|         
 | |
|         font.xfont = xfont;
 | |
|         font.pattern = pattern;
 | |
|         font.h = (*xfont).ascent + (*xfont).descent;
 | |
|         font.display = self.display;
 | |
|         Ok(font)
 | |
|     }
 | |
| 
 | |
| }
 |