Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace freetype-rs with freetype (from servo) to match harfbuzz #141

Open
cormacrelf opened this issue Oct 7, 2019 · 2 comments
Open
Labels
good first issue Good for newcomers

Comments

@cormacrelf
Copy link
Collaborator

cormacrelf commented Oct 7, 2019

Probably best to depend on freetype -> servo-freetype-sys only. Replace the freetype-rs dependency, as I recall it had some iffy bugs and panics in its issue tracker and moreover I believe it may cause cargo to complain if you use harfbuzz/the servo freetype crates as well.

Originally posted by @cormacrelf in #136 (comment)

Relevant code that needs to be expanded into plain freetype calls:

thread_local!(static FREETYPE_LIBRARY: RefCell<FreeTypeLibrary> = RefCell::new(FreeTypeLibrary::init().unwrap()));
// This needs to be linked from C++, hence extern "C"
#[no_mangle]
pub unsafe extern "C" fn getFileNameFromCTFont(
mut ctFontRef: CTFontRef,
mut index: *mut u32,
) -> *mut i8 {
let mut ix: i32 = -1;
let mut ret: *mut libc::c_char = 0 as *mut libc::c_char;
let urlRef = CTFontCopyAttribute(ctFontRef, kCTFontURLAttribute) as CFURLRef;
if !urlRef.is_null() {
let url = CFURL::wrap_under_create_rule(urlRef);
if let Some(pathbuf) = url.to_path() {
let ps_name1 = ct_font_get_postscript_name(ctFontRef, kCTFontPostScriptNameKey);
let ps_name = Cow::from(&ps_name1);
let mut i: isize = 0;
while let Ok(face) = FREETYPE_LIBRARY.with(|l| l.borrow().new_face(&pathbuf, i)) {
if let Some(ps_name2) = face.postscript_name() {
if ps_name2 == ps_name {
ix = i as i32;
break;
}
}
i += 1;
}

Should be 'good first issue' but I can't tag. Also requires a mac to test.

@xcaptain
Copy link

xcaptain commented Oct 8, 2019

Can you be more specific about how to fix it? I can give it a try if it's really an easy issue and you can guide me :)

@cormacrelf cormacrelf added the good first issue Good for newcomers label Oct 8, 2019
@cormacrelf
Copy link
Collaborator Author

cormacrelf commented Oct 9, 2019

Not sure how much more specific I can be without doing it myself... Lines 871, 889-90 needs to do the same thing, except using raw freetype calls. It:

  1. creates a FreeType library object technically line 871
  2. Uses it to get a typeface from a filesystem path and an index (i)
  3. Gets its postscript name (which includes Bold, etc) as a rust-comparable string so the code can cycle through the fonts at that path to find the one with the right postscript name. You may need to create a Cstr if FreeType gives you a null-terminated string.

https://docs.rs/freetype

Actually it's even easier. You're basically reverting this change:

46ca29c#diff-4f48babb53558bc10105fee1eb626783L1515-L1582 for these lines

pub unsafe extern "C" fn getFileNameFromCTFont(
mut ctFontRef: CTFontRef,
mut index: *mut uint32_t,
) -> *mut libc::c_char {
let mut ret: *mut libc::c_char = 0 as *mut libc::c_char;
let mut url: CFURLRef = 0 as CFURLRef;
url = CTFontCopyAttribute(ctFontRef, kCTFontURLAttribute) as CFURLRef;
if !url.is_null() {
let mut pathname: [UInt8; 1024] = [0; 1024];
if CFURLGetFileSystemRepresentation(
url,
1i32 as Boolean,
pathname.as_mut_ptr(),
1024i32 as CFIndex,
) != 0
{
let mut error: FT_Error = 0;
let mut face: FT_Face = 0 as *mut FT_FaceRec_;
*index = 0i32 as uint32_t;
if gFreeTypeLibrary.is_null() {
error = FT_Init_FreeType(&mut gFreeTypeLibrary);
if error != 0 {
panic!("FreeType initialization failed; error {}\x00", error);
}
}
error = FT_New_Face(
gFreeTypeLibrary,
pathname.as_mut_ptr() as *mut libc::c_char,
0i32 as FT_Long,
&mut face,
);
if error == 0 {
if (*face).num_faces > 1i32 as libc::c_long {
let mut num_faces: libc::c_int = (*face).num_faces as libc::c_int;
let mut ps_name1: *mut libc::c_char =
getNameFromCTFont(ctFontRef, kCTFontPostScriptNameKey);
let mut i: libc::c_int = 0;
*index = -1i32 as uint32_t;
FT_Done_Face(face);
i = 0i32;
while i < num_faces {
error = FT_New_Face(
gFreeTypeLibrary,
pathname.as_mut_ptr() as *mut libc::c_char,
i as FT_Long,
&mut face,
);
if error == 0 {
let mut ps_name2: *const libc::c_char = FT_Get_Postscript_Name(face);
if streq_ptr(ps_name1, ps_name2) {
*index = i as uint32_t;
break;
} else {
FT_Done_Face(face);
}
}
i += 1
}
free(ps_name1 as *mut libc::c_void);
}
}
if *index != -1i32 as libc::c_uint {
ret = strdup(pathname.as_mut_ptr() as *mut libc::c_char)
}
}
CFRelease(url as CFTypeRef);
}
return ret;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants