mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-18 13:55:23 -05:00
Add ffi-util crate and use in fontconfig wrapper
This cleans up and fixes the C-type wrapping for fontconfig.
This commit is contained in:
parent
44c6171bc0
commit
a00970c9a8
7 changed files with 160 additions and 109 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -230,6 +230,10 @@ dependencies = [
|
|||
"pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ffi-util"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.1.10"
|
||||
|
@ -247,6 +251,7 @@ dependencies = [
|
|||
"core-graphics 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-text 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ffi-util 0.1.0",
|
||||
"freetype-rs 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-fontconfig 0.2.0 (git+https://github.com/jwilm/rust-fontconfig)",
|
||||
|
|
6
ffi-util/Cargo.toml
Normal file
6
ffi-util/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "ffi-util"
|
||||
version = "0.1.0"
|
||||
authors = ["Joe Wilm <joe@jwilm.com>"]
|
||||
|
||||
[dependencies]
|
102
ffi-util/src/lib.rs
Normal file
102
ffi-util/src/lib.rs
Normal file
|
@ -0,0 +1,102 @@
|
|||
// Copyright 2011 Google Inc.
|
||||
// 2013 Jack Lloyd
|
||||
// 2013-2014 Steven Fackler
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
use std::cell::UnsafeCell;
|
||||
|
||||
/// This is intended to be used as the inner type for `FooRef` types converted from raw C pointers.
|
||||
/// It has an `UnsafeCell` internally to inform the compiler about aliasability and doesn't
|
||||
/// implement `Copy`, so it can't be dereferenced.
|
||||
pub struct Opaque(UnsafeCell<()>);
|
||||
|
||||
/// A type implemented by wrappers over foreign types.
|
||||
///
|
||||
/// This should not be implemented by anything outside of this crate; new methods may be added at
|
||||
/// any time.
|
||||
pub trait ForeignType: Sized {
|
||||
/// The raw C type.
|
||||
type CType;
|
||||
|
||||
/// The type representing a reference to this type.
|
||||
type Ref: ForeignTypeRef<CType = Self::CType>;
|
||||
|
||||
/// Constructs an instance of this type from its raw type.
|
||||
unsafe fn from_ptr(ptr: *mut Self::CType) -> Self;
|
||||
}
|
||||
|
||||
/// A trait implemented by types which reference borrowed foreign types.
|
||||
///
|
||||
/// This should not be implemented by anything outside of this crate; new methods may be added at
|
||||
/// any time.
|
||||
pub trait ForeignTypeRef: Sized {
|
||||
/// The raw C type.
|
||||
type CType;
|
||||
|
||||
/// Constructs a shared instance of this type from its raw type.
|
||||
unsafe fn from_ptr<'a>(ptr: *mut Self::CType) -> &'a Self {
|
||||
&*(ptr as *mut _)
|
||||
}
|
||||
|
||||
/// Constructs a mutable reference of this type from its raw type.
|
||||
unsafe fn from_ptr_mut<'a>(ptr: *mut Self::CType) -> &'a mut Self {
|
||||
&mut *(ptr as *mut _)
|
||||
}
|
||||
|
||||
/// Returns a raw pointer to the wrapped value.
|
||||
fn as_ptr(&self) -> *mut Self::CType {
|
||||
self as *const _ as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! ffi_type {
|
||||
($n:ident, $r:ident, $c:path, $d:path) => {
|
||||
pub struct $n(*mut $c);
|
||||
|
||||
impl $crate::ForeignType for $n {
|
||||
type CType = $c;
|
||||
type Ref = $r;
|
||||
|
||||
unsafe fn from_ptr(ptr: *mut $c) -> $n {
|
||||
$n(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for $n {
|
||||
fn drop(&mut self) {
|
||||
unsafe { $d(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::Deref for $n {
|
||||
type Target = $r;
|
||||
|
||||
fn deref(&self) -> &$r {
|
||||
unsafe { $crate::ForeignTypeRef::from_ptr(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::DerefMut for $n {
|
||||
fn deref_mut(&mut self) -> &mut $r {
|
||||
unsafe { $crate::ForeignTypeRef::from_ptr_mut(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct $r($crate::Opaque);
|
||||
|
||||
impl $crate::ForeignTypeRef for $r {
|
||||
type CType = $c;
|
||||
}
|
||||
}
|
||||
}
|
5
font/Cargo.lock
generated
5
font/Cargo.lock
generated
|
@ -7,6 +7,7 @@ dependencies = [
|
|||
"core-graphics 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-text 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ffi-util 0.1.0",
|
||||
"freetype-rs 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-fontconfig 0.2.0 (git+https://github.com/jwilm/rust-fontconfig)",
|
||||
|
@ -75,6 +76,10 @@ dependencies = [
|
|||
"pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ffi-util"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "freetype-rs"
|
||||
version = "0.9.0"
|
||||
|
|
|
@ -8,6 +8,7 @@ license = "Apache-2.0"
|
|||
[dependencies]
|
||||
euclid = "0.6.8"
|
||||
libc = "0.2.11"
|
||||
ffi-util = { path = "../ffi-util" }
|
||||
|
||||
[target.'cfg(not(target_os = "macos"))'.dependencies]
|
||||
servo-fontconfig = { git = "https://github.com/jwilm/rust-fontconfig" }
|
||||
|
|
|
@ -20,12 +20,14 @@ mod fc {
|
|||
use std::ptr;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::str;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::ops::Deref;
|
||||
|
||||
use ffi_util::ForeignTypeRef;
|
||||
|
||||
use libc::{c_char, c_int};
|
||||
use fontconfig::fontconfig as ffi;
|
||||
|
||||
use self::ffi::{FcConfigGetCurrent, FcConfigGetFonts};
|
||||
use self::ffi::{FcConfigGetCurrent, FcConfigGetFonts, FcSetSystem, FcSetApplication};
|
||||
use self::ffi::{FcPatternGetString, FcPatternCreate, FcPatternAddString};
|
||||
use self::ffi::{FcPatternGetInteger};
|
||||
use self::ffi::{FcObjectSetCreate, FcObjectSetAdd};
|
||||
|
@ -33,15 +35,6 @@ mod fc {
|
|||
use self::ffi::{FcChar8, FcConfig, FcPattern, FcFontSet, FcObjectSet};
|
||||
use self::ffi::{FcFontSetDestroy, FcPatternDestroy, FcObjectSetDestroy, FcConfigDestroy};
|
||||
|
||||
/// FcConfig - Font Configuration
|
||||
pub struct Config(*mut FcConfig);
|
||||
|
||||
/// FcFontSet
|
||||
pub struct FontSet(*mut FcFontSet);
|
||||
|
||||
/// FcFontSet reference
|
||||
pub struct FontSetRef(*mut FcFontSet);
|
||||
|
||||
/// Iterator over a font set
|
||||
pub struct FontSetIter<'a> {
|
||||
font_set: &'a FontSetRef,
|
||||
|
@ -49,51 +42,10 @@ mod fc {
|
|||
current: usize,
|
||||
}
|
||||
|
||||
macro_rules! ref_type {
|
||||
($($owned:ty => $refty:ty),*) => {
|
||||
$(
|
||||
impl Deref for $owned {
|
||||
type Target = $refty;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe {
|
||||
&*(self.0 as *mut _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for $owned {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe {
|
||||
&mut *(self.0 as *mut _)
|
||||
}
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
/// FcPattern
|
||||
pub struct Pattern(*mut FcPattern);
|
||||
|
||||
/// FcObjectSet
|
||||
pub struct ObjectSet(*mut FcObjectSet);
|
||||
|
||||
/// FcObjectSet reference
|
||||
pub struct ObjectSetRef(*mut FcObjectSet);
|
||||
|
||||
ref_type! {
|
||||
ObjectSet => ObjectSetRef,
|
||||
Pattern => PatternRef,
|
||||
FontSet => FontSetRef
|
||||
}
|
||||
|
||||
impl Drop for ObjectSet {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
FcObjectSetDestroy(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
ffi_type!(Pattern, PatternRef, FcPattern, FcPatternDestroy);
|
||||
ffi_type!(Config, ConfigRef, FcConfig, FcConfigDestroy);
|
||||
ffi_type!(ObjectSet, ObjectSetRef, FcObjectSet, FcObjectSetDestroy);
|
||||
ffi_type!(FontSet, FontSetRef, FcFontSet, FcFontSetDestroy);
|
||||
|
||||
impl ObjectSet {
|
||||
pub fn new() -> ObjectSet {
|
||||
|
@ -103,11 +55,10 @@ mod fc {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl ObjectSetRef {
|
||||
fn add(&mut self, property: &[u8]) {
|
||||
unsafe {
|
||||
FcObjectSetAdd(self.0, property.as_ptr() as *mut c_char);
|
||||
FcObjectSetAdd(self.as_ptr(), property.as_ptr() as *mut c_char);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,21 +95,11 @@ mod fc {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for Pattern {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
FcPatternDestroy(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// FcPattern reference
|
||||
pub struct PatternRef(*mut FcPattern);
|
||||
|
||||
/// Available font sets
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum SetName {
|
||||
System = 0,
|
||||
Application = 1,
|
||||
System = FcSetSystem as isize,
|
||||
Application = FcSetApplication as isize,
|
||||
}
|
||||
|
||||
pub unsafe fn char8_to_string(fc_str: *mut FcChar8) -> String {
|
||||
|
@ -173,7 +114,7 @@ mod fc {
|
|||
let mut format: *mut FcChar8 = ptr::null_mut();
|
||||
|
||||
let result = FcPatternGetString(
|
||||
self.0,
|
||||
self.as_ptr(),
|
||||
$property.as_ptr() as *mut c_char,
|
||||
id as c_int,
|
||||
&mut format
|
||||
|
@ -197,7 +138,7 @@ mod fc {
|
|||
let mut index = 0 as c_int;
|
||||
unsafe {
|
||||
let result = FcPatternGetInteger(
|
||||
self.0,
|
||||
self.as_ptr(),
|
||||
$property.as_ptr() as *mut c_char,
|
||||
id as c_int,
|
||||
&mut index
|
||||
|
@ -228,7 +169,7 @@ mod fc {
|
|||
let value = value.as_ptr();
|
||||
|
||||
FcPatternAddString(
|
||||
self.0,
|
||||
self.as_ptr(),
|
||||
object.as_ptr() as *mut c_char,
|
||||
value as *mut FcChar8
|
||||
) == 1
|
||||
|
@ -255,11 +196,11 @@ mod fc {
|
|||
type IntoIter = FontSetIter<'a>;
|
||||
fn into_iter(self) -> FontSetIter<'a> {
|
||||
let num_fonts = unsafe {
|
||||
(*self.0).nfont as isize
|
||||
(*self.as_ptr()).nfont as isize
|
||||
};
|
||||
|
||||
FontSetIter {
|
||||
font_set: unsafe { &*(self.0 as *mut _) },
|
||||
font_set: self.deref(),
|
||||
num_fonts: num_fonts as _,
|
||||
current: 0,
|
||||
}
|
||||
|
@ -271,7 +212,7 @@ mod fc {
|
|||
type IntoIter = FontSetIter<'a>;
|
||||
fn into_iter(self) -> FontSetIter<'a> {
|
||||
let num_fonts = unsafe {
|
||||
(*self.0).nfont as isize
|
||||
(*self.as_ptr()).nfont as isize
|
||||
};
|
||||
|
||||
FontSetIter {
|
||||
|
@ -290,8 +231,8 @@ mod fc {
|
|||
None
|
||||
} else {
|
||||
let pattern = unsafe {
|
||||
let ptr = *(*self.font_set.0).fonts.offset(self.current as isize);
|
||||
&*(ptr as *mut _)
|
||||
let ptr = *(*self.font_set.as_ptr()).fonts.offset(self.current as isize);
|
||||
PatternRef::from_ptr(ptr)
|
||||
};
|
||||
|
||||
self.current += 1;
|
||||
|
@ -302,18 +243,18 @@ mod fc {
|
|||
|
||||
impl FontSet {
|
||||
pub fn list(
|
||||
config: &Config,
|
||||
config: &ConfigRef,
|
||||
source: &mut FontSetRef,
|
||||
pattern: &PatternRef,
|
||||
objects: &ObjectSetRef
|
||||
) -> FontSet {
|
||||
let raw = unsafe {
|
||||
FcFontSetList(
|
||||
config.0,
|
||||
&mut source.0,
|
||||
config.as_ptr(),
|
||||
&mut source.as_ptr(),
|
||||
1 /* nsets */,
|
||||
pattern.0,
|
||||
objects.0
|
||||
pattern.as_ptr(),
|
||||
objects.as_ptr(),
|
||||
)
|
||||
};
|
||||
FontSet(raw)
|
||||
|
@ -322,34 +263,20 @@ mod fc {
|
|||
|
||||
impl Config {
|
||||
/// Get the current configuration
|
||||
pub fn get_current() -> Config {
|
||||
Config(unsafe { FcConfigGetCurrent() })
|
||||
pub fn get_current() -> &'static ConfigRef {
|
||||
unsafe {
|
||||
ConfigRef::from_ptr(FcConfigGetCurrent())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigRef {
|
||||
/// Returns one of the two sets of fonts from the configuration as
|
||||
/// specified by `set`.
|
||||
pub fn get_fonts<'a>(&'a self, set: SetName) -> &'a FontSetRef {
|
||||
unsafe {
|
||||
let ptr = FcConfigGetFonts(self.0, set as u32);
|
||||
&*(ptr as *mut _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FontSet {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
FcFontSetDestroy(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Config {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
if self.0 != FcConfigGetCurrent() {
|
||||
FcConfigDestroy(self.0)
|
||||
}
|
||||
let ptr = FcConfigGetFonts(self.as_ptr(), set as u32);
|
||||
FontSetRef::from_ptr(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -363,9 +290,11 @@ fn list_families() -> Vec<String> {
|
|||
for font in font_set {
|
||||
if let Some(format) = font.fontformat(0) {
|
||||
if format == "TrueType" || format == "CFF" {
|
||||
let id = 0;
|
||||
while let Some(family) = font.family(id) {
|
||||
families.push(family);
|
||||
for id in 0.. {
|
||||
match font.family(id) {
|
||||
Some(family) => families.push(family),
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,9 @@ extern crate core_graphics;
|
|||
extern crate euclid;
|
||||
extern crate libc;
|
||||
|
||||
#[macro_use]
|
||||
extern crate ffi_util;
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::atomic::{AtomicU32, ATOMIC_U32_INIT, Ordering};
|
||||
|
||||
|
|
Loading…
Reference in a new issue