Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 43 additions & 17 deletions src/font_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::ptr;
use std::slice;
use std::sync::Arc;
use winapi::ctypes::c_void;
use winapi::shared::winerror::S_OK;
use winapi::um::dwrite::{IDWriteFontFace, IDWriteFontFile, IDWriteFontFileStream};
use winapi::um::dwrite::{IDWriteFontFileLoader, IDWriteLocalFontFileLoader};
use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE, DWRITE_FONT_FILE_TYPE_UNKNOWN};
Expand Down Expand Up @@ -147,68 +148,91 @@ impl FontFile {
(*self.native.get()).clone()
}

#[deprecated(note = "Use `font_file_bytes` instead.")]
pub fn get_font_file_bytes(&self) -> Vec<u8> {
self.font_file_bytes().unwrap()
}

// This is a helper to read the contents of this FontFile,
// without requiring callers to deal with loaders, keys,
// or streams.
pub fn get_font_file_bytes(&self) -> Vec<u8> {
pub fn font_file_bytes(&self) -> Result<Vec<u8>, HRESULT> {
unsafe {
let mut ref_key: *const c_void = ptr::null();
let mut ref_key_size: u32 = 0;
let hr = (*self.native.get()).GetReferenceKey(&mut ref_key, &mut ref_key_size);
assert!(hr == 0);
if hr != S_OK {
return Err(hr);
}

let mut loader: *mut IDWriteFontFileLoader = ptr::null_mut();
let hr = (*self.native.get()).GetLoader(&mut loader);
assert!(hr == 0);
if hr != S_OK {
return Err(hr);
}
let loader = ComPtr::from_raw(loader);

let mut stream: *mut IDWriteFontFileStream = ptr::null_mut();
let hr = loader.CreateStreamFromKey(ref_key, ref_key_size, &mut stream);
assert!(hr == 0);
if hr != S_OK {
return Err(hr);
}
let stream = ComPtr::from_raw(stream);

let mut file_size: u64 = 0;
let hr = stream.GetFileSize(&mut file_size);
assert!(hr == 0);
if hr != S_OK {
return Err(hr);
}

let mut fragment_start: *const c_void = ptr::null();
let mut fragment_context: *mut c_void = ptr::null_mut();
let hr =
stream.ReadFileFragment(&mut fragment_start, 0, file_size, &mut fragment_context);
assert!(hr == 0);
if hr != S_OK {
return Err(hr);
}

let in_ptr = slice::from_raw_parts(fragment_start as *const u8, file_size as usize);
let bytes = in_ptr.to_vec();

stream.ReleaseFileFragment(fragment_context);

bytes
Ok(bytes)
}
}

#[deprecated(note = "Use `font_file_path` instead.")]
pub fn get_font_file_path(&self) -> Option<PathBuf> {
self.font_file_path().ok()
}

// This is a helper to get the path of a font file,
// without requiring callers to deal with loaders.
pub fn get_font_file_path(&self) -> Option<PathBuf> {
pub fn font_file_path(&self) -> Result<PathBuf, HRESULT> {
unsafe {
let mut ref_key: *const c_void = ptr::null();
let mut ref_key_size: u32 = 0;
let hr = (*self.native.get()).GetReferenceKey(&mut ref_key, &mut ref_key_size);
assert!(hr == 0);
if hr != S_OK {
return Err(hr);
}

let mut loader: *mut IDWriteFontFileLoader = ptr::null_mut();
let hr = (*self.native.get()).GetLoader(&mut loader);
assert!(hr == 0);
if hr != S_OK {
return Err(hr);
}
let loader = ComPtr::from_raw(loader);

let local_loader: ComPtr<IDWriteLocalFontFileLoader> = match loader.cast() {
Ok(local_loader) => local_loader,
Err(_) => return None,
};
let local_loader: ComPtr<IDWriteLocalFontFileLoader> = loader.cast()?;

let mut file_path_len = 0;
let hr =
local_loader.GetFilePathLengthFromKey(ref_key, ref_key_size, &mut file_path_len);
assert_eq!(hr, 0);
if hr != S_OK {
return Err(hr);
}

let mut file_path_buf = vec![0; file_path_len as usize + 1];
let hr = local_loader.GetFilePathFromKey(
Expand All @@ -217,13 +241,15 @@ impl FontFile {
file_path_buf.as_mut_ptr(),
file_path_len + 1,
);
assert_eq!(hr, 0);
if hr != S_OK {
return Err(hr);
}

if let Some(&0) = file_path_buf.last() {
file_path_buf.pop();
}

Some(PathBuf::from(OsString::from_wide(&file_path_buf)))
Ok(PathBuf::from(OsString::from_wide(&file_path_buf)))
}
}

Expand Down