Skip to content

Commit

Permalink
Auto merge of #192 - Be-ing:dlopen, r=jdm
Browse files Browse the repository at this point in the history
switch to yeslogic-fontconfig-sys instead of servo-fontconfig

servo-fontconfig statically links a vendored fontconfig library if fontconfig is not found by pkgconfig. Using a vendored fontconfig
library instead of the system fontconfig library doesn't actually work well though:
slint-ui/slint#88
Building a vendored copy of fontconfig is also problematic because fontconfig has a lot of C dependencies, which makes it difficult to cross compile the vendored copy of fontconfig:

```
$ pkg-config fontconfig --static --libs
-lfontconfig -lfreetype -lz -lbz2 -lpng16 -lm -lm -lz -lharfbuzz -lm -lglib-2.0 -lm -lpcre -lsysprof-capture-4 -pthread -lgraphite2 -lbrotlidec -lbrotlicommon -lxml2 -lz -llzma -lm
```

Instead of using a vendored copy, with
yeslogic/fontconfig-rs#12
yeslogic-fontconfig-sys will have a Cargo feature to dlopen fontconfig at runtime instead of linking it at build time. This is exposed in font-kit with the new source-fontconfig-dlopen feature, which is disabled by default. This feature makes it considerably easier to cross compile by avoiding the need to cross compile fontconfig and all its dependencies.
  • Loading branch information
bors-servo authored Mar 28, 2022
2 parents c359470 + 4130e14 commit 75f99cf
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 24 deletions.
11 changes: 6 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "font-kit"
version = "0.10.1"
version = "0.11.0"
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
description = "A cross-platform font loading library"
license = "MIT/Apache-2.0"
Expand All @@ -14,7 +14,8 @@ edition = "2018"
default = ["source"]
loader-freetype = ["freetype"]
loader-freetype-default = ["loader-freetype"]
source-fontconfig = ["servo-fontconfig"]
source-fontconfig = ["yeslogic-fontconfig-sys"]
source-fontconfig-dlopen = ["yeslogic-fontconfig-sys/dlopen"]
source-fontconfig-default = ["source-fontconfig"]
source = []

Expand All @@ -32,8 +33,8 @@ pathfinder_simd = "0.5.1"
version = "0.7"
optional = true

[dependencies.servo-fontconfig]
version = "0.5"
[dependencies.yeslogic-fontconfig-sys]
version = "3.0.0"
optional = true

[dev-dependencies]
Expand All @@ -58,7 +59,7 @@ core-text = "19.1.0"
freetype = "0.7"

[target.'cfg(not(any(target_family = "windows", target_os = "macos", target_os = "ios", target_arch = "wasm32")))'.dependencies]
servo-fontconfig = "0.5"
yeslogic-fontconfig-sys = "3.0.0"

[target.'cfg(not(any(target_arch = "wasm32", target_family = "windows", target_os = "android")))'.dependencies]
dirs-next = "2.0"
Expand Down
7 changes: 7 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn main() {
println!("cargo:rerun-if-env-changed=RUST_FONTCONFIG_DLOPEN");
let dlopen = std::env::var("RUST_FONTCONFIG_DLOPEN").is_ok();
if dlopen {
println!("cargo:rustc-cfg=feature=\"source-fontconfig-dlopen\"");
}
}
2 changes: 1 addition & 1 deletion src/loaders/freetype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1198,7 +1198,7 @@ impl FtFixedToF32 for RectI {
type Output = RectF;
#[inline]
fn ft_fixed_26_6_to_f32(self) -> RectF {
(self.to_f32() * (1.0 / 64.0))
self.to_f32() * (1.0 / 64.0)
}
}

Expand Down
145 changes: 127 additions & 18 deletions src/sources/fontconfig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,13 @@ impl Source for FontconfigSource {
mod fc {
#![allow(dead_code)]

use fontconfig::fontconfig as ffi;
use fontconfig_sys as ffi;
use fontconfig_sys::ffi_dispatch;

#[cfg(feature = "source-fontconfig-dlopen")]
use ffi::statics::LIB;
#[cfg(not(feature = "source-fontconfig-dlopen"))]
use ffi::*;

use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_uchar};
Expand Down Expand Up @@ -308,7 +314,11 @@ mod fc {
pub fn new() -> Self {
unsafe {
Config {
d: ffi::FcInitLoadConfigAndFonts(),
d: ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcInitLoadConfigAndFonts,
),
}
}
}
Expand All @@ -317,7 +327,12 @@ mod fc {
impl Drop for Config {
fn drop(&mut self) {
unsafe {
ffi::FcConfigDestroy(self.d);
ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcConfigDestroy,
self.d
);
}
}
}
Expand All @@ -337,23 +352,39 @@ mod fc {

// FcPatternCreate
pub fn new() -> Self {
unsafe { Pattern::from_ptr(ffi::FcPatternCreate()) }
unsafe {
Pattern::from_ptr(ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcPatternCreate,
))
}
}

// FcNameParse
pub fn from_name(name: &str) -> Self {
let c_name = CString::new(name).unwrap();
unsafe { Pattern::from_ptr(ffi::FcNameParse(c_name.as_ptr() as *mut c_uchar)) }
unsafe {
Pattern::from_ptr(ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcNameParse,
c_name.as_ptr() as *mut c_uchar
))
}
}

