use core::cell::UnsafeCell;
use core::mem::MaybeUninit;
use core::ptr::addr_of;
use oxivgl_sys::{lv_font_glyph_dsc_t, lv_font_get_glyph_dsc_fmt_txt, lv_font_t};
#[derive(Copy, Clone, Debug)]
pub struct Font(pub(crate) *const lv_font_t);
unsafe impl Send for Font {}
unsafe impl Sync for Font {}
impl Font {
pub const unsafe fn from_raw(ptr: *const lv_font_t) -> Self {
Font(ptr)
}
pub const unsafe fn from_extern(ptr: *const ()) -> Self {
Font(ptr as *const lv_font_t)
}
pub fn as_ptr(self) -> *const lv_font_t {
self.0
}
}
pub static DEJAVU_16_PERSIAN_HEBREW: Font =
Font(addr_of!(oxivgl_sys::lv_font_dejavu_16_persian_hebrew));
pub static SOURCE_HAN_SANS_SC_14_CJK: Font =
Font(addr_of!(oxivgl_sys::lv_font_source_han_sans_sc_14_cjk));
pub static SOURCE_HAN_SANS_SC_16_CJK: Font =
Font(addr_of!(oxivgl_sys::lv_font_source_han_sans_sc_16_cjk));
pub struct FixedWidthFont {
inner: UnsafeCell<MaybeUninit<lv_font_t>>,
}
unsafe impl Send for FixedWidthFont {}
unsafe impl Sync for FixedWidthFont {}
impl FixedWidthFont {
pub const fn new() -> Self {
Self {
inner: UnsafeCell::new(MaybeUninit::zeroed()),
}
}
pub fn init(&self, source: Font, advance_w: u16) -> Font {
unsafe {
let font_ptr = self.inner.get();
core::ptr::copy_nonoverlapping(source.as_ptr(), (*font_ptr).as_mut_ptr(), 1);
let font = (*font_ptr).as_mut_ptr();
(*font).get_glyph_dsc = Some(fixed_width_get_glyph_dsc);
(*font).user_data = advance_w as usize as *mut core::ffi::c_void;
Font((*font_ptr).as_ptr())
}
}
}
unsafe extern "C" fn fixed_width_get_glyph_dsc(
font: *const lv_font_t,
dsc: *mut lv_font_glyph_dsc_t,
letter: u32,
letter_next: u32,
) -> bool {
unsafe {
let ret = lv_font_get_glyph_dsc_fmt_txt(font, dsc, letter, letter_next);
if !ret {
return false;
}
let adv = (*font).user_data as usize as u16;
(*dsc).adv_w = adv;
(*dsc).ofs_x = (adv as i16 - (*dsc).box_w as i16) / 2;
true
}
}
pub static MONTSERRAT_8: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_8));
pub static MONTSERRAT_10: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_10));
pub static MONTSERRAT_12: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_12));
pub static MONTSERRAT_14: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_14));
pub static MONTSERRAT_16: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_16));
pub static MONTSERRAT_18: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_18));
pub static MONTSERRAT_20: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_20));
pub static MONTSERRAT_22: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_22));
pub static MONTSERRAT_24: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_24));
pub static MONTSERRAT_26: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_26));
pub static MONTSERRAT_28: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_28));
pub static MONTSERRAT_30: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_30));
pub static MONTSERRAT_32: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_32));
pub static MONTSERRAT_34: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_34));
pub static MONTSERRAT_36: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_36));
pub static MONTSERRAT_38: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_38));
pub static MONTSERRAT_40: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_40));
pub static MONTSERRAT_42: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_42));
pub static MONTSERRAT_44: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_44));
pub static MONTSERRAT_46: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_46));
pub static MONTSERRAT_48: Font = Font(addr_of!(oxivgl_sys::lv_font_montserrat_48));
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn font_as_ptr_nonnull() {
assert!(!MONTSERRAT_12.as_ptr().is_null());
assert!(!MONTSERRAT_14.as_ptr().is_null());
assert!(!MONTSERRAT_20.as_ptr().is_null());
assert!(!MONTSERRAT_48.as_ptr().is_null());
}
#[test]
fn font_copy_clone() {
let f = MONTSERRAT_12;
let g = f;
assert_eq!(f.as_ptr(), g.as_ptr());
let h = f;
assert_eq!(f.as_ptr(), h.as_ptr());
}
#[test]
fn font_debug_fmt() {
let s = format!("{:?}", MONTSERRAT_14);
assert!(!s.is_empty());
}
#[test]
fn font_from_extern() {
let ptr = MONTSERRAT_12.as_ptr() as *const ();
let f = unsafe { Font::from_extern(ptr) };
assert_eq!(f.as_ptr(), MONTSERRAT_12.as_ptr());
}
#[test]
fn fixed_width_font_new_is_const() {
static FW: FixedWidthFont = FixedWidthFont::new();
let _ = &FW;
}
}