Skip to content

Commit

Permalink
Mac stuff!
Browse files Browse the repository at this point in the history
  • Loading branch information
CraftSpider committed Mar 20, 2024
1 parent f1eed93 commit 04e3c2b
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 83 deletions.
30 changes: 30 additions & 0 deletions crates/xetex_layout/src/c_api/fc/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,36 @@ impl PatParam for Index {
}
}

pub struct Weight(());

impl PatParam for Weight {
type Output<'a> = i32;

fn get(pat: &Pattern, idx: usize) -> Result<Self::Output<'_>, FcErr> {
unsafe { get_int(pat.0.as_ptr(), sys::FC_WEIGHT, idx as libc::c_int) }
}
}

pub struct Width(());

impl PatParam for Width {
type Output<'a> = i32;

fn get(pat: &Pattern, idx: usize) -> Result<Self::Output<'_>, FcErr> {
unsafe { get_int(pat.0.as_ptr(), sys::FC_WIDTH, idx as libc::c_int) }
}
}

pub struct Slant(());

impl PatParam for Slant {
type Output<'a> = i32;

fn get(pat: &Pattern, idx: usize) -> Result<Self::Output<'_>, FcErr> {
unsafe { get_int(pat.0.as_ptr(), sys::FC_SLANT, idx as libc::c_int) }
}
}

#[derive(Clone, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct Pattern(NonNull<sys::FcPattern>);
Expand Down
62 changes: 59 additions & 3 deletions crates/xetex_layout/src/c_api/manager.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use crate::c_api::{Fixed, PlatformFontRef, RawPlatformFontRef, XeTeXFont};
use crate::c_api::font::XeTeXFontBase;
use crate::c_api::{Fixed, PlatformFontRef, RawPlatformFontRef, RsFix2D, XeTeXFont};
use std::borrow::Cow;
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::ptr;
use tectonic_bridge_freetype2::{FT_Sfnt_Tag, TT_Header, TT_Postscript, TT_OS2};
use tectonic_bridge_harfbuzz::{hb_font_get_face, hb_ot_layout_get_size_params};