// FcPatternAddString
pub fn push_string(&mut self, object: Object, value: String) {
unsafe {
let c_string = CString::new(value).unwrap();
ffi::FcPatternAddString(
ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcPatternAddString,
self.d,
object.as_ptr(),
c_string.as_ptr() as *const c_uchar,
c_string.as_ptr() as *const c_uchar
);

// We have to keep this string, because `FcPattern` has a pointer to it now.
Expand All @@ -364,21 +395,44 @@ mod fc {
// FcConfigSubstitute
pub fn config_substitute(&mut self, match_kind: MatchKind) {
unsafe {
ffi::FcConfigSubstitute(ptr::null_mut(), self.d, match_kind.to_u32());
ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcConfigSubstitute,
ptr::null_mut(),
self.d,
match_kind.to_u32()
);
}
}

// FcDefaultSubstitute
pub fn default_substitute(&mut self) {
unsafe {
ffi::FcDefaultSubstitute(self.d);
ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcDefaultSubstitute,
self.d
);
}
}

// FcFontSort
pub fn sorted(&self, config: &Config) -> Result<FontSet, Error> {
let mut res = ffi::FcResultMatch;
let d = unsafe { ffi::FcFontSort(config.d, self.d, 1, ptr::null_mut(), &mut res) };
let d = unsafe {
ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcFontSort,
config.d,
self.d,
1,
ptr::null_mut(),
&mut res
)
};

match res {
ffi::FcResultMatch => Ok(FontSet { d, idx: 0 }),
Expand All @@ -391,7 +445,16 @@ mod fc {

// FcFontList
pub fn list(&self, config: &Config, set: ObjectSet) -> Result<FontSet, Error> {
let d = unsafe { ffi::FcFontList(config.d, self.d, set.d) };
let d = unsafe {
ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcFontList,
config.d,
self.d,
set.d
)
};
if !d.is_null() {
Ok(FontSet { d, idx: 0 })
} else {
Expand All @@ -403,7 +466,14 @@ mod fc {
impl Drop for Pattern {
#[inline]
fn drop(&mut self) {
unsafe { ffi::FcPatternDestroy(self.d) }
unsafe {
ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcPatternDestroy,
self.d
)
}
}
}

Expand All @@ -417,7 +487,15 @@ mod fc {
pub fn get_string(&self, object: Object) -> Option<String> {
unsafe {
let mut string = ptr::null_mut();
let res = ffi::FcPatternGetString(self.d, object.as_ptr(), 0, &mut string);
let res = ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcPatternGetString,
self.d,
object.as_ptr(),
0,
&mut string
);
if res != ffi::FcResultMatch {
return None;
}
Expand All @@ -437,7 +515,15 @@ mod fc {
pub fn get_integer(&self, object: Object) -> Option<i32> {
unsafe {
let mut integer = 0;
let res = ffi::FcPatternGetInteger(self.d, object.as_ptr(), 0, &mut integer);
let res = ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcPatternGetInteger,
self.d,
object.as_ptr(),
0,
&mut integer
);
if res != ffi::FcResultMatch {
return None;
}
Expand Down Expand Up @@ -484,7 +570,14 @@ mod fc {

impl Drop for FontSet {
fn drop(&mut self) {
unsafe { ffi::FcFontSetDestroy(self.d) }
unsafe {
ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcFontSetDestroy,
self.d
)
}
}
}

Expand All @@ -497,7 +590,7 @@ mod fc {
pub fn new() -> Self {
unsafe {
ObjectSet {
d: ffi::FcObjectSetCreate(),
d: ffi_dispatch!(feature = "source-fontconfig-dlopen", LIB, FcObjectSetCreate,),
}
}
}
Expand All @@ -507,14 +600,30 @@ mod fc {
unsafe {
// Returns `false` if the property name cannot be inserted
// into the set (due to allocation failure).
assert_eq!(ffi::FcObjectSetAdd(self.d, object.as_ptr()), 1);
assert_eq!(
ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcObjectSetAdd,
self.d,
object.as_ptr()
),
1
);
}
}
}

impl Drop for ObjectSet {
fn drop(&mut self) {
unsafe { ffi::FcObjectSetDestroy(self.d) }
unsafe {
ffi_dispatch!(
feature = "source-fontconfig-dlopen",
LIB,
FcObjectSetDestroy,
self.d
)
}
}
}
}

0 comments on commit 75f99cf

Please sign in to comment.