Skip to content

Commit

Permalink
switch to yeslogic-fontconfig-sys
Browse files Browse the repository at this point in the history
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. The feature can be enabled by setting the
RUST_FONTCONFIG_DLOPEN environment variable to avoid needing to
propagate the Cargo feature all the way through downstream
Cargo.toml's. This feature makes it considerably easier to cross
compile by avoiding the need to cross compile fontconfig and all its
dependencies.
  • Loading branch information
Be-ing committed Mar 28, 2022
1 parent 9d657cc commit 4130e14
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 23 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 <[email protected]>"]
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\"");
}
}
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 4130e14

Please sign in to comment.