#[cfg(not(target_os = "macos"))]
Expand Down Expand Up @@ -105,12 +108,65 @@ pub struct NameCollection {
pub trait FontManagerBackend {
unsafe fn initialize(&mut self);
unsafe fn terminate(&mut self);
fn get_platform_font_desc<'a>(&'a self, font: &'a PlatformFontRef) -> &'a CStr;
unsafe fn get_platform_font_desc<'a>(&'a self, font: &'a PlatformFontRef) -> Cow<'a, CStr>;
unsafe fn get_op_size_rec_and_style_flags(&self, font: &mut Font);
unsafe fn search_for_host_platform_fonts(&mut self, maps: &mut FontMaps, name: &CStr);
unsafe fn read_names(&self, font: PlatformFontRef) -> NameCollection;
}

unsafe fn base_get_op_size_rec_and_style_flags(font: &mut Font) {
let mut xfont = match XeTeXFontBase::new(font.font_ref.clone(), 10.0) {
Ok(xfont) => xfont,
Err(_) => return,
};

let size_rec = FontManager::get_op_size(&mut xfont);
if let Some(size_rec) = size_rec {
font.op_size_info.design_size = size_rec.design_size;
if size_rec.sub_family_id != 0
|| size_rec.name_code != 0
|| size_rec.min_size != 0.0
|| size_rec.max_size != 0.0
{
font.op_size_info.sub_family_id = size_rec.sub_family_id;
font.op_size_info.name_code = size_rec.name_code;
font.op_size_info.min_size = size_rec.min_size;
font.op_size_info.max_size = size_rec.max_size;
}
}

let os2_table = xfont.get_font_table(FT_Sfnt_Tag::Os2).cast::<TT_OS2>();
if !os2_table.is_null() {
font.weight = (*os2_table).usWeightClass;
font.width = (*os2_table).usWidthClass;
let sel = (*os2_table).fsSelection;
font.is_reg = (sel & (1 << 6)) != 0;
font.is_bold = (sel & (1 << 5)) != 0;
font.is_italic = (sel & (1 << 0)) != 0;
}

let head_table = xfont.get_font_table(FT_Sfnt_Tag::Head).cast::<TT_Header>();
if !head_table.is_null() {
let ms = (*head_table).Mac_Style;
if (ms & (1 << 0)) != 0 {
font.is_bold = true;
}
if (ms & (1 << 1)) != 0 {
font.is_italic = true;
}
}

let post_table = xfont
.get_font_table(FT_Sfnt_Tag::Post)
.cast::<TT_Postscript>();
if !post_table.is_null() {
font.slant = (1000.0
* (f64::tan(
RsFix2D((-(*post_table).italic_angle) as Fixed) * std::f64::consts::PI / 180.0,
))) as _;
}
}

#[derive(Default)]
pub struct FontMaps {
name_to_font: HashMap<CString, *mut Font>,
Expand Down Expand Up @@ -709,7 +765,7 @@ impl FontManager {
.search_for_host_platform_fonts(&mut self.maps, name)
}

pub unsafe fn get_platform_font_desc<'a>(&'a self, font: &'a PlatformFontRef) -> &'a CStr {
pub unsafe fn get_platform_font_desc<'a>(&'a self, font: &'a PlatformFontRef) -> Cow<'a, CStr> {
self.backend.get_platform_font_desc(font)
}

Expand Down
74 changes: 20 additions & 54 deletions crates/xetex_layout/src/c_api/manager/fc.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
use super::{Font, FontManager, FontManagerBackend, FontMaps, NameCollection};
use super::{
base_get_op_size_rec_and_style_flags, Font, FontManager, FontManagerBackend, FontMaps,
NameCollection,
};
use crate::c_api::fc::sys::{
FcConfigGetCurrent, FcFalse, FcFontList, FcFontSet, FcFontSetDestroy, FcInit, FcObjectSetBuild,
FcObjectSetDestroy, FC_FAMILY, FC_FILE, FC_FONTFORMAT, FC_FULLNAME, FC_INDEX, FC_SLANT,
FC_STYLE, FC_WEIGHT, FC_WIDTH,
};
use crate::c_api::font::XeTeXFontBase;
use crate::c_api::{fc, Fixed, PlatformFontRef, RsFix2D};
use crate::c_api::{fc, PlatformFontRef};
use std::borrow::Cow;
use std::cell::{Cell, RefCell};
use std::ffi::{CStr, CString};
use std::ptr;
use tectonic_bridge_freetype2::{
FT_Done_Face, FT_Get_Postscript_Name, FT_Get_Sfnt_Name, FT_Get_Sfnt_Name_Count,
FT_Init_FreeType, FT_Library, FT_New_Face, FT_SfntName, FT_Sfnt_Tag, TT_Header, TT_Postscript,
FT_IS_SFNT, TT_MAC_ID_ROMAN, TT_OS2, TT_PLATFORM_APPLE_UNICODE, TT_PLATFORM_MACINTOSH,
TT_PLATFORM_MICROSOFT,
FT_Init_FreeType, FT_Library, FT_New_Face, FT_SfntName, FT_IS_SFNT, TT_MAC_ID_ROMAN,
TT_PLATFORM_APPLE_UNICODE, TT_PLATFORM_MACINTOSH, TT_PLATFORM_MICROSOFT,
};
use tectonic_bridge_icu::{
ucnv_close, ucnv_fromUChars, ucnv_open, ucnv_toUChars, UConverter, U_SUCCESS, U_ZERO_ERROR,
Expand Down Expand Up @@ -164,65 +166,29 @@ impl FontManagerBackend for FcBackend {
}
}

fn get_platform_font_desc<'a>(&'a self, font: &'a PlatformFontRef) -> &'a CStr {
unsafe fn get_platform_font_desc<'a>(&'a self, font: &'a PlatformFontRef) -> Cow<'a, CStr> {
if let Ok(str) = font.get::<fc::pat::File>(0) {
str
Cow::Borrowed(str)
} else {
cstr!("[unknown]")
Cow::Borrowed(cstr!("[unknown]"))
}
}

unsafe fn get_op_size_rec_and_style_flags(&self, font: &mut Font) {
let mut xfont = match XeTeXFontBase::new(font.font_ref.clone(), 10.0) {
Ok(xfont) => xfont,
Err(_) => return,
};
base_get_op_size_rec_and_style_flags(font);

let size_rec = FontManager::get_op_size(&mut xfont);
if let Some(size_rec) = size_rec {
font.op_size_info.design_size = size_rec.design_size;
if size_rec.sub_family_id != 0
|| size_rec.name_code != 0
|| size_rec.min_size != 0.0
|| size_rec.max_size != 0.0
{
font.op_size_info.sub_family_id = size_rec.sub_family_id;
font.op_size_info.name_code = size_rec.name_code;
font.op_size_info.min_size = size_rec.min_size;
font.op_size_info.max_size = size_rec.max_size;
if font.weight == 0 && font.width == 0 {
let pat = &font.font_ref;
if let Ok(weight) = pat.get::<fc::pat::Weight>(0) {
font.weight = weight as u16;
}
}

let os2_table = xfont.get_font_table(FT_Sfnt_Tag::Os2).cast::<TT_OS2>();
if !os2_table.is_null() {
font.weight = (*os2_table).usWeightClass;
font.width = (*os2_table).usWidthClass;
let sel = (*os2_table).fsSelection;
font.is_reg = (sel & (1 << 6)) != 0;
font.is_bold = (sel & (1 << 5)) != 0;
font.is_italic = (sel & (1 << 0)) != 0;
}

let head_table = xfont.get_font_table(FT_Sfnt_Tag::Head).cast::<TT_Header>();
if !head_table.is_null() {
let ms = (*head_table).Mac_Style;
if (ms & (1 << 0)) != 0 {
font.is_bold = true;
if let Ok(width) = pat.get::<fc::pat::Width>(0) {
font.width = width as u16;
}
if (ms & (1 << 1)) != 0 {
font.is_italic = true;
if let Ok(slant) = pat.get::<fc::pat::Slant>(0) {
font.slant = slant as i16;
}
}

let post_table = xfont
.get_font_table(FT_Sfnt_Tag::Post)
.cast::<TT_Postscript>();
if !post_table.is_null() {
font.slant = (1000.0
* (f64::tan(
RsFix2D((-(*post_table).italic_angle) as Fixed) * std::f64::consts::PI / 180.0,
))) as _;
}
}

unsafe fn search_for_host_platform_fonts(&mut self, maps: &mut FontMaps, name: &CStr) {
Expand Down
Loading

0 comments on commit 04e3c2b

Please sign in to comment.