mirror of https://github.com/Aloxaf/silicon
118 lines
3.0 KiB
Rust
118 lines
3.0 KiB
Rust
use anyhow::{ensure, Result};
|
|
use core::slice;
|
|
// font_kit already has a wrapper around freetype called Font so use it directly
|
|
use font_kit::font::Font;
|
|
use font_kit::loaders::freetype::NativeFont;
|
|
// use harfbuzz for shaping ligatures
|
|
pub use harfbuzz::*;
|
|
use harfbuzz_sys as harfbuzz;
|
|
use std::mem;
|
|
|
|
/// font feature tag
|
|
pub fn feature_from_tag(tag: &str) -> Result<hb_feature_t> {
|
|
unsafe {
|
|
let mut feature = mem::zeroed();
|
|
ensure!(
|
|
hb_feature_from_string(
|
|
tag.as_ptr() as *const ::std::os::raw::c_char,
|
|
tag.len() as i32,
|
|
&mut feature as *mut _
|
|
) != 0,
|
|
"hb_feature_from_string failed for {}",
|
|
tag
|
|
);
|
|
Ok(feature)
|
|
}
|
|
}
|
|
|
|
/// Harfbuzz font
|
|
pub struct HBFont {
|
|
font: *mut hb_font_t,
|
|
}
|
|
|
|
// harfbuzz freetype integration
|
|
extern "C" {
|
|
pub fn hb_ft_font_create_referenced(face: NativeFont) -> *mut hb_font_t; // the same as hb_face_t
|
|
}
|
|
|
|
impl Drop for HBFont {
|
|
fn drop(&mut self) {
|
|
unsafe { hb_font_destroy(self.font) }
|
|
}
|
|
}
|
|
|
|
impl HBFont {
|
|
pub fn new(face: &Font) -> HBFont {
|
|
HBFont {
|
|
font: unsafe { hb_ft_font_create_referenced(face.native_font() as _) },
|
|
}
|
|
}
|
|
pub fn shape(&mut self, buffer: &HBBuffer, features: &[hb_feature_t]) {
|
|
unsafe {
|
|
hb_shape(
|
|
self.font,
|
|
buffer.buffer,
|
|
features.as_ptr(),
|
|
features.len() as u32,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Harfbuzz buffer
|
|
pub struct HBBuffer {
|
|
buffer: *mut hb_buffer_t,
|
|
}
|
|
|
|
impl Drop for HBBuffer {
|
|
fn drop(&mut self) {
|
|
unsafe { hb_buffer_destroy(self.buffer) }
|
|
}
|
|
}
|
|
|
|
impl HBBuffer {
|
|
pub fn new() -> Result<HBBuffer> {
|
|
let hb_buf = unsafe { hb_buffer_create() };
|
|
ensure!(
|
|
unsafe { hb_buffer_allocation_successful(hb_buf) } != 0,
|
|
"hb_buffer_create failed!"
|
|
);
|
|
Ok(HBBuffer { buffer: hb_buf })
|
|
}
|
|
|
|
pub fn guess_segments_properties(&mut self) {
|
|
unsafe { hb_buffer_guess_segment_properties(self.buffer) };
|
|
}
|
|
|
|
pub fn add_utf8(&mut self, s: &[u8]) {
|
|
unsafe {
|
|
hb_buffer_add_utf8(
|
|
self.buffer,
|
|
s.as_ptr() as *const ::std::os::raw::c_char,
|
|
s.len() as i32,
|
|
0,
|
|
s.len() as i32,
|
|
);
|
|
}
|
|
}
|
|
pub fn add_str(&mut self, s: &str) {
|
|
self.add_utf8(s.as_bytes());
|
|
}
|
|
|
|
pub fn get_glyph_infos(&mut self) -> &[hb_glyph_info_t] {
|
|
unsafe {
|
|
let mut len: u32 = 0;
|
|
let info = hb_buffer_get_glyph_infos(self.buffer, &mut len as *mut u32);
|
|
slice::from_raw_parts(info, len as usize)
|
|
}
|
|
}
|
|
|
|
pub fn get_glyph_positions(&mut self) -> &[hb_glyph_position_t] {
|
|
unsafe {
|
|
let mut len: u32 = 0;
|
|
let info = hb_buffer_get_glyph_positions(self.buffer, &mut len as *mut u32);
|
|
slice::from_raw_parts(info, len as usize)
|
|
}
|
|
}
|
|
}
